From 7fe95980d7c715b044205e442d111367a347fceb Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Fri, 6 Jun 2025 00:51:03 -0700 Subject: [PATCH] VGMStream: Updated libvgmstream code base Updated VGMStream to r2023-16-gb2fc214a Signed-off-by: Christopher Snowhill --- .../libvgmstream.xcodeproj/project.pbxproj | 24 +++-- .../vgmstream/vgmstream/src/base/render.c | 2 +- .../vgmstream/src/coding/atrac9_decoder.c | 2 +- .../src/coding/ffmpeg_decoder_utils.c | 12 +-- .../vgmstream/src/coding/imuse_decoder.c | 4 +- Frameworks/vgmstream/vgmstream/src/formats.c | 16 ++- .../vgmstream/vgmstream/src/libvgmstream.h | 2 +- .../vgmstream/vgmstream/src/meta/bfwav.c | 70 ------------- .../vgmstream/vgmstream/src/meta/ffmpeg.c | 53 ---------- .../vgmstream/vgmstream/src/meta/fsb_keys.h | 1 + Frameworks/vgmstream/vgmstream/src/meta/ivb.c | 59 +++++++++++ .../vgmstream/src/meta/ivb_streamfile.h | 21 ++++ .../vgmstream/vgmstream/src/meta/meta.h | 12 +-- .../vgmstream/vgmstream/src/meta/mn_str.c | 81 ---------------- .../vgmstream/src/meta/ngc_dsp_std.c | 32 ------ Frameworks/vgmstream/vgmstream/src/meta/nub.c | 17 +++- .../vgmstream/vgmstream/src/meta/ogg_vorbis.c | 10 +- .../vgmstream/vgmstream/src/meta/rwar.c | 72 ++++++++++++++ .../vgmstream/vgmstream/src/meta/sps_n1.c | 73 +++++++++----- .../vgmstream/vgmstream/src/meta/swar.c | 97 +++++++++++++++++++ .../vgmstream/vgmstream/src/meta/txth.c | 22 ++++- .../vgmstream/src/meta/txtp_process.c | 2 +- .../vgmstream/vgmstream/src/meta/ubi_sb.c | 6 +- Frameworks/vgmstream/vgmstream/src/meta/xwb.c | 25 ++--- .../vgmstream/vgmstream/src/meta/xwb_xsb.h | 53 +++++----- .../vgmstream/vgmstream/src/meta/zwdsp.c | 93 ------------------ .../vgmstream/vgmstream/src/util/meta_utils.c | 5 + .../vgmstream/vgmstream/src/util/meta_utils.h | 1 + .../vgmstream/vgmstream/src/util/sf_utils.c | 26 ++++- .../vgmstream/vgmstream/src/util/sf_utils.h | 9 +- .../vgmstream/vgmstream/src/vgmstream.h | 8 +- .../vgmstream/vgmstream/src/vgmstream_init.c | 7 +- .../vgmstream/vgmstream/src/vgmstream_types.h | 5 +- 33 files changed, 471 insertions(+), 451 deletions(-) create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ivb.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ivb_streamfile.h delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/mn_str.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/rwar.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/swar.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 4db3f0106..ca52d535d 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -518,7 +518,6 @@ 836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */; }; 836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5D18BDC2180095E648 /* maxis_xa.c */; }; 836F6F9A18BDC2190095E648 /* meta.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6E5E18BDC2180095E648 /* meta.h */; }; - 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5F18BDC2180095E648 /* mn_str.c */; }; 836F6F9C18BDC2190095E648 /* mp4.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6018BDC2180095E648 /* mp4.c */; }; 836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6218BDC2180095E648 /* mus_acm.c */; }; 836F6F9F18BDC2190095E648 /* musc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6318BDC2180095E648 /* musc.c */; }; @@ -623,7 +622,6 @@ 836F704F18BDC2190095E648 /* xwb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1318BDC2190095E648 /* xwb.c */; }; 836F705018BDC2190095E648 /* ydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1418BDC2190095E648 /* ydsp.c */; }; 836F705118BDC2190095E648 /* zsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1518BDC2190095E648 /* zsd.c */; }; - 836F705218BDC2190095E648 /* zwdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1618BDC2190095E648 /* zwdsp.c */; }; 836F705318BDC2190095E648 /* streamfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1718BDC2190095E648 /* streamfile.c */; }; 836F705418BDC2190095E648 /* streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1818BDC2190095E648 /* streamfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; 836F705518BDC2190095E648 /* streamtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1918BDC2190095E648 /* streamtypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -779,6 +777,10 @@ 83B8FE2F2D5AB2F4005854C1 /* xwb_konami.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B8FE2E2D5AB2F4005854C1 /* xwb_konami.c */; }; 83B8FE312D5AB421005854C1 /* undefind.c in Sources */ = {isa = PBXBuildFile; fileRef = 83B8FE302D5AB421005854C1 /* undefind.c */; }; 83BAFB6C19F45EB3005DAB60 /* bfstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BAFB6B19F45EB3005DAB60 /* bfstm.c */; }; + 83BB84012DF2D049002077FC /* swar.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BB84002DF2D049002077FC /* swar.c */; }; + 83BB84032DF2D125002077FC /* rwar.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BB84022DF2D125002077FC /* rwar.c */; }; + 83BB84062DF2D1C2002077FC /* ivb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BB84042DF2D1C2002077FC /* ivb.c */; }; + 83BB84072DF2D1C2002077FC /* ivb_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BB84052DF2D1C2002077FC /* ivb_streamfile.h */; }; 83C0C75D2AA435C60056AFD8 /* squeak.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75C2AA435C60056AFD8 /* squeak.c */; }; 83C0C7602AA436370056AFD8 /* layout_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75E2AA436370056AFD8 /* layout_utils.c */; }; 83C0C7612AA436370056AFD8 /* layout_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C0C75F2AA436370056AFD8 /* layout_utils.h */; }; @@ -1475,7 +1477,6 @@ 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mattel_hyperscan.c; sourceTree = ""; }; 836F6E5D18BDC2180095E648 /* maxis_xa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = maxis_xa.c; sourceTree = ""; }; 836F6E5E18BDC2180095E648 /* meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = meta.h; sourceTree = ""; }; - 836F6E5F18BDC2180095E648 /* mn_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mn_str.c; sourceTree = ""; }; 836F6E6018BDC2180095E648 /* mp4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mp4.c; sourceTree = ""; }; 836F6E6218BDC2180095E648 /* mus_acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm.c; sourceTree = ""; }; 836F6E6318BDC2180095E648 /* musc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = musc.c; sourceTree = ""; }; @@ -1580,7 +1581,6 @@ 836F6F1318BDC2190095E648 /* xwb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwb.c; sourceTree = ""; }; 836F6F1418BDC2190095E648 /* ydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ydsp.c; sourceTree = ""; }; 836F6F1518BDC2190095E648 /* zsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zsd.c; sourceTree = ""; }; - 836F6F1618BDC2190095E648 /* zwdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zwdsp.c; sourceTree = ""; }; 836F6F1718BDC2190095E648 /* streamfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = streamfile.c; sourceTree = ""; }; 836F6F1818BDC2190095E648 /* streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streamfile.h; sourceTree = ""; }; 836F6F1918BDC2190095E648 /* streamtypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streamtypes.h; sourceTree = ""; }; @@ -1738,6 +1738,10 @@ 83B8FE2E2D5AB2F4005854C1 /* xwb_konami.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = xwb_konami.c; sourceTree = ""; }; 83B8FE302D5AB421005854C1 /* undefind.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = undefind.c; sourceTree = ""; }; 83BAFB6B19F45EB3005DAB60 /* bfstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bfstm.c; sourceTree = ""; }; + 83BB84002DF2D049002077FC /* swar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = swar.c; sourceTree = ""; }; + 83BB84022DF2D125002077FC /* rwar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = rwar.c; sourceTree = ""; }; + 83BB84042DF2D1C2002077FC /* ivb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ivb.c; sourceTree = ""; }; + 83BB84052DF2D1C2002077FC /* ivb_streamfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ivb_streamfile.h; sourceTree = ""; }; 83C0C75C2AA435C60056AFD8 /* squeak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = squeak.c; sourceTree = ""; }; 83C0C75E2AA436370056AFD8 /* layout_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = layout_utils.c; sourceTree = ""; }; 83C0C75F2AA436370056AFD8 /* layout_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout_utils.h; sourceTree = ""; }; @@ -2481,6 +2485,8 @@ 83AFABBB23795202002F3947 /* isb.c */, 836F6E5618BDC2180095E648 /* ish_isd.c */, 83269DD12399F5DE00F49FE3 /* ivag.c */, + 83BB84042DF2D1C2002077FC /* ivb.c */, + 83BB84052DF2D1C2002077FC /* ivb_streamfile.h */, 837CEAEF23487F2C00E62A4A /* jstm.c */, 837CEAE923487F2B00E62A4A /* jstm_streamfile.h */, 83CBF5382D4630B400AA2D75 /* ka1a.c */, @@ -2514,7 +2520,6 @@ 836F6EAC18BDC2180095E648 /* mic_koei.c */, 83B73C4A2D8FF19800A57F08 /* mio.c */, 8346D97725BF838C00D1A8B0 /* mjb_mjh.c */, - 836F6E5F18BDC2180095E648 /* mn_str.c */, 8349A9031FE6258100E26435 /* mogg.c */, 836F6E6018BDC2180095E648 /* mp4.c */, 839FBFF926C354E70016A78A /* mp4_faac.c */, @@ -2623,6 +2628,7 @@ 836F6EE518BDC2190095E648 /* rs03.c */, 836F6EE618BDC2190095E648 /* rsd.c */, 83FBB1772A4FF71B00CD0580 /* rstm_rockstar.c */, + 83BB84022DF2D125002077FC /* rwar.c */, 836F6EE918BDC2190095E648 /* rwax.c */, 836F6EB818BDC2180095E648 /* rws_80d.c */, 83FBB1762A4FF71B00CD0580 /* rws_809.c */, @@ -2696,6 +2702,7 @@ 83AA7F7B2519C042004C5298 /* svag_snk.c */, 834FE0D7215C79EA000A5D3D /* svgp.c */, 836F6EF918BDC2190095E648 /* svs.c */, + 83BB84002DF2D049002077FC /* swar.c */, 83D0381724A4129A004CF90F /* swav.c */, 83E7FD6425EF2B2400683FD2 /* tac.c */, 8373342E23F60D4100DE14DC /* tgc.c */, @@ -2799,7 +2806,6 @@ 836F6F1518BDC2190095E648 /* zsd.c */, 832BF80F21E05149006F50F1 /* zsnd.c */, 832BF80E21E05149006F50F1 /* zsnd_streamfile.h */, - 836F6F1618BDC2190095E648 /* zwdsp.c */, 83AA7F7C2519C042004C5298 /* zwv.c */, ); path = meta; @@ -2975,6 +2981,7 @@ 834F7DDE2C7093EA003AC386 /* mpeg_decoder.h in Headers */, 83031EDB243C510500C3F3E0 /* xnb_lz4mg.h in Headers */, 836F705418BDC2190095E648 /* streamfile.h in Headers */, + 83BB84072DF2D1C2002077FC /* ivb_streamfile.h in Headers */, 834F7DB12C7093EA003AC386 /* circus_vq_lzxpcm.h in Headers */, 835B9B922730BF2D00F87EE3 /* hca_bf.h in Headers */, 836DF623298F83F400CD0580 /* bitstream_msb.h in Headers */, @@ -3223,6 +3230,7 @@ 8306B0AF20984552000302D4 /* blocked_rws.c in Sources */, 83C7281A22BC893D00678B4A /* mus_vc.c in Sources */, 835559FC2869102B005FE93A /* sndz.c in Sources */, + 83BB84032DF2D125002077FC /* rwar.c in Sources */, 839E21EB1F2EDB0600EE54D7 /* sk_aud.c in Sources */, 834FE0F1215C79ED000A5D3D /* a2m.c in Sources */, 8301659A1F256BD000CA0941 /* txth.c in Sources */, @@ -3272,7 +3280,6 @@ 83997F5B22D9569E00633184 /* rad.c in Sources */, 834F7DED2C7093EA003AC386 /* psv_decoder.c in Sources */, 837CEAF423487F2C00E62A4A /* xa_xa30.c in Sources */, - 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */, 832BF82821E0514B006F50F1 /* xwma.c in Sources */, 83FC176E23AC58D100E1025F /* csb.c in Sources */, 836F46B32820874D005B9B87 /* esf.c in Sources */, @@ -3399,6 +3406,7 @@ 836F703618BDC2190095E648 /* thp.c in Sources */, 834F7DFB2C7093EA003AC386 /* tac_decoder.c in Sources */, 836F6F7818BDC2190095E648 /* cstr.c in Sources */, + 83BB84012DF2D049002077FC /* swar.c in Sources */, 83F1EE30245D4FC10076E182 /* imuse.c in Sources */, 833E82F02A28587D00CD0580 /* companion_files.c in Sources */, 834F7E072C7093EA003AC386 /* vorbis_custom_utils_sk.c in Sources */, @@ -3542,7 +3550,6 @@ 836F6FD518BDC2190095E648 /* lp_ap_lep.c in Sources */, 8306B0DC20984590000302D4 /* sthd.c in Sources */, 836F6FAE18BDC2190095E648 /* mpds.c in Sources */, - 836F705218BDC2190095E648 /* zwdsp.c in Sources */, 83FBB1722A4FF4EC00CD0580 /* ego_dic.c in Sources */, 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */, 834F7DE12C7093EA003AC386 /* mtaf_decoder.c in Sources */, @@ -3689,6 +3696,7 @@ 83031ECD243C50CC00C3F3E0 /* blocked_vid1.c in Sources */, 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, 8349A9161FE6258200E26435 /* flx.c in Sources */, + 83BB84062DF2D1C2002077FC /* ivb.c in Sources */, 832BF82921E0514B006F50F1 /* msf_banpresto.c in Sources */, 834FE0BE215C79A9000A5D3D /* blocked_xa_aiff.c in Sources */, 835B9B902730BF2D00F87EE3 /* ast_mmv.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/base/render.c b/Frameworks/vgmstream/vgmstream/src/base/render.c index 12a5cee52..a2cbefd91 100644 --- a/Frameworks/vgmstream/vgmstream/src/base/render.c +++ b/Frameworks/vgmstream/vgmstream/src/base/render.c @@ -345,7 +345,7 @@ int render_main(sbuf_t* sbuf, VGMSTREAM* vgmstream) { return sbuf->filled; } -int render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { +int render_vgmstream2(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { sbuf_t sbuf = {0}; sbuf_init_s16(&sbuf, buf, sample_count, vgmstream->channels); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c index 148d354eb..d83b62681 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/atrac9_decoder.c @@ -62,7 +62,7 @@ void* init_atrac9(atrac9_config* cfg) { if (!data->buf) goto fail; // while ATRAC9 uses float internally, Sony's API only returns PCM16 - data->sbuf = calloc(data->info.channels * data->info.frameSamples * data->info.framesInSuperframe, sizeof(sample_t)); + data->sbuf = calloc(data->info.channels * data->info.frameSamples * data->info.framesInSuperframe, sizeof(int16_t)); if (!data->sbuf) goto fail; data->discard = cfg->encoder_delay; diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c index 3d66f053d..476554c30 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/ffmpeg_decoder_utils.c @@ -22,7 +22,7 @@ static int ffmpeg_make_riff_atrac3(uint8_t* buf, size_t buf_size, size_t sample_ put_u16le(buf+0x14, 0x0270); /* ATRAC3 codec */ put_u16le(buf+0x16, channels); put_u32le(buf+0x18, sample_rate); - put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample_t)); /* average bytes per second (wrong) */ + put_u32le(buf+0x1c, sample_rate * channels / sizeof(int16_t)); /* average bytes per second (wrong) */ put_u16le(buf+0x20, block_align); /* block align */ put_u16le(buf+0x24, 0x0e); /* extra data size */ @@ -230,7 +230,7 @@ static int ffmpeg_make_riff_atrac3plus(uint8_t* buf, int buf_size, uint32_t data put_u16le(buf+0x14, 0xfffe); /* WAVEFORMATEXTENSIBLE */ put_u16le(buf+0x16, channels); put_u32le(buf+0x18, sample_rate); - put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample_t)); /* average bytes per second (wrong) */ + put_u32le(buf+0x1c, sample_rate * channels / sizeof(int16_t)); /* average bytes per second (wrong) */ put_u32le(buf+0x20, block_align); /* block align */ put_u16le(buf+0x24, 0x22); /* extra data size */ @@ -432,7 +432,7 @@ static int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t data_size } } - put_u32le(buf+off+0x00, sample_rate*stream_channels / sizeof(sample_t)); /* average bytes per second (wrong, unneeded) */ + put_u32le(buf+off+0x00, sample_rate*stream_channels / sizeof(int16_t)); /* average bytes per second (wrong, unneeded) */ put_u32le(buf+off+0x04, sample_rate); put_u32le(buf+off+0x08, 0); /* loop start */ put_u32le(buf+off+0x0c, 0); /* loop end */ @@ -492,7 +492,7 @@ static int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t data_size default: speakers = 0; break; } - bytecount = sample_count * channels * sizeof(sample_t); + bytecount = sample_count * channels * sizeof(int16_t); memcpy (buf+0x00, "RIFF", 0x04); put_u32le(buf+0x04, buf_max - (0x04 * 2) + data_size); /* riff size */ @@ -503,8 +503,8 @@ static int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t data_size put_u16le(buf+0x14, 0x0166); /* XMA2 */ put_u16le(buf+0x16, channels); put_u32le(buf+0x18, sample_rate); - put_u32le(buf+0x1c, sample_rate * channels / sizeof(sample_t)); /* average bytes per second (wrong, unneeded) */ - put_u16le(buf+0x20, (uint16_t)(channels * sizeof(sample_t))); /* block align */ + put_u32le(buf+0x1c, sample_rate * channels / sizeof(int16_t)); /* average bytes per second (wrong, unneeded) */ + put_u16le(buf+0x20, (uint16_t)(channels * sizeof(int16_t))); /* block align */ put_u16le(buf+0x22, 16); /* bits per sample */ put_u16le(buf+0x24, 0x22); /* extra data size */ diff --git a/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c index 3e7e9785e..b178e9cbf 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/imuse_decoder.c @@ -480,10 +480,10 @@ static int decode_vima_comp(imuse_codec_data* data, block_entry_t* entry) { VGM_LOG("IMUSE: found PCM block %i\n", data->current_block); /* presumably PCM data (not seen) */ - for (int i = 0, j = pos; i < copy_size / sizeof(sample_t); i++, j += 2) { + for (int i = 0, j = pos; i < copy_size / sizeof(int16_t); i++, j += 2) { data->pbuf[i] = get_s16le(data->block + j); } - filled += copy_size / chs / sizeof(sample_t); + filled += copy_size / chs / sizeof(int16_t); pos += copy_size; data_left -= copy_size; diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 7776be8a2..f7f3e9939 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -352,7 +352,6 @@ static const char* extension_list[] = { "mib", "mic", "mio", - "mnstr", "mogg", //"m4a", //common //"m4v", //common @@ -580,6 +579,7 @@ static const char* extension_list[] = { "svs", "svg", "swag", + "swar", "swav", "swd", "switch", //txth/reserved (.m4a-x.switch) [Ikinari Maou (Switch)] @@ -728,7 +728,6 @@ static const char* extension_list[] = { "zsd", "zsm", "zss", - "zwdsp", "zwv", "vgmstream" /* fake extension, catch-all for FFmpeg/txth/etc */ @@ -833,10 +832,10 @@ static const coding_info coding_info_list[] = { {coding_XA, "CD-ROM XA 4-bit ADPCM"}, {coding_XA8, "CD-ROM XA 8-bit ADPCM"}, {coding_XA_EA, "Electronic Arts XA 4-bit ADPCM"}, - {coding_PSX, "Playstation 4-bit ADPCM"}, - {coding_PSX_badflags, "Playstation 4-bit ADPCM (bad flags)"}, - {coding_PSX_cfg, "Playstation 4-bit ADPCM (configurable)"}, - {coding_PSX_pivotal, "Playstation 4-bit ADPCM (Pivotal)"}, + {coding_PSX, "PlayStation 4-bit ADPCM"}, + {coding_PSX_badflags, "PlayStation 4-bit ADPCM (bad flags)"}, + {coding_PSX_cfg, "PlayStation 4-bit ADPCM (configurable)"}, + {coding_PSX_pivotal, "PlayStation 4-bit ADPCM (Pivotal)"}, {coding_HEVAG, "Sony HEVAG 4-bit ADPCM"}, {coding_EA_XA, "Electronic Arts EA-XA 4-bit ADPCM v1"}, @@ -1158,7 +1157,6 @@ static const meta_info meta_info_list[] = { {meta_SEG, "Stormfront SEG header"}, {meta_RIFF_IMA, "Square Enix RIFF IMA eader"}, {meta_KNON, "Paon KNON header"}, - {meta_ZWDSP, "Zack and Wiki custom DSP Header"}, {meta_GCA, "GCA DSP Header"}, {meta_SPT_SPD, "SPT+SPD DSP Header"}, {meta_ISH_ISD, "ISH+ISD DSP Header"}, @@ -1264,7 +1262,6 @@ static const meta_info meta_info_list[] = { {meta_MTAF, "Konami MTAF header"}, {meta_ALP, "High Voltage ALP header"}, {meta_WPD, "Navel WPD header"}, - {meta_MN_STR, "Mini Ninjas 'STR' header"}, {meta_MCSS, "Guerilla MCSS header"}, {meta_PS2_HSF, "Lowrider 'HSF' header"}, {meta_IVAG, "Namco IVAG header"}, @@ -1358,7 +1355,6 @@ static const meta_info meta_info_list[] = { {meta_HD3_BD3, "Sony HD3+BD3 header"}, {meta_BNK_SONY, "Sony BNK header"}, {meta_SSCF, "Square Enix SSCF header"}, - {meta_DSP_VAG, ".VAG DSP header"}, {meta_DSP_ITL, ".ITL DSP header"}, {meta_A2M, "Artificial Mind & Movement A2M header"}, {meta_AHV, "Amuze AHV header"}, @@ -1481,6 +1477,8 @@ static const meta_info meta_info_list[] = { {meta_OOR, "age .OOR header"}, {meta_MIO, "Entis .MIO header"}, {meta_AUDIOPKG, "Inevitable .AUDIOPKG header"}, + {meta_SWAR, "Nintendo SWAR header"}, + {meta_IVB, "Metro IVB header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/Frameworks/vgmstream/vgmstream/src/libvgmstream.h b/Frameworks/vgmstream/vgmstream/src/libvgmstream.h index f29a46075..911bef40a 100644 --- a/Frameworks/vgmstream/vgmstream/src/libvgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/libvgmstream.h @@ -64,7 +64,7 @@ LIBVGMSTREAM_API uint32_t libvgmstream_get_version(void); /* CHANGELOG: - * - 1.0.0: beta version + * - 1.0.0: initial version */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c b/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c index 48a2d0941..1c0b58ad3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/bfwav.c @@ -324,73 +324,3 @@ fail: close_vgmstream(vgmstream); return NULL; } - -/* ************************************************************************* */ - -/* RWAR - NintendoWare container [BIT.TRIP BEAT (Wii), Dance Dance Revolution Hottest Party 2 (Wii)] */ -VGMSTREAM* init_vgmstream_brwar(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - STREAMFILE* temp_sf = NULL; - uint32_t tabl_offset, data_offset; - uint32_t subfile_offset, subfile_size; - int total_subsongs, target_subsong = sf->stream_index; - - - /* checks */ - if (!is_id32be(0x00, sf, "RWAR")) - goto fail; - - if (!check_extensions(sf,"rwar")) - goto fail; - - /* simple container of .rwavs (inside .brsar), rarely used with single siles (DDR) */ - - /* abridged, see RWAV (same header) */ - /* 0x04(2): BOM */ - /* 0x06(2): version (usually 0100) */ - /* 0x08: file size */ - /* 0x0c(2): header size (0x20) */ - /* 0x0e(2): sections (2) */ - - tabl_offset = read_u32be(0x10, sf); - /* 0x14: tabl size */ - - data_offset = read_u32be(0x18, sf); - /* 0x1c: data size */ - - /* TABL section */ - if (!is_id32be(tabl_offset + 0x00, sf, "TABL")) - goto fail; - /* 0x04: size */ - - total_subsongs = read_u32be(tabl_offset + 0x08,sf); - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - /* 0x00: always 0x01000000? */ - subfile_offset = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x04,sf) + data_offset; - subfile_size = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x08,sf); - - - /* DATA section */ - if (!is_id32be(data_offset + 0x00, sf, "DATA")) - goto fail; - /* 0x04: size */ - - //VGM_LOG("BRWAR: of=%x, sz=%x\n", subfile_offset, subfile_size); - - temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "rwav"); - if (!temp_sf) goto fail; - - vgmstream = init_vgmstream_brwav(temp_sf); - if (!vgmstream) goto fail; - - vgmstream->num_streams = total_subsongs; - 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 486a39767..e8eb2d76a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c @@ -3,7 +3,6 @@ #ifdef VGM_USE_FFMPEG -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: @@ -53,19 +52,6 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { total_subsongs = ffmpeg_get_subsong_count(data); /* uncommon, ex. wmv [Lost Odyssey (X360)] */ if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - /* try to get .pos data */ - { - uint8_t posbuf[0x04*3]; - - if (read_pos_file(posbuf, sizeof(posbuf), sf)) { - loop_start = get_s32le(posbuf+0x00); - loop_end = get_s32le(posbuf+0x04); - loop_flag = 1; /* incorrect looping will be validated outside */ - /* FFmpeg can't always determine samples correctly so optionally load it (can be 0/NULL) - * won't crash and will output silence if no loop points and bigger than actual stream's samples */ - num_samples = get_s32le(posbuf+8); - } - } /* try to read Ogg/Flac loop tags (abridged) */ if (!loop_flag && (is_id32be(0x00, sf, "OggS") || is_id32be(0x00, sf, "fLaC"))) { @@ -160,45 +146,6 @@ fail: } -/* open file containing looping data and copy to buffer, returns true if found and copied */ -int read_pos_file(uint8_t* buf, size_t bufsize, STREAMFILE* sf) { - char posname[PATH_LIMIT]; - char filename[PATH_LIMIT]; - /*size_t bytes_read;*/ - STREAMFILE* sf_pos = NULL; - - get_streamfile_name(sf,filename,sizeof(filename)); - - if (strlen(filename)+4 > sizeof(posname)) - goto fail; - - /* try to open a posfile using variations: "(name.ext).pos" */ - { - strcpy(posname, filename); - strcat(posname, ".pos"); - sf_pos = open_streamfile(sf, posname);; - if (sf_pos) goto found; - - goto fail; - } - -found: - //if (get_streamfile_size(sf_pos) != bufsize) goto fail; - - /* allow pos files to be of different sizes in case of new features, just fill all we can */ - memset(buf, 0, bufsize); - read_streamfile(buf, 0, bufsize, sf_pos); - - close_streamfile(sf_pos); - - return 1; - -fail: - close_streamfile(sf_pos); - return 0; -} - - /* loop tag handling could be unified with ogg_vorbis.c, but that one has a extra features too. * Also has support for flac meta loops, that can be used by stuff like Platformer Game Engine * or ZDoom/Duke Nukem 3D source ports (maybe RPG Maker too). */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h index 7247b61ce..24550161a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h @@ -72,6 +72,7 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSB4, FSBKEY_ADD("dpdjeoqkr") }, // AirRider CrazyRacing (PC) { MODE_FSB5, FSBKEY_ADD("weareAbsolutelyUnsure2018") }, // Wanderstop (PC) { MODE_FSB5, FSBKEY_ADD(".xW3uXQ8q79yunvMjL6nahLXts9esEXX2VgetuPCxdLrAjUUbZAmB7R*A6KjW24NU_8ifMZ8TC4Qk@_oEsjsK2QLpAaG-Fy!wYKP") }, // UNBEATABLE Demo (PC) + { MODE_FSB5, FSBKEY_ADD(",H9}:p?`bRlQG5_yJ\"\"/L,X_{:=Gs1") }, // Rennsport (PC) /* some games use a key per file, generated from the filename * (could add all of them but there are a lot of songs, so external .fsbkey are probably better) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ivb.c b/Frameworks/vgmstream/vgmstream/src/meta/ivb.c new file mode 100644 index 000000000..23bc49587 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ivb.c @@ -0,0 +1,59 @@ +#include "meta.h" +#include "../util.h" +#include "../util/meta_utils.h" +#include "ivb_streamfile.h" + + +/* IVB - from Metro PS2 games [Bomberman Jetters (PS2), Dance Summit 2001: Bust A Move (PS2)] */ +VGMSTREAM* init_vgmstream_ivb(STREAMFILE* sf) { + + /* checks */ + if (!is_id32be(0x00, sf, "IVB\0")) + return NULL; + if (!check_extensions(sf,"ivb")) + return NULL; + + meta_header_t h = {0}; + h.meta = meta_IVB; + + // N stereo tracks, treat as subsongs instead of channels as both may have different total time + // and aren't meant to play at once, though data is padded so tracks have same size + + h.total_subsongs = read_s32le(0x04, sf); // always 2 tracks + h.interleave = read_s32le(0x08, sf); + // 0c: null + + // per track + // 00: channel size + // 04: channel blocks (may be less than channel size due to padding and different per track) + // 08: size of last block (1 channel) + // 0c: null + + int target_subsong = sf->stream_index; + if (target_subsong == 0) + target_subsong = 1; + + uint32_t head_offset = 0x10 + (target_subsong - 1) * 0x10; + //uint32_t chan_size = read_u32le(head_offset + 0x00, sf); //with padding + uint32_t chan_blocks = read_u32le(head_offset + 0x04, sf); + uint32_t last_size = read_u32le(head_offset + 0x08, sf); // last block without padding + + h.channels = 2; + h.sample_rate = 44100; + h.has_subsongs = true; + + h.coding = coding_PSX; + h.layout = layout_interleave; + + h.stream_offset = 0x00; + h.stream_size = (chan_blocks - 1) * h.interleave * h.channels + last_size * h.channels; + + h.num_samples = ps_bytes_to_samples(h.stream_size, h.channels); + + h.sf = setup_ivb_streamfile(sf, 0x800, h.total_subsongs, target_subsong - 1, h.interleave * h.channels); + h.open_stream = true; + + VGMSTREAM* v = alloc_metastream(&h); + close_streamfile(h.sf); + return v; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ivb_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/ivb_streamfile.h new file mode 100644 index 000000000..91ab9ed88 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ivb_streamfile.h @@ -0,0 +1,21 @@ +#ifndef _STR_WAV_STREAMFILE_H_ +#define _STR_WAV_STREAMFILE_H_ +#include "deblock_streamfile.h" + +/* Deblocks streams */ +static STREAMFILE* setup_ivb_streamfile(STREAMFILE* sf, uint32_t stream_start, int stream_count, int stream_number, uint32_t chunk_size) { + STREAMFILE* new_sf = NULL; + deblock_config_t cfg = {0}; + + cfg.stream_start = stream_start; + cfg.chunk_size = chunk_size; + cfg.step_start = stream_number; + cfg.step_count = stream_count; + + /* setup sf */ + new_sf = open_wrap_streamfile(sf); + new_sf = open_io_deblock_streamfile_f(new_sf, &cfg); + return new_sf; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 378d27ffe..8742ba2ba 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -57,7 +57,6 @@ VGMSTREAM* init_vgmstream_dsp_dspw(STREAMFILE* sf); VGMSTREAM* init_vgmstream_ngc_dsp_iadp(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_mcadpcm(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_switch_audio(STREAMFILE* sf); -VGMSTREAM* init_vgmstream_dsp_sps_n1(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_itl_ch(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_adpy(STREAMFILE* sf); VGMSTREAM* init_vgmstream_dsp_adpx(STREAMFILE* sf); @@ -316,8 +315,6 @@ VGMSTREAM* init_vgmstream_riff_ima(STREAMFILE* sf); VGMSTREAM * init_vgmstream_knon(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_gca(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_spt_spd(STREAMFILE * streamFile); @@ -504,8 +501,6 @@ VGMSTREAM* init_vgmstream_alp(STREAMFILE* sf); VGMSTREAM * init_vgmstream_wpd(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_mn_str(STREAMFILE* streamFile); - VGMSTREAM* init_vgmstream_mcss(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE* streamFile); @@ -527,7 +522,8 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_brwav(STREAMFILE* sf); VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf); VGMSTREAM* init_vgmstream_bcwav(STREAMFILE* sf); -VGMSTREAM* init_vgmstream_brwar(STREAMFILE* sf); + +VGMSTREAM* init_vgmstream_rwar(STREAMFILE* sf); VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE* streamFile); @@ -1037,4 +1033,8 @@ VGMSTREAM* init_vgmstream_ssp(STREAMFILE* sf); VGMSTREAM* init_vgmstream_audiopkg(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_swar(STREAMFILE* sf); + +VGMSTREAM* init_vgmstream_ivb(STREAMFILE* sf); + #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c b/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c deleted file mode 100644 index 5706963dd..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c +++ /dev/null @@ -1,81 +0,0 @@ -#include "meta.h" -#include "../util.h" - -VGMSTREAM * init_vgmstream_mn_str(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - int bitspersample; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("mnstr",filename_extension(filename))) goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x50,streamFile); - bitspersample = read_32bitLE(0x58,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x20,streamFile)+0x48; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x54,streamFile); - - switch (bitspersample) { - case 0x10: - vgmstream->coding_type = coding_PCM16LE; - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else - { - vgmstream->interleave_block_size = 0x2; - vgmstream->layout_type = layout_interleave; - } - break; - case 0x4: - if (read_32bitLE(0x20,streamFile) == 0x24) - { - vgmstream->interleave_block_size = 0x800; - vgmstream->layout_type = layout_none; - } - break; - default: - goto fail; - } - - vgmstream->num_samples = read_32bitLE(0x4C,streamFile); - - //vgmstream->layout_type = layout_interleave; - //vgmstream->interleave_block_size = 0x2; - vgmstream->meta_type = meta_MN_STR; - - /* 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; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c index 96089aef8..e5295801f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -1206,38 +1206,6 @@ fail: return NULL; } - -/* .vag - Nippon Ichi SPS wrapper [Penny-Punching Princess (Switch), Ys VIII (Switch)] */ -VGMSTREAM* init_vgmstream_dsp_sps_n1(STREAMFILE* sf) { - dsp_meta dspm = {0}; - - /* checks */ - if (read_u32be(0x00,sf) != 0x08000000) /* file type (see other N1 SPS) */ - goto fail; - - /* .vag: Penny-Punching Princess (Switch) - * .nlsd: Ys VIII (Switch) */ - if (!check_extensions(sf, "vag,nlsd")) - goto fail; - if (read_u16le(0x08,sf) != read_u32le(0x24,sf)) /* header has various repeated values */ - goto fail; - - dspm.channels = 1; - dspm.max_channels = 1; - dspm.little_endian = 1; - - dspm.header_offset = 0x1c; - dspm.header_spacing = 0x60; - dspm.start_offset = dspm.header_offset + dspm.header_spacing*dspm.channels; - dspm.interleave = 0; - - dspm.meta_type = meta_DSP_VAG; - return init_vgmstream_dsp_common(sf, &dspm); -fail: - return NULL; -} - - /* .itl - from Chanrinko Hero (GC) */ VGMSTREAM* init_vgmstream_dsp_itl_ch(STREAMFILE* sf) { dsp_meta dspm = {0}; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nub.c b/Frameworks/vgmstream/vgmstream/src/meta/nub.c index a309c8cba..ab88f1490 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/nub.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/nub.c @@ -547,15 +547,23 @@ VGMSTREAM* init_vgmstream_nub_dsp(STREAMFILE* sf) { /* paste header+data together and pass to meta, which has loop info too */ header_offset = 0xBC; - stream_size = read_32bitBE(0x14, sf); - header_size = read_32bitBE(0x1c, sf); + stream_size = read_u32be(0x14, sf); + header_size = read_u32be(0x1c, sf); stream_offset = align_size_to_block(header_offset + header_size, 0x10); temp_sf = setup_nub_streamfile(sf, header_offset, header_size, stream_offset, stream_size, "dsp"); if (!temp_sf) goto fail; - vgmstream = init_vgmstream_ngc_dsp_std(temp_sf); - if (!vgmstream) goto fail; + + if (stream_size <= 0x10) { + // SoulCalibur Legends (Wii) empty subsongs (tc_jp0b.nub#4) + vgmstream = init_vgmstream_silence(0, 0, 0); + if (!vgmstream) goto fail; + } + else { + vgmstream = init_vgmstream_ngc_dsp_std(temp_sf); + if (!vgmstream) goto fail; + } close_streamfile(temp_sf); return vgmstream; @@ -576,6 +584,7 @@ VGMSTREAM* init_vgmstream_nub_idsp(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "idsp")) return NULL; + // .idsp: internal extension before packing, seen in debug files with filenames if (!check_extensions(sf,"idsp")) return NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c index d7a929906..300d00343 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis.c @@ -400,7 +400,7 @@ static int _init_vgmstream_ogg_vorbis_tests(STREAMFILE* sf, ogg_vorbis_io_config /* try in ../(file) too since that's how the .isl is stored on disc */ char isl_path[PATH_LIMIT]; snprintf(isl_path, sizeof(isl_path), "../%s", isl_name); - sf_isl = open_streamfile_by_filename(sf, isl_path); + sf_isl = open_streamfile_by_pathname(sf, isl_path); } if (sf_isl) { @@ -741,6 +741,14 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start, loop_end_found = 1; } } + else if (strstr(comment,"COMMENT=SetSample ") == comment) { /* Ore no Tsure wa Hito de Nashi (PC) */ + int unk0; // always 0 (delay?) + int m = sscanf(comment,"COMMENT=SetSample %d,%d,%d", &unk0, &loop_start, &loop_end); + if (m == 3) { + loop_flag = true; + loop_end_found = true; + } + } else if (strstr(comment,"L=") == comment) { /* Kamaitachi no Yoru 2 (PS2) */ //sscanf(strrchr(comment,'=')+1,"%d", &loop_start); loop_start = atol(strrchr(comment,'=')+1); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rwar.c b/Frameworks/vgmstream/vgmstream/src/meta/rwar.c new file mode 100644 index 000000000..ba70dbea4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rwar.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/endianness.h" + + +/* RWAR - NintendoWare container [BIT.TRIP BEAT (Wii), Dance Dance Revolution Hottest Party 2 (Wii)] */ +VGMSTREAM* init_vgmstream_rwar(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + uint32_t tabl_offset, data_offset; + uint32_t subfile_offset, subfile_size; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00, sf, "RWAR")) + goto fail; + + if (!check_extensions(sf,"rwar")) + goto fail; + + /* simple container of .rwavs (inside .brsar), rarely used with single siles (DDR) */ + + /* abridged, see RWAV (same header) */ + /* 0x04(2): BOM */ + /* 0x06(2): version (usually 0100) */ + /* 0x08: file size */ + /* 0x0c(2): header size (0x20) */ + /* 0x0e(2): sections (2) */ + + tabl_offset = read_u32be(0x10, sf); + /* 0x14: tabl size */ + + data_offset = read_u32be(0x18, sf); + /* 0x1c: data size */ + + /* TABL section */ + if (!is_id32be(tabl_offset + 0x00, sf, "TABL")) + return NULL; + /* 0x04: size */ + + total_subsongs = read_u32be(tabl_offset + 0x08,sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + /* 0x00: always 0x01000000? */ + subfile_offset = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x04,sf) + data_offset; + subfile_size = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x08,sf); + + + /* DATA section */ + if (!is_id32be(data_offset + 0x00, sf, "DATA")) + goto fail; + /* 0x04: size */ + + //VGM_LOG("BRWAR: of=%x, sz=%x\n", subfile_offset, subfile_size); + + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "rwav"); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream_brwav(temp_sf); + if (!vgmstream) goto fail; + + vgmstream->num_streams = total_subsongs; + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c b/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c index f5c3af563..bdcb472ce 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sps_n1.c @@ -4,26 +4,27 @@ #include "../util/endianness.h" #include "../util/layout_utils.h" -/* also see init_vgmstream_dsp_sps_n1 and init_vgmstream_opus_sps_n1 */ - /* Nippon Ichi SPS wrapper [ClaDun (PSP), Legasista (PS3)] */ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; - int type, sample_rate; - off_t subfile_offset; - size_t subfile_size; - init_vgmstream_t init_vgmstream = NULL; const char* extension = NULL; - uint32_t (*read_u32)(off_t,STREAMFILE*); - uint16_t (*read_u16)(off_t,STREAMFILE*); + read_u32_t read_u32; + read_u16_t read_u16; /* checks */ - if (!check_extensions(sf,"sps")) - goto fail; + int type = read_u32le(0x00,sf); + if (!((type > 0 && type < 10) || type == 0x01000000 || type == 0x02000000)) + return NULL; - if (guess_endian32(0x00, sf)) { /* PS3 */ + /* .sps: common, ClaDun X3 (Switch) + * .vag: Penny-Punching Princess (Switch) + * .nlsd: Ys VIII (Switch) */ + if (!check_extensions(sf,"sps,vag,nlsd")) + return NULL; + + if (guess_endian32(0x00, sf)) { // PS3 read_u32 = read_u32be; read_u16 = read_u16be; } @@ -31,12 +32,25 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) { read_u32 = read_u32le; read_u16 = read_u16le; } + type = read_u32(0x00,sf); - subfile_size = read_u32(0x04,sf); - sample_rate = read_u16(0x08,sf); - /* 0x0a: flag? (stereo?) */ - /* 0x0b: flag? */ - /* 0x0c: num_samples */ + uint32_t subfile_size = read_u32(0x04,sf); + int sample_rate = read_u16(0x08,sf); + // 0x0a: flag? (stereo?) + // 0x0b: flag? + // 0x0c: num_samples + // newer games with loop section (>7?): + // 0x10: loop start + // 0x14: loop end + // some games extra value (>8?): + // 0x18: null? + + if (sample_rate < 8000 || sample_rate > 48000) //arbitrary max + return NULL; + + uint32_t subfile_offset = get_streamfile_size(sf) - subfile_size; + if (subfile_offset <= 0 || subfile_offset > 0x1c) + return NULL; switch(type) { case 1: @@ -49,13 +63,21 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) { extension = "at3"; break; + case 8: + init_vgmstream = init_vgmstream_ngc_dsp_std_le; + extension = "adpcm"; + break; + + case 7: + // init_vgmstream_ogg_vorbis (init_vgmstream_sps_n1_segmented) + case 9: + // init_vgmstream_opus_sps_n1 + // init_vgmstream_opus_std (init_vgmstream_sps_n1_segmented) + default: - goto fail; + return NULL; } - subfile_offset = 0x10; - if (subfile_size + subfile_offset != get_streamfile_size(sf)) - goto fail; /* init the VGMSTREAM */ temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, extension); @@ -64,7 +86,14 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) { vgmstream = init_vgmstream(temp_sf); if (!vgmstream) goto fail; - vgmstream->sample_rate = sample_rate; /* .vag header doesn't match */ + vgmstream->sample_rate = sample_rate; // internal header isn't always correct vs .sps info + + if (type == 8) { + // most files set loops in DSP header but don't loop, though some do full loops + uint32_t loop_start = read_u32(0x10, sf); + if (loop_start == 0) + vgmstream->loop_flag = false; + } close_streamfile(temp_sf); return vgmstream; @@ -91,7 +120,7 @@ VGMSTREAM* init_vgmstream_sps_n1_segmented(STREAMFILE* sf) { /* checks */ type = read_u32le(0x00,sf); - if (type > 10) + if (type < 7 || type > 10) return NULL; /* .at9: Penny-Punching Princess (Switch), Labyrinth of Galleria (PC) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/swar.c b/Frameworks/vgmstream/vgmstream/src/meta/swar.c new file mode 100644 index 000000000..e0b95490c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/swar.c @@ -0,0 +1,97 @@ + #include "meta.h" +#include "../coding/coding.h" +#include "../util/meta_utils.h" + +/* SWAR - wave container generated by the DS SDK */ +VGMSTREAM* init_vgmstream_swar(STREAMFILE* sf) { + + /* checks */ + if (!is_id32be(0x00,sf, "SWAR")) + return NULL; + if (!check_extensions(sf, "swar")) + return NULL; + + meta_header_t h = {0}; + h.meta = meta_SWAV; + h.target_subsong = sf->stream_index; + if (h.target_subsong == 0) + h.target_subsong = 1; + + // wave container mainly for sequences, accesed through .sbnk + // 0x04: BOM mark + // 0x06: version? (1.00) + h.data_size = read_u32le(0x08,sf); + // 0x0c: always 16? + // 0x0e: always 1? + + if (!is_id32be(0x10, sf, "DATA")) + return NULL; + // 0x14: chunk size (full) + + h.total_subsongs = read_s32le(0x38,sf); + uint32_t head_offset = read_s32le(0x3c + (h.target_subsong - 1) * 0x04, sf); + + // "sample" header, similar to SWAV + int codec = read_u8 (head_offset + 0x00, sf); + h.loop_flag = read_u8 (head_offset + 0x01, sf) != 0; + h.sample_rate = read_u16le(head_offset + 0x02, sf); + // 04 time units? (33.513982MHz/2 * time = samples?) + h.loop_start = read_u16le(head_offset + 0x06,sf); //in units + h.loop_end = read_s32le(head_offset + 0x08,sf); //length in units + + h.stream_offset = head_offset; + uint32_t next_offset = h.target_subsong < h.total_subsongs ? + read_s32le(0x3c + (h.target_subsong) * 0x04, sf) : + h.data_size; + h.stream_size = next_offset - h.stream_offset; + + h.stream_offset += 0x10; + h.stream_size -= 0x10; + + h.channels = 1; + + // same as SWAV + int bits_per_sample; + switch (codec) { + case 0: // Phoenix Wright: Ace Attorney (DS) + h.coding = coding_PCM8; + bits_per_sample = 8; + h.num_samples = pcm8_bytes_to_samples(h.stream_size, h.channels); + break; + case 1: // Electroplankton (DS) + h.coding = coding_PCM16LE; + bits_per_sample = 16; + h.num_samples = pcm16_bytes_to_samples(h.stream_size, h.channels); + break; + case 2: // common + h.coding = coding_IMA; + bits_per_sample = 4; + h.num_samples = ima_bytes_to_samples(h.stream_size, h.channels); + break; + default: + VGM_LOG("SWAR: unknown format\n"); + return NULL; + } + + h.loop_start = h.loop_start * 32 / bits_per_sample; + h.loop_end = h.loop_end * 32 / bits_per_sample + h.loop_start; + if (codec == 2) { + // handle IMA frame header + h.loop_start -= 32 / bits_per_sample; + h.loop_end -= 32 / bits_per_sample; + } + + + h.layout = layout_none; + h.sf = sf; + h.open_stream = true; + h.has_subsongs = true; + + VGMSTREAM* v = alloc_metastream(&h); + if (!v) return NULL; + + v->ch[0].adpcm_history1_32 = read_s16le(head_offset + 0x0c, sf); + v->ch[0].adpcm_step_index = read_u8(head_offset + 0x0e, sf); + + return v; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index ea38de2b2..b582c04c2 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txth.c @@ -414,8 +414,22 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { vgmstream->codec_config = 1; /* CONFIG_HIGH_NIBBLE */ } + /* get hist */ + if (txth.hist_set) { + read_s16_t read_s16 = txth.hist_big_endian ? read_s16be : read_s16le; + + if (txth.codec == IMA || txth.codec == DVI_IMA) { + for (int i = 0; i < txth.channels; i++) { + vgmstream->ch[i].adpcm_history1_32 = read_s16(txth.hist_offset + i * txth.hist_spacing + 0x00, sf); + vgmstream->ch[i].adpcm_step_index = read_u8(txth.hist_offset + i * txth.hist_spacing + 0x02, sf); + } + } + } + + + //TODO recheck and use only for needed cases - vgmstream->allow_dual_stereo = 1; /* known to be used in: PSX, AICA, YMZ */ + vgmstream->allow_dual_stereo = true; /* known to be used in: PSX, AICA, YMZ */ break; case coding_DPCM_KCEJ: @@ -555,7 +569,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { /* get hist */ if (txth.hist_set) { - read_s16_t read_s16 = txth.coef_big_endian ? read_s16be : read_s16le; + read_s16_t read_s16 = txth.hist_big_endian ? read_s16be : read_s16le; for (i = 0; i < vgmstream->channels; i++) { off_t offset = txth.hist_offset + i*txth.hist_spacing; @@ -1094,7 +1108,7 @@ static STREAMFILE* open_path_streamfile(STREAMFILE* sf, char* path) { if (is_absolute(path)) return open_streamfile(sf, path); /* from path as is */ else - return open_streamfile_by_filename(sf, path); /* from current path */ + return open_streamfile_by_pathname(sf, path); /* from current path */ } static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, char* val) { @@ -1354,7 +1368,7 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha if (!parse_num(txth->sf_head,txth,val, &txth->hist_offset)) goto fail; txth->hist_set = true; /* special adjustment */ - txth->hist_offset += txth->hist_offset; + txth->hist_offset += txth->base_offset; if (txth->subsong_spacing && !txth->is_offset_absolute) txth->hist_offset += txth->subsong_spacing * (txth->target_subsong - 1); } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txtp_process.c b/Frameworks/vgmstream/vgmstream/src/meta/txtp_process.c index efbb43002..437e75172 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txtp_process.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/txtp_process.c @@ -253,7 +253,7 @@ static bool parse_entries(txtp_header_t* txtp, STREAMFILE* sf) { if (is_absolute(filename)) temp_sf = open_streamfile(sf, filename); /* from path as is */ else - temp_sf = open_streamfile_by_filename(sf, filename); /* from current path */ + temp_sf = open_streamfile_by_pathname(sf, filename); /* from current path */ if (!temp_sf) { vgm_logi("TXTP: cannot open %s\n", filename); goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 0c4d391c2..15e848337 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -2779,8 +2779,8 @@ static void config_sb_random_old(ubi_sb_header* sb, off_t sequence_count, off_t sb->cfg.random_percent_int = 1; } -static int check_project_file(STREAMFILE *sf_header, const char *name, int has_localized_banks) { - STREAMFILE *sf_test = open_streamfile_by_filename(sf_header, name); +static int check_project_file(STREAMFILE* sf_header, const char *name, bool has_localized_banks) { + STREAMFILE *sf_test = open_streamfile_by_pathname(sf_header, name); if (sf_test) { close_streamfile(sf_test); return 1; @@ -3107,7 +3107,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* Tonic Touble Special Edition has garbage instead of version */ if (sb->is_bnm && sb->version > 0x00000000 && sb->platform == UBI_PC) { - if (check_project_file(sf, "ED_MAIN.LCB", 0) || check_project_file(sf, "../ED_MAIN.LCB", 0)) { + if (check_project_file(sf, "ED_MAIN.LCB", true)) { is_ttse_pc = true; sb->version = 0x00000000; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index c2d40d7dd..d73efb902 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" #include #include "xwb_xsb.h" @@ -9,14 +10,14 @@ #define WAVEBANKENTRY_FLAGS_IGNORELOOP 0x00000008 // Used internally when the loop region can't be used (no idea...) /* the x.x version is just to make it clearer, MS only classifies XACT as 1/2/3 */ -#define XACT1_0_MAX 1 /* Project Gotham Racing 2 (Xbox)-v01, Silent Hill 4 (Xbox)-v01, Shin Megami Tensei NINE (Xbox)-v01 */ -#define XACT1_1_MAX 3 /* Unreal Championship (Xbox)-v02, The King of Fighters 2003 (Xbox)-v03 */ -#define XACT2_0_MAX 34 /* Project Gotham Racing 3 (X360)-v22, Dead or Alive 4 (X360)-v23, Table Tennis (X360)-v34 */ // v35/36/37 too? -#define XACT2_1_MAX 38 /* Prey (X360)-v38 */ -#define XACT2_2_MAX 41 /* Just Cause (X360)-v39, Blue Dragon (X360)-v40 */ -#define XACT3_0_MAX 46 /* Ninja Blade (X360)-t43-v42, Saints Row 2 (PC)-t44-v42, Persona 4 Ultimax NESSICA (PC)-t45-v43, BlazBlue (X360)-t46-v44 */ -#define XACT_TECHLAND 0x10000 /* Sniper Ghost Warrior (PS3/X360), Nail'd (PS3/X360), equivalent to XACT3_0 */ -#define XACT_CRACKDOWN 0x87 /* Crackdown 1, equivalent to XACT2_2 */ +#define XACT1_0_MAX 1 // 0x01 // Project Gotham Racing 2 (Xbox)-v01, Silent Hill 4 (Xbox)-v01, Shin Megami Tensei NINE (Xbox)-v01 +#define XACT1_1_MAX 3 // 0x03 // Unreal Championship (Xbox)-v02, The King of Fighters 2003 (Xbox)-v03 +#define XACT2_0_MAX 34 // 0x22 // Project Gotham Racing 3 (X360)-v22, Dead or Alive 4 (X360)-v23, Table Tennis (X360)-v34 // v35/36/37 too? +#define XACT2_1_MAX 38 // 0x26 // Prey (X360)-v38 +#define XACT2_2_MAX 41 // 0x29 // Just Cause (X360)-v39, Blue Dragon (X360)-v40 +#define XACT3_0_MAX 46 // 0x2E // Ninja Blade (X360)-t43-v42, Saints Row 2 (PC)-t44-v42, Persona 4 Ultimax NESSICA (PC)-t45-v43, BlazBlue (X360)-t46-v44 +#define XACT_TECHLAND 0x10000 // Sniper Ghost Warrior (PS3/X360), Nail'd (PS3/X360), equivalent to XACT3_0 +#define XACT_CRACKDOWN 0x87 // Crackdown 1, equivalent to XACT2_2 static const int wma_avg_bps_index[7] = { 12000, 24000, 4000, 6000, 8000, 20000, 2500 @@ -84,8 +85,8 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { off_t start_offset, offset, suboffset; xwb_header xwb = {0}; int target_subsong = sf->stream_index; - uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL; - int32_t (*read_s32)(off_t,STREAMFILE*) = NULL; + read_u32_t read_u32 = NULL; + read_s32_t read_s32 = NULL; char stream_name[STREAM_NAME_SIZE], file_name[STREAM_NAME_SIZE]; @@ -313,8 +314,8 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { else if (xwb.version <= XACT2_2_MAX) { switch(xwb.tag) { case 0: xwb.codec = PCM; break; - /* Table Tennis (v34): XMA1, Prey (v38): XMA2, v35/36/37: ? */ - case 1: xwb.codec = xwb.version <= XACT2_0_MAX ? XMA1 : XMA2; break; + /* Table Tennis (v34)~Prey (v38): XMA1, Just Cause (v39): XMA2 */ + case 1: xwb.codec = xwb.version <= XACT2_1_MAX ? XMA1 : XMA2; break; case 2: xwb.codec = MS_ADPCM; break; default: goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb_xsb.h b/Frameworks/vgmstream/vgmstream/src/meta/xwb_xsb.h index 92435673c..0177c04d1 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb_xsb.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb_xsb.h @@ -3,12 +3,12 @@ #include "meta.h" #include "../util/companion_files.h" -#define XSB_XACT1_0_MAX 5 /* Unreal Championship (Xbox) */ -#define XSB_XACT1_1_MAX 8 /* Die Hard: Vendetta (Xbox) */ -#define XSB_XACT1_2_MAX 11 /* other Xbox games */ -#define XSB_XACT2_0_MAX 34 /* Table Tennis (v34) */ -//#define XSB_XACT2_1_MAX 38 /* Prey (v38) */ // v39 too? -#define XSB_XACT2_2_MAX 41 /* other PC/X360 games */ +#define XSB_XACT1_0_MAX 5 // 0x05 // Unreal Championship (Xbox) +#define XSB_XACT1_1_MAX 8 // 0x08 // Die Hard: Vendetta (Xbox) +#define XSB_XACT1_2_MAX 11 // 0x0B // other Xbox games +#define XSB_XACT2_0_MAX 34 // 0x22 // Table Tennis (v34) +//#define XSB_XACT2_1_MAX 38 // 0x26 // Prey (v38) // v39 too? +#define XSB_XACT2_2_MAX 41 // 0x29 // other PC/X360 games typedef struct { @@ -83,8 +83,8 @@ static void xsb_check_stream(xsb_header *xsb, int stream_index, int wavebank_ind static int parse_xsb_old_cue_entry(xsb_header *xsb, STREAMFILE *sf, off_t name_offset, int entry) { - int32_t (*read_s32)(off_t,STREAMFILE*) = xsb->big_endian ? read_s32be : read_s32le; - int16_t (*read_s16)(off_t,STREAMFILE*) = xsb->big_endian ? read_s16be : read_s16le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; uint8_t flags, subflags; uint32_t sound_type, sound_size; int stream_index, wavebank_index; @@ -259,8 +259,8 @@ fail: * - others */ static int parse_xsb_old_cues(xsb_header *xsb, STREAMFILE *sf) { - int32_t (*read_s32)(off_t,STREAMFILE*) = xsb->big_endian ? read_s32be : read_s32le; - int16_t (*read_s16)(off_t,STREAMFILE*) = xsb->big_endian ? read_s16be : read_s16le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; //uint16_t flags; int cue_entry; off_t offset, name_offset, jump_offset; @@ -313,8 +313,8 @@ static int parse_xsb_old_cues(xsb_header *xsb, STREAMFILE *sf) { } static int parse_xsb_clip(xsb_header *xsb, off_t offset, off_t name_offset, STREAMFILE *sf) { - uint32_t (*read_u32)(off_t,STREAMFILE*) = xsb->big_endian ? read_u32be : read_u32le; - int16_t (*read_s16)(off_t,STREAMFILE*) = xsb->big_endian ? read_s16be : read_s16le; + read_u32_t read_u32 = xsb->big_endian ? read_u32be : read_u32le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; uint32_t flags; int stream_index, wavebank_index; @@ -478,8 +478,8 @@ fail: } static int parse_xsb_sound(xsb_header *xsb, off_t offset, off_t name_offset, STREAMFILE *sf) { - int32_t (*read_s32)(off_t,STREAMFILE*) = xsb->big_endian ? read_s32be : read_s32le; - int16_t (*read_s16)(off_t,STREAMFILE*) = xsb->big_endian ? read_s16be : read_s16le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; uint8_t flags; int stream_index = 0, wavebank_index = 0; @@ -548,9 +548,9 @@ static int parse_xsb_sound(xsb_header *xsb, off_t offset, off_t name_offset, STR } static int parse_xsb_variation(xsb_header *xsb, off_t offset, off_t name_offset, STREAMFILE *sf) { - int32_t (*read_s32)(off_t,STREAMFILE*) = xsb->big_endian ? read_s32be : read_s32le; - uint16_t (*read_u16)(off_t,STREAMFILE*) = xsb->big_endian ? read_u16be : read_u16le; - int16_t (*read_s16)(off_t,STREAMFILE*) = xsb->big_endian ? read_s16be : read_s16le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; + read_u16_t read_u16 = xsb->big_endian ? read_u16be : read_u16le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; uint16_t flags; int stream_index, wavebank_index; @@ -639,7 +639,7 @@ fail: static int parse_xsb_cues(xsb_header *xsb, STREAMFILE *sf) { - int32_t (*read_s32)(off_t,STREAMFILE*) = xsb->big_endian ? read_s32be : read_s32le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; uint8_t flags; off_t offset, name_offset, sound_offset; @@ -712,9 +712,6 @@ static int parse_xsb_cues(xsb_header *xsb, STREAMFILE *sf) { * - https://github.com/espes/MacTerrariaWrapper/tree/master/xactxtract */ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { - int32_t (*read_s32)(off_t,STREAMFILE*) = NULL; - int16_t (*read_s16)(off_t,STREAMFILE*) = NULL; - /* check header */ if ((read_u32be(0x00,sf) != 0x5344424B) && /* "SDBK" (LE) */ @@ -722,14 +719,14 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { goto fail; xsb->big_endian = (read_u32be(0x00,sf) == 0x4B424453); /* "KBDS" */ - read_s32 = xsb->big_endian ? read_s32be : read_s32le; - read_s16 = xsb->big_endian ? read_s16be : read_s16le; + read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; + read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; /* parse sound bank header */ xsb->version = read_s16(0x04, sf); /* tool version */ if (xsb->version <= XSB_XACT1_0_MAX) { - /* 06(2): crc */ + /* 06(2): CRC-16/IBM-SDLC of data starting from 0x08 */ xsb->wavebanks_offset = read_s32(0x08, sf); /* 0c(4): unknown1 offset (entry: 0x04) */ /* 10(4): unknown2 offset */ @@ -748,7 +745,7 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { } else if (xsb->version <= XSB_XACT1_1_MAX) { - /* 06(2): crc */ + /* 06(2): CRC-16/IBM-SDLC of data starting from 0x08 */ xsb->wavebanks_offset = read_s32(0x08, sf); /* 0c(4): unknown1 offset (entry: 0x04) */ /* 10(4): unknown2 offset */ @@ -767,7 +764,7 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { xsb->entry_size = 0x14; } else if (xsb->version <= XSB_XACT1_2_MAX) { - /* 06(2): crc */ + /* 06(2): CRC-16/IBM-SDLC of data starting from 0x08 */ xsb->wavebanks_offset = read_s32(0x08, sf); /* 0c(4): unknown1 offset (entry: 0x14) */ /* 10(4): unknown2 offset (entry: variable) */ @@ -787,7 +784,7 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { xsb->entry_size = 0x14; } else if (xsb->version <= XSB_XACT2_2_MAX) { - /* 06(2): crc */ + /* 06(2): CRC-16/IBM-SDLC of data starting from 0x08 (always LE) */ /* 08(1): platform? (3=X360) */ xsb->simple_cues_count = read_s16(0x09, sf); xsb->complex_cues_count = read_s16(0x0B, sf); @@ -813,7 +810,7 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { } else { /* 06(2): format version */ - /* 08(2): crc (fcs16 checksum of all following data) */ + /* 08(2): CRC-16/IBM-SDLC of data starting from 0x12 (always LE) */ /* 0a(4): last modified low */ /* 0e(4): last modified high */ /* 12(1): platform? (1=PC, 3=X360) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c b/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c deleted file mode 100644 index 5b73520d7..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* ZWDSP (hcs' custom DSP files from Zack & Wiki) */ -VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int second_channel_start; - int loop_flag; - int channel_count = 2; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("zwdsp",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */ - goto fail; - - /* Retrieve the loop flag, some files have 0x0 and some 0x02 as "no loop" */ - - switch (read_32bitBE(0x10, streamFile)) { - case 0: - case 2: - loop_flag = 0; - break; - default: - loop_flag = 1; - } - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x90; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x08,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x10,streamFile)*14/8/channel_count; - vgmstream->loop_end_sample = read_32bitBE(0x14,streamFile)*14/8/channel_count; - // frequently end sample is one more than total samples in file - if (vgmstream->loop_end_sample > vgmstream->num_samples) - { - vgmstream->loop_end_sample = vgmstream->num_samples; - } - } - - - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_ZWDSP; - - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); - } - if (vgmstream->channels == 2) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x60+i*2,streamFile); - } - } - } - - second_channel_start = (get_streamfile_size(streamFile)+start_offset)/2; - { - 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[0].channel_start_offset=start_offset; - if (channel_count == 2) { - if (second_channel_start == -1) goto fail; - vgmstream->ch[1].channel_start_offset=second_channel_start; - } - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/util/meta_utils.c b/Frameworks/vgmstream/vgmstream/src/util/meta_utils.c index bea8b0608..e310305ce 100644 --- a/Frameworks/vgmstream/vgmstream/src/util/meta_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/util/meta_utils.c @@ -15,6 +15,11 @@ VGMSTREAM* alloc_metastream(meta_header_t* h) { return NULL; } + if (h->has_subsongs && h->has_empty_banks && h->total_subsongs == 0) { + vgm_logi("VGMSTREAM: bank has no subsongs (ignore)\n"); + return NULL; + } + if (h->has_subsongs && (h->target_subsong < 0 || h->target_subsong > h->total_subsongs || h->total_subsongs < 1)) { VGM_LOG("meta: wrong subsongs %i vs %i\n", h->target_subsong, h->total_subsongs); return NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/util/meta_utils.h b/Frameworks/vgmstream/vgmstream/src/util/meta_utils.h index 3e7e31077..95540dc29 100644 --- a/Frameworks/vgmstream/vgmstream/src/util/meta_utils.h +++ b/Frameworks/vgmstream/vgmstream/src/util/meta_utils.h @@ -56,6 +56,7 @@ typedef struct { bool open_stream; bool has_subsongs; + bool has_empty_banks; bool allow_dual_stereo; } meta_header_t; diff --git a/Frameworks/vgmstream/vgmstream/src/util/sf_utils.c b/Frameworks/vgmstream/vgmstream/src/util/sf_utils.c index 03e1723a7..aa6ef2d13 100644 --- a/Frameworks/vgmstream/vgmstream/src/util/sf_utils.c +++ b/Frameworks/vgmstream/vgmstream/src/util/sf_utils.c @@ -2,6 +2,7 @@ #include "../vgmstream.h" #include "reader_sf.h" #include "paths.h" +#include "log.h" /* change pathname's extension to another (or add it if extensionless) */ @@ -34,12 +35,25 @@ STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) { return open_streamfile(sf, filename); } -STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { +static STREAMFILE* open_streamfile_internal(STREAMFILE* sf, const char* filename, bool allow_relpaths) { char fullname[PATH_LIMIT]; char partname[PATH_LIMIT]; char *path, *name, *otherpath; - if (!sf || !filename || !filename[0]) return NULL; + if (!sf || !filename || !filename[0]) + return NULL; + + // Some formats open companion files in current dir or subfolders. Relative paths are restricted by default + // for better control access. Mainly for doc purposes (most formats wouldn't need that), since + // the security risk of a format opening an arbitrary file is low given regular .m3u allow arbitrary paths + // anyway, and without RCE it can't leave your system (and web player can't read the filesystem). + if (!allow_relpaths) { + // disallow relative or absolute paths (crafty users could mimic plugin's internal URIs though) + if (strstr(filename, "..") || strstr(filename, ":\\") || filename[0] == '/') { + VGM_LOG("SF: ignored relative path %s\n", filename); + return NULL; + } + } get_streamfile_name(sf, fullname, sizeof(fullname)); @@ -93,6 +107,14 @@ STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { return open_streamfile(sf, fullname); } +STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { + return open_streamfile_internal(sf, filename, false); +} + +STREAMFILE* open_streamfile_by_pathname(STREAMFILE* sf, const char* filename) { + return open_streamfile_internal(sf, filename, true); +} + /* ************************************************************************* */ int check_extensions(STREAMFILE* sf, const char* cmp_exts) { diff --git a/Frameworks/vgmstream/vgmstream/src/util/sf_utils.h b/Frameworks/vgmstream/vgmstream/src/util/sf_utils.h index c1260bfe5..0b1034919 100644 --- a/Frameworks/vgmstream/vgmstream/src/util/sf_utils.h +++ b/Frameworks/vgmstream/vgmstream/src/util/sf_utils.h @@ -8,11 +8,14 @@ * Can be used to get companion headers. */ STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext); -/* Opens a STREAMFILE from a base path + new filename. - * Can be used to get companion files. Relative paths like - * './filename', '../filename', 'dir/filename' also work. */ +/* Opens a STREAMFILE from a base path + new filename. Can be used to get companion files. + * Subfolders like 'dir/filename' also work (not as common but some formats do use it). */ STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename); +/* Same as above, but relative paths like '../filename' also work. + * Not much difference but helps identifying which formats need prev folders */ +STREAMFILE* open_streamfile_by_pathname(STREAMFILE* sf, const char* filename); + /* various STREAMFILE helpers functions */ /* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 7512c94eb..5a7d8c844 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -300,8 +300,14 @@ void reset_vgmstream(VGMSTREAM* vgmstream); /* close an open vgmstream */ void close_vgmstream(VGMSTREAM* vgmstream); +// If you are using vgmstream as a library and wonder what happened to render_vgmstream(), you can use +// render_vgmstream2() for the time being, it's 100% the same (it was renamed to bring this into attention, +// typedef as needed). However, please migrate to the public API (see libvgmstream.h) instead, it's +// fairly straightforward (see "Use external API" and related commits for various plugins). +// In next versions the "API" in this .h will be removed without warning as it wasn't really intended to be +// used by external projects. I hate breaking things but it's becoming very hard to improve anything otherwise, sorry. /* Decode data into sample buffer. Returns < sample_count on stream end */ -int render_vgmstream(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream); +int render_vgmstream2(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream); /* Seek to sample position (next render starts from that point). Use only after config is set (vgmstream_apply_config) */ void seek_vgmstream(VGMSTREAM* vgmstream, int32_t seek_sample); diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c b/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c index 0e42810d7..59d15bd95 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c @@ -9,7 +9,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_brwav, init_vgmstream_bfwav, init_vgmstream_bcwav, - init_vgmstream_brwar, + init_vgmstream_rwar, init_vgmstream_nds_strm, init_vgmstream_afc, init_vgmstream_ast, @@ -210,7 +210,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mtaf, init_vgmstream_alp, init_vgmstream_wpd, - init_vgmstream_mn_str, init_vgmstream_mcss, init_vgmstream_ps2_hsf, init_vgmstream_ivag, @@ -338,7 +337,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_bnk_sony, init_vgmstream_nus3bank, init_vgmstream_sscf, - init_vgmstream_dsp_sps_n1, init_vgmstream_dsp_itl_ch, init_vgmstream_a2m, init_vgmstream_ahv, @@ -512,6 +510,8 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_oor, init_vgmstream_mio, init_vgmstream_audiopkg, + init_vgmstream_swar, + init_vgmstream_ivb, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_agsc, @@ -559,7 +559,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_raw_pcm, /* .raw raw PCM */ init_vgmstream_raw_s14_sss, /* .s14/sss raw siren14 */ init_vgmstream_exakt_sc, /* .sc raw PCM */ - init_vgmstream_zwdsp, /* fake format */ init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */ init_vgmstream_rwsd, /* crap, to be removed */ #ifdef VGM_USE_FFMPEG diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h b/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h index 884308e24..8ccd9fe78 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h @@ -384,7 +384,6 @@ typedef enum { meta_SEG, meta_RIFF_IMA, meta_KNON, - meta_ZWDSP, /* Zack and Wiki */ meta_VGS, /* Guitar Hero Encore - Rocks the 80s */ meta_DCS_WAV, meta_SMP, @@ -506,7 +505,6 @@ typedef enum { meta_MTAF, meta_ALP, meta_WPD, - meta_MN_STR, /* Mini Ninjas (PC/PS3/WII) */ meta_MCSS, meta_PS2_HSF, /* Lowrider (PS2) */ meta_IVAG, @@ -598,7 +596,6 @@ typedef enum { meta_HD3_BD3, /* Sony PS3 bank */ meta_BNK_SONY, /* Sony Scream Tool bank */ meta_SSCF, - meta_DSP_VAG, /* Penny-Punching Princess (Switch) sfx */ meta_DSP_ITL, /* Charinko Hero (GC) */ meta_A2M, /* Scooby-Doo! Unmasked (PS2) */ meta_AHV, /* Headhunter (PS2) */ @@ -722,6 +719,8 @@ typedef enum { meta_OOR, meta_MIO, meta_AUDIOPKG, + meta_SWAR, + meta_IVB, } meta_t; #endif