From 636120c9d54e5929f7ec188ef06bd74a528cf13c Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sun, 20 Jun 2021 19:36:12 -0700 Subject: [PATCH] Updated VGMStream to r1050-3774-gbecac809 --- .../libvgmstream.xcodeproj/project.pbxproj | 24 +- .../vgmstream/vgmstream/src/coding/coding.h | 6 +- .../vgmstream/src/coding/msadpcm_decoder.c | 132 ++-- .../vgmstream/src/coding/pcm_decoder.c | 10 +- .../vgmstream/src/coding/psx_decoder.c | 4 +- Frameworks/vgmstream/vgmstream/src/decode.c | 3 +- Frameworks/vgmstream/vgmstream/src/formats.c | 12 +- .../vgmstream/src/layout/blocked_thp.c | 20 +- .../vgmstream/vgmstream/src/meta/Cstr.c | 5 +- Frameworks/vgmstream/vgmstream/src/meta/acb.c | 25 +- .../src/meta/{ads.c => ads_midway.c} | 158 ++-- Frameworks/vgmstream/vgmstream/src/meta/awb.c | 22 +- Frameworks/vgmstream/vgmstream/src/meta/cpk.c | 5 +- .../vgmstream/vgmstream/src/meta/csmp.c | 110 +-- .../vgmstream/vgmstream/src/meta/ffmpeg.c | 4 + .../vgmstream/vgmstream/src/meta/ktsr.c | 3 +- Frameworks/vgmstream/vgmstream/src/meta/kwb.c | 83 +- .../vgmstream/vgmstream/src/meta/meta.h | 14 +- .../vgmstream/vgmstream/src/meta/msb_msh.c | 23 +- .../vgmstream/src/meta/msf_banpresto.c | 124 +-- .../vgmstream/vgmstream/src/meta/msf_konami.c | 116 +-- .../vgmstream/vgmstream/src/meta/ngca.c | 68 -- .../vgmstream/vgmstream/src/meta/ps2_ads.c | 736 +++++++++--------- .../vgmstream/vgmstream/src/meta/riff.c | 1 + .../vgmstream/src/meta/{ps2_rxws.c => rxws.c} | 135 ++-- .../vgmstream/vgmstream/src/meta/sqex_scd.c | 208 +++-- .../vgmstream/src/meta/sqex_scd_streamfile.h | 92 --- Frameworks/vgmstream/vgmstream/src/meta/thp.c | 34 +- .../vgmstream/vgmstream/src/meta/ubi_bao.c | 61 +- .../vgmstream/vgmstream/src/meta/ubi_sb.c | 59 +- .../vgmstream/vgmstream/src/meta/ue4opus.c | 123 ++- Frameworks/vgmstream/vgmstream/src/plugins.c | 14 + Frameworks/vgmstream/vgmstream/src/plugins.h | 5 +- .../vgmstream/vgmstream/src/streamfile.c | 17 +- .../vgmstream/vgmstream/src/streamfile.h | 4 +- .../vgmstream/vgmstream/src/vgmstream.c | 26 +- .../vgmstream/vgmstream/src/vgmstream.h | 7 +- 37 files changed, 1171 insertions(+), 1322 deletions(-) rename Frameworks/vgmstream/vgmstream/src/meta/{ads.c => ads_midway.c} (50%) delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ngca.c rename Frameworks/vgmstream/vgmstream/src/meta/{ps2_rxws.c => rxws.c} (52%) delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index c43831905..68d8e6454 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -155,7 +155,6 @@ 8349A9091FE6258200E26435 /* pc_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F01FE6257C00E26435 /* pc_ast.c */; }; 8349A90A1FE6258200E26435 /* sab.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F11FE6257D00E26435 /* sab.c */; }; 8349A90B1FE6258200E26435 /* ps2_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F21FE6257D00E26435 /* ps2_pcm.c */; }; - 8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */; }; 8349A90D1FE6258200E26435 /* ubi_sb.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F41FE6257D00E26435 /* ubi_sb.c */; }; 8349A90E1FE6258200E26435 /* scd_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8349A8F51FE6257D00E26435 /* scd_pcm.c */; }; 8349A90F1FE6258200E26435 /* aix_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 8349A8F61FE6257E00E26435 /* aix_streamfile.h */; }; @@ -266,7 +265,6 @@ 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2918BDC2180095E648 /* 2dx9.c */; }; 836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; }; 836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; }; - 836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; }; 836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; }; 836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; }; 836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; }; @@ -333,7 +331,6 @@ 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7B18BDC2180095E648 /* ngc_ssm.c */; }; 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */; }; 836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ngc_ymf.c */; }; - 836F6FBB18BDC2190095E648 /* ngca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7F18BDC2180095E648 /* ngca.c */; }; 836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; }; 836F6FBF18BDC2190095E648 /* otm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8318BDC2180095E648 /* otm.c */; }; 836F6FC018BDC2190095E648 /* p3d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8418BDC2180095E648 /* p3d.c */; }; @@ -447,7 +444,6 @@ 83709E051ECBC1A4005C03D3 /* gtd.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709DFF1ECBC1A4005C03D3 /* gtd.c */; }; 83709E061ECBC1A4005C03D3 /* mc3.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E001ECBC1A4005C03D3 /* mc3.c */; }; 83709E071ECBC1A4005C03D3 /* mss.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E011ECBC1A4005C03D3 /* mss.c */; }; - 83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E021ECBC1A4005C03D3 /* ps2_rxws.c */; }; 83709E091ECBC1A4005C03D3 /* ta_aac.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E031ECBC1A4005C03D3 /* ta_aac.c */; }; 83709E0D1ECBC1C3005C03D3 /* mc3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */; }; 83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */; }; @@ -497,6 +493,8 @@ 837CEB0423487F2C00E62A4A /* jstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEAEF23487F2C00E62A4A /* jstm.c */; }; 837CEB0523487F2C00E62A4A /* sqex_sead_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */; }; 837CEB072348809400E62A4A /* seb.c in Sources */ = {isa = PBXBuildFile; fileRef = 837CEB062348809400E62A4A /* seb.c */; }; + 83852B0B2680247900378854 /* rxws.c in Sources */ = {isa = PBXBuildFile; fileRef = 83852B092680247900378854 /* rxws.c */; }; + 83852B0C2680247900378854 /* ads_midway.c in Sources */ = {isa = PBXBuildFile; fileRef = 83852B0A2680247900378854 /* ads_midway.c */; }; 8385D4E6245174C700FF8E67 /* diva.c in Sources */ = {isa = PBXBuildFile; fileRef = 8385D4E2245174C600FF8E67 /* diva.c */; }; 838BDB681D3AF70D0022CA6F /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB671D3AF70D0022CA6F /* libz.tbd */; }; 838BDB6A1D3AF7140022CA6F /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 838BDB691D3AF7140022CA6F /* libiconv.tbd */; }; @@ -949,7 +947,6 @@ 8349A8F01FE6257C00E26435 /* pc_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_ast.c; sourceTree = ""; }; 8349A8F11FE6257D00E26435 /* sab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sab.c; sourceTree = ""; }; 8349A8F21FE6257D00E26435 /* ps2_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pcm.c; sourceTree = ""; }; - 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_scd_streamfile.h; sourceTree = ""; }; 8349A8F41FE6257D00E26435 /* ubi_sb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_sb.c; sourceTree = ""; }; 8349A8F51FE6257D00E26435 /* scd_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_pcm.c; sourceTree = ""; }; 8349A8F61FE6257E00E26435 /* aix_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aix_streamfile.h; sourceTree = ""; }; @@ -1060,7 +1057,6 @@ 836F6E2918BDC2180095E648 /* 2dx9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 2dx9.c; sourceTree = ""; }; 836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = ""; }; 836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = ""; }; - 836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = ""; }; 836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = ""; }; 836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = ""; }; 836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = ""; }; @@ -1127,7 +1123,6 @@ 836F6E7B18BDC2180095E648 /* ngc_ssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ssm.c; sourceTree = ""; }; 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_tydsp.c; sourceTree = ""; }; 836F6E7E18BDC2180095E648 /* ngc_ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ymf.c; sourceTree = ""; }; - 836F6E7F18BDC2180095E648 /* ngca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngca.c; sourceTree = ""; }; 836F6E8118BDC2180095E648 /* nwa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa.c; sourceTree = ""; }; 836F6E8318BDC2180095E648 /* otm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = otm.c; sourceTree = ""; }; 836F6E8418BDC2180095E648 /* p3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p3d.c; sourceTree = ""; }; @@ -1241,7 +1236,6 @@ 83709DFF1ECBC1A4005C03D3 /* gtd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gtd.c; sourceTree = ""; }; 83709E001ECBC1A4005C03D3 /* mc3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3.c; sourceTree = ""; }; 83709E011ECBC1A4005C03D3 /* mss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mss.c; sourceTree = ""; }; - 83709E021ECBC1A4005C03D3 /* ps2_rxws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rxws.c; sourceTree = ""; }; 83709E031ECBC1A4005C03D3 /* ta_aac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ta_aac.c; sourceTree = ""; }; 83709E0B1ECBC1C3005C03D3 /* mc3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mc3_decoder.c; sourceTree = ""; }; 83709E0C1ECBC1C3005C03D3 /* psv_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psv_decoder.c; sourceTree = ""; }; @@ -1291,6 +1285,8 @@ 837CEAEF23487F2C00E62A4A /* jstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = jstm.c; sourceTree = ""; }; 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sqex_sead_streamfile.h; sourceTree = ""; }; 837CEB062348809400E62A4A /* seb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seb.c; sourceTree = ""; }; + 83852B092680247900378854 /* rxws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rxws.c; sourceTree = ""; }; + 83852B0A2680247900378854 /* ads_midway.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads_midway.c; sourceTree = ""; }; 8385D4E2245174C600FF8E67 /* diva.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = diva.c; sourceTree = ""; }; 838BDB671D3AF70D0022CA6F /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; 838BDB691D3AF7140022CA6F /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; }; @@ -1772,7 +1768,7 @@ 83F2CCE125A5B41600F46FA8 /* acx.c */, 83AA7F7A2519C042004C5298 /* adp_konami.c */, 834FE0CF215C79E8000A5D3D /* adpcm_capcom.c */, - 836F6E2C18BDC2180095E648 /* ads.c */, + 83852B0A2680247900378854 /* ads_midway.c */, 8349A9021FE6258100E26435 /* adx_keys.h */, 831BA60E1EAC61A500CF89B0 /* adx.c */, 8349A9001FE6258000E26435 /* afc.c */, @@ -1965,7 +1961,6 @@ 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */, 831BD11F1EEE1CF200198540 /* ngc_ulw.c */, 836F6E7E18BDC2180095E648 /* ngc_ymf.c */, - 836F6E7F18BDC2180095E648 /* ngca.c */, 83C727FC22BC893900678B4A /* nps.c */, 837CEAE223487F2A00E62A4A /* nub.c */, 832BF81B21E0514B006F50F1 /* nus3audio.c */, @@ -2028,7 +2023,6 @@ 836F6EB318BDC2180095E648 /* ps2_pnb.c */, 836F6EB618BDC2180095E648 /* ps2_rnd.c */, 836F6EB718BDC2180095E648 /* ps2_rstm.c */, - 83709E021ECBC1A4005C03D3 /* ps2_rxws.c */, 836F6EBA18BDC2180095E648 /* ps2_sfs.c */, 836F6EBB18BDC2180095E648 /* ps2_sl3.c */, 836F6EBC18BDC2180095E648 /* ps2_smpl.c */, @@ -2072,6 +2066,7 @@ 836F6EB818BDC2180095E648 /* rws.c */, 836F6EE818BDC2190095E648 /* rwsd.c */, 836F6EE918BDC2190095E648 /* rwx.c */, + 83852B092680247900378854 /* rxws.c */, 836F6EEA18BDC2190095E648 /* s14_sss.c */, 83AA7F772519C042004C5298 /* sab_streamfile.h */, 8349A8F11FE6257D00E26435 /* sab.c */, @@ -2101,7 +2096,6 @@ 83A21F82201D8981000F04B9 /* sps_n1.c */, 836F6EF318BDC2190095E648 /* spt_spd.c */, 834FE0D6215C79E9000A5D3D /* sqex_scd_sscf.c */, - 8349A8F31FE6257D00E26435 /* sqex_scd_streamfile.h */, 836F6EF418BDC2190095E648 /* sqex_scd.c */, 837CEAF023487F2C00E62A4A /* sqex_sead_streamfile.h */, 83A21F84201D8981000F04B9 /* sqex_sead.c */, @@ -2333,7 +2327,6 @@ 83031EDA243C510500C3F3E0 /* mul_streamfile.h in Headers */, 83C7281822BC893D00678B4A /* sfh_streamfile.h in Headers */, 834FE0EF215C79ED000A5D3D /* xvag_streamfile.h in Headers */, - 8349A90C1FE6258200E26435 /* sqex_scd_streamfile.h in Headers */, 83031EC4243C50A800C3F3E0 /* circus_decoder_miniz.h in Headers */, 8349A91B1FE6258200E26435 /* adx_keys.h in Headers */, 836F6F4D18BDC2190095E648 /* layout.h in Headers */, @@ -2601,7 +2594,6 @@ 83E7FD6525EF2B2400683FD2 /* tac.c in Sources */, 83C7281322BC893D00678B4A /* mta2.c in Sources */, 8306B0EF20984590000302D4 /* ubi_bao.c in Sources */, - 836F6FBB18BDC2190095E648 /* ngca.c in Sources */, 83AF2CCA26226BA500538240 /* exst.c in Sources */, 8306B0E220984590000302D4 /* smv.c in Sources */, 8349A91E1FE6258200E26435 /* bar.c in Sources */, @@ -2622,7 +2614,6 @@ 835C883622CC17BE001B4B3F /* bwav.c in Sources */, 8349A90A1FE6258200E26435 /* sab.c in Sources */, 83AF2CC926226BA500538240 /* gcub.c in Sources */, - 836F6F6818BDC2190095E648 /* ads.c in Sources */, 8306B08620984518000302D4 /* fadpcm_decoder.c in Sources */, 83AB8C761E8072A100086084 /* x360_ast.c in Sources */, 834FE105215C79ED000A5D3D /* xmd.c in Sources */, @@ -2738,6 +2729,7 @@ 837CEB0423487F2C00E62A4A /* jstm.c in Sources */, 83C7282022BC893D00678B4A /* dcs_wav.c in Sources */, 8306B0F220984590000302D4 /* ubi_jade.c in Sources */, + 83852B0C2680247900378854 /* ads_midway.c in Sources */, 836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */, 836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */, 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */, @@ -2794,7 +2786,6 @@ 836F704418BDC2190095E648 /* ws_aud.c in Sources */, 83031ED2243C50DF00C3F3E0 /* bkhd.c in Sources */, 8373342F23F60D4100DE14DC /* tgc.c in Sources */, - 83709E081ECBC1A4005C03D3 /* ps2_rxws.c in Sources */, 8373342823F60CDC00DE14DC /* fda.c in Sources */, 836F6F6D18BDC2190095E648 /* aifc.c in Sources */, 836F702218BDC2190095E648 /* rsd.c in Sources */, @@ -2954,6 +2945,7 @@ 832BF82621E0514B006F50F1 /* nwav.c in Sources */, 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, 8349A8E81FE6253900E26435 /* blocked_dec.c in Sources */, + 83852B0B2680247900378854 /* rxws.c in Sources */, 831BA6181EAC61A500CF89B0 /* adx.c in Sources */, 832BF82321E0514B006F50F1 /* imc.c in Sources */, 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h index 87d8d8971..ad9de1513 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/coding.h +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -90,7 +90,9 @@ void decode_ulaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, void decode_ulaw_int(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian); -size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); +int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); +int32_t pcm16_bytes_to_samples(size_t bytes, int channels); +int32_t pcm8_bytes_to_samples(size_t bytes, int channels); /* psx_decoder */ @@ -159,7 +161,7 @@ STREAMFILE* nwa_get_streamfile(nwa_codec_data* data); #define MSADPCM_MAX_BLOCK_SIZE 0x800 /* known max and RIFF spec seems to concur, while MS's encoders may be lower (typical stereo: 0x8c, 0x2C, 0x48, 0x400) */ void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do); -void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int config); void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); long msadpcm_bytes_to_samples(long bytes, int block_size, int channels); int msadpcm_check_coefs(STREAMFILE* sf, off_t offset); diff --git a/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c index 92e1949a3..67107bd63 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c @@ -22,14 +22,64 @@ static const int16_t msadpcm_coefs[7][2] = { { 392, -232 } }; - -/* Decodes MSADPCM as explained in the spec (RIFFNEW / msadpcm.c). - * Though RIFFNEW spec uses "predictor / 256", msadpcm.c uses "predictor >> 8" = diffs on negs (silly MS). - * SHR is also true in Windows msadp32.acm decoders (up to Win10), that seem to use same code. - * Some non-Windows implementations or engines (like UE4) use DIV though (more accurate). +/* Decodes MSADPCM as explained in the spec (RIFFNEW doc + msadpcm.c). + * Though RIFFNEW writes "predictor / 256" (DIV), msadpcm.c uses "predictor >> 8" (SHR). They may seem the + * same but on negative values SHR gets different results (-128 / 256 = 0; -128 >> 8 = -1) = some output diffs. + * SHR is true in Windows msadp32.acm decoders (up to Win10), while some non-Windows implementations or + * engines (like UE4) may use DIV. + * * On invalid coef index, msadpcm.c returns 0 decoded samples but here we clamp and keep on trucking. * In theory blocks may be 0-padded and should use samples_per_frame from header, in practice seems to * decode up to block length or available data. */ + +static int16_t msadpcm_adpcm_expand_nibble_shr(VGMSTREAMCHANNEL* stream, uint8_t byte, int shift) { + int32_t hist1, hist2, predicted; + int code = (shift) ? + get_high_nibble_signed(byte) : + get_low_nibble_signed (byte); + + hist1 = stream->adpcm_history1_16; + hist2 = stream->adpcm_history2_16; + predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1]; + predicted = predicted >> 8; /* 256 = FIXED_POINT_COEF_BASE (uses SHR instead) */ + predicted = predicted + (code * stream->adpcm_scale); + predicted = clamp16(predicted); /* lNewSample */ + + stream->adpcm_history2_16 = stream->adpcm_history1_16; + stream->adpcm_history1_16 = predicted; + + stream->adpcm_scale = (msadpcm_steps[code & 0xf] * stream->adpcm_scale) >> 8; /* not diffs vs DIV here (always >=0) */ + if (stream->adpcm_scale < 16) /* min delta */ + stream->adpcm_scale = 16; + + return predicted; +} + +static int16_t msadpcm_adpcm_expand_nibble_div(VGMSTREAMCHANNEL* stream, uint8_t byte, int shift) { + int32_t hist1, hist2, predicted; + + int code = (shift) ? + get_high_nibble_signed(byte) : + get_low_nibble_signed (byte); + + hist1 = stream->adpcm_history1_16; + hist2 = stream->adpcm_history2_16; + predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1]; + predicted = predicted / 256; /* 256 = FIXED_POINT_COEF_BASE */ + predicted = predicted + (code * stream->adpcm_scale); + predicted = clamp16(predicted); /* lNewSample */ + + stream->adpcm_history2_16 = stream->adpcm_history1_16; + stream->adpcm_history1_16 = predicted; + + stream->adpcm_scale = (msadpcm_steps[code & 0xf] * stream->adpcm_scale) / 256; /* 256 = FIXED_POINT_ADAPTION_BASE */ + if (stream->adpcm_scale < 16) /* min delta */ + stream->adpcm_scale = 16; + + return predicted; +} + + void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do) { VGMSTREAMCHANNEL *stream1, *stream2; uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0}; @@ -81,40 +131,20 @@ void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first /* decode nibbles */ for (i = first_sample; i < first_sample + samples_to_do; i++) { - int ch; + uint8_t byte = get_u8(frame+0x07*2+(i-2)); - for (ch = 0; ch < 2; ch++) { - VGMSTREAMCHANNEL* stream = &vgmstream->ch[ch]; - int32_t hist1, hist2, predicted; - uint8_t byte = get_u8(frame+0x07*2+(i-2)); - int sample_nibble = (ch == 0) ? /* L = high nibble first (iErrorDelta) */ - get_high_nibble_signed(byte) : - get_low_nibble_signed (byte); - - hist1 = stream->adpcm_history1_16; - hist2 = stream->adpcm_history2_16; - predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1]; - predicted = predicted / 256; /* 256 = FIXED_POINT_COEF_BASE (though MS code uses SHR) */ - predicted = predicted + (sample_nibble * stream->adpcm_scale); - outbuf[0] = clamp16(predicted); /* lNewSample */ - - stream->adpcm_history2_16 = stream->adpcm_history1_16; - stream->adpcm_history1_16 = outbuf[0]; - stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256; /* 256 = FIXED_POINT_ADAPTION_BASE */ - if (stream->adpcm_scale < 16) /* min delta */ - stream->adpcm_scale = 16; - - outbuf++; - } + *outbuf++ = msadpcm_adpcm_expand_nibble_shr(&vgmstream->ch[0], byte, 1); /* L */ + *outbuf++ = msadpcm_adpcm_expand_nibble_shr(&vgmstream->ch[1], byte, 0); /* R */ } } -void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { +void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int config) { VGMSTREAMCHANNEL* stream = &vgmstream->ch[channel]; uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0}; int i, frames_in; size_t bytes_per_frame, samples_per_frame; off_t frame_offset; + int is_shr = (config == 0); /* external interleave (variable size), mono */ bytes_per_frame = vgmstream->frame_size; @@ -150,25 +180,12 @@ void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspac /* decode nibbles */ for (i = first_sample; i < first_sample + samples_to_do; i++) { - int32_t hist1, hist2, predicted; uint8_t byte = get_u8(frame+0x07+(i-2)/2); - int sample_nibble = (i & 1) ? /* high nibble first */ - get_low_nibble_signed (byte) : - get_high_nibble_signed(byte); - - hist1 = stream->adpcm_history1_16; - hist2 = stream->adpcm_history2_16; - predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1]; - predicted = predicted / 256; - predicted = predicted + (sample_nibble * stream->adpcm_scale); - outbuf[0] = clamp16(predicted); - - stream->adpcm_history2_16 = stream->adpcm_history1_16; - stream->adpcm_history1_16 = outbuf[0]; - stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256; - if (stream->adpcm_scale < 16) /* min delta */ - stream->adpcm_scale = 16; + int shift = !(i & 1); /* high nibble first */ + outbuf[0] = is_shr ? + msadpcm_adpcm_expand_nibble_shr(stream, byte, shift) : + msadpcm_adpcm_expand_nibble_div(stream, byte, shift); outbuf += channelspacing; } } @@ -215,26 +232,11 @@ void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacin } /* decode nibbles */ - for (i = first_sample; i < first_sample+samples_to_do; i++) { - int32_t hist1,hist2, predicted; + for (i = first_sample; i < first_sample + samples_to_do; i++) { uint8_t byte = get_u8(frame+0x07+(i-2)/2); - int sample_nibble = (i & 1) ? /* low nibble first, unlike normal MSADPCM */ - get_high_nibble_signed(byte) : - get_low_nibble_signed (byte); - - hist1 = stream->adpcm_history1_16; - hist2 = stream->adpcm_history2_16; - predicted = hist1 * stream->adpcm_coef[0] + hist2 *stream->adpcm_coef[1]; - predicted = predicted >> 8; /* not DIV unlike spec */ - predicted = predicted + (sample_nibble * stream->adpcm_scale); - outbuf[0] = clamp16(predicted); - - stream->adpcm_history2_16 = stream->adpcm_history1_16; - stream->adpcm_history1_16 = outbuf[0]; - stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) >> 8; /* not DIV but same here (always >=0) */ - if (stream->adpcm_scale < 16) - stream->adpcm_scale = 16; + int shift = (i & 1); /* low nibble first, unlike normal MSADPCM */ + outbuf[0] = msadpcm_adpcm_expand_nibble_shr(stream, byte, shift); outbuf += channelspacing; } } diff --git a/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c index cb86e2d14..c1bc2c0b1 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c @@ -216,7 +216,15 @@ void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelsp } } -size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) { +int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) { if (channels <= 0 || bits_per_sample <= 0) return 0; return ((int64_t)bytes * 8) / channels / bits_per_sample; } + +int32_t pcm16_bytes_to_samples(size_t bytes, int channels) { + return pcm_bytes_to_samples(bytes, channels, 16); +} + +int32_t pcm8_bytes_to_samples(size_t bytes, int channels) { + return pcm_bytes_to_samples(bytes, channels, 8); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c index 00bb28107..f4bb7e438 100644 --- a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c +++ b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c @@ -358,7 +358,7 @@ size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_s size_t interleave_consumed = 0; - if (data_size == 0 || channels == 0 || (channels > 0 && interleave == 0)) + if (data_size == 0 || channels == 0 || (channels > 1 && interleave == 0)) return 0; offset = start_offset + data_size; @@ -405,7 +405,7 @@ size_t ps_find_padding(STREAMFILE *streamFile, off_t start_offset, size_t data_s interleave_consumed += 0x10; if (interleave_consumed == interleave) { interleave_consumed = 0; - offset -= interleave*(channels - 1); + offset -= interleave * (channels - 1); } } diff --git a/Frameworks/vgmstream/vgmstream/src/decode.c b/Frameworks/vgmstream/vgmstream/src/decode.c index a023a112e..db00ccea8 100644 --- a/Frameworks/vgmstream/vgmstream/src/decode.c +++ b/Frameworks/vgmstream/vgmstream/src/decode.c @@ -1290,7 +1290,8 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ if (vgmstream->channels == 1 || vgmstream->coding_type == coding_MSADPCM_int) { for (ch = 0; ch < vgmstream->channels; ch++) { decode_msadpcm_mono(vgmstream,buffer+ch, - vgmstream->channels,vgmstream->samples_into_block, samples_to_do, ch); + vgmstream->channels,vgmstream->samples_into_block, samples_to_do, ch, + vgmstream->codec_config); } } else if (vgmstream->channels == 2) { diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 7000bb450..040c4e0d2 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -311,7 +311,7 @@ static const char* extension_list[] = { "mdsp", "med", "mjb", - "mi4", + "mi4", //fake extension for .mib (renamed, to be removed) "mib", "mic", "mihb", @@ -353,7 +353,6 @@ static const char* extension_list[] = { "naac", "nds", "ndp", //fake extension/header id for .nds - "ngca", "nlsd", "nop", "nps", @@ -581,7 +580,6 @@ static const char* extension_list[] = { "wii", "wip", //txth/reserved [Colin McRae DiRT (PC)] "wlv", //txth/reserved [ToeJam & Earl III: Mission to Earth (DC)] - "wma", //common "wmus", "wp2", "wpd", @@ -658,6 +656,7 @@ static const char* common_extension_list[] = { "ogg", //common "opus", //common "wav", //common + "wma", //common }; @@ -921,7 +920,7 @@ static const meta_info meta_info_list[] = { {meta_DSP_STD, "Nintendo DSP header"}, {meta_DSP_CSTR, "Namco Cstr header"}, {meta_GCSW, "MileStone GCSW header"}, - {meta_PS2_SShd, "Sony ADS header"}, + {meta_ADS, "Sony ADS header"}, {meta_NPS, "Namco NPSF header"}, {meta_RWSD, "Nintendo RWSD header (single stream)"}, {meta_RWAR, "Nintendo RWAR header (single RWAV stream)"}, @@ -929,7 +928,7 @@ static const meta_info meta_info_list[] = { {meta_CWAV, "Nintendo CWAV header"}, {meta_FWAV, "Nintendo FWAV header"}, {meta_XA, "Sony XA header"}, - {meta_PS2_RXWS, "Sony RXWS header"}, + {meta_RXWS, "Sony RXWS header"}, {meta_RAW_INT, "PS2 .int raw header"}, {meta_PS2_OMU, "Alter Echo OMU Header"}, {meta_DSP_STM, "Intelligent Systems STM header"}, @@ -1080,7 +1079,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_TK5, "Tekken 5 Stream Header"}, {meta_PS2_SND, "Might and Magic SSND Header"}, {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, - {meta_ADS, "dhSS Header"}, + {meta_ADS_MIDWAY, "Midway ADS header"}, {meta_PS2_MCG, "Gunvari MCG Header"}, {meta_ZSD, "ZSD Header"}, {meta_REDSPARK, "RedSpark Header"}, @@ -1151,7 +1150,6 @@ static const meta_info meta_info_list[] = { {meta_MSF, "Sony MSF header"}, {meta_PS3_PAST, "SNDP header"}, {meta_SGXD, "Sony SGXD header"}, - {meta_NGCA, "NGCA header"}, {meta_WII_RAS, "RAS header"}, {meta_PS2_SPM, "SPM header"}, {meta_X360_TRA, "Terminal Reality .TRA raw header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked_thp.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked_thp.c index 1722e9e31..494b86f57 100644 --- a/Frameworks/vgmstream/vgmstream/src/layout/blocked_thp.c +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked_thp.c @@ -2,15 +2,15 @@ #include "../vgmstream.h" /* set up for the block at the given offset */ -void block_update_thp(off_t block_offset, VGMSTREAM *vgmstream) { +void block_update_thp(off_t block_offset, VGMSTREAM* vgmstream) { int i, j; - STREAMFILE *streamFile = vgmstream->ch[0].streamfile; + STREAMFILE* sf = vgmstream->ch[0].streamfile; off_t audio_offset; size_t next_block_size, video_size; - next_block_size = read_32bitBE(block_offset + 0x00, streamFile); + next_block_size = read_u32be(block_offset + 0x00, sf); /* 0x04: frame size previous */ - video_size = read_32bitBE(block_offset + 0x08,streamFile); + video_size = read_u32be(block_offset + 0x08,sf); /* 0x0c: audio size */ audio_offset = block_offset + 0x10 + video_size; @@ -21,21 +21,21 @@ void block_update_thp(off_t block_offset, VGMSTREAM *vgmstream) { /* block samples can be smaller than block size, normally in the last block, * but num_samples already takes that into account, so there is no real difference */ - vgmstream->current_block_size = read_32bitBE(audio_offset + 0x00, streamFile); - vgmstream->current_block_samples = read_32bitBE(audio_offset + 0x04, streamFile); + vgmstream->current_block_size = read_u32be(audio_offset + 0x00, sf); + vgmstream->current_block_samples = read_u32be(audio_offset + 0x04, sf); audio_offset += 0x08; for (i = 0; i < vgmstream->channels; i++) { off_t coef_offset = audio_offset + i*0x20; off_t hist_offset = audio_offset + vgmstream->channels*0x20 + i*0x04; - off_t data_offset = audio_offset + vgmstream->channels*0x24 + i*vgmstream->current_block_size; + off_t data_offset = audio_offset + 2*0x24 + i*vgmstream->current_block_size; /* reserved for 2 even in mono [WarioWare Inc. (GC)] */ for (j = 0; j < 16; j++) { - vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef_offset + (j*0x02),streamFile); + vgmstream->ch[i].adpcm_coef[j] = read_s16be(coef_offset + (j*0x02),sf); } - vgmstream->ch[i].adpcm_history1_16 = read_16bitBE(hist_offset + 0x00,streamFile); - vgmstream->ch[i].adpcm_history2_16 = read_16bitBE(hist_offset + 0x02,streamFile); + vgmstream->ch[i].adpcm_history1_16 = read_s16be(hist_offset + 0x00,sf); + vgmstream->ch[i].adpcm_history2_16 = read_s16be(hist_offset + 0x02,sf); vgmstream->ch[i].offset = data_offset; } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c index ecbd05c15..227c72331 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c @@ -44,7 +44,6 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) { loop_flag = (loop_start >= 0); start_offset = 0x20 + 0x60 * channels + first_skip; -#if 1 /* nonlooped tracks may not set first skip for no reason, but can be tested with initial p/s */ if (!loop_flag && channels == 2 && first_skip == 0) { while (first_skip < 0x800) { @@ -61,7 +60,7 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) { } if (first_skip > 0 && loop_start >= (interleave - first_skip)) loop_start = loop_start - (interleave - first_skip); -#endif + loop_start = loop_start * 2; /* Mr. Driller oddity, unreliable loop flag */ @@ -97,7 +96,7 @@ VGMSTREAM * init_vgmstream_cstr(STREAMFILE* sf) { vgmstream->interleave_first_block_size = interleave - first_skip; vgmstream->interleave_first_skip = first_skip; vgmstream->meta_type = meta_DSP_CSTR; -VGM_LOG("1=%x, =%x\n",vgmstream->interleave_first_block_size, vgmstream->interleave_first_skip); + dsp_read_coefs_be(vgmstream, sf, 0x3c, 0x60); if (!vgmstream_open_stream(vgmstream, sf, start_offset)) diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acb.c b/Frameworks/vgmstream/vgmstream/src/meta/acb.c index e5fbf35b0..0acad0a83 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/acb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/acb.c @@ -132,6 +132,7 @@ typedef struct { /* config */ int is_memory; int target_waveid; + int target_port; int has_TrackEventTable; int has_CommandTable; @@ -221,7 +222,7 @@ static void add_acb_name(acb_header* acb, int8_t Streaming) { /* OBJECT HANDLERS */ static int load_acb_waveform(acb_header* acb, int16_t Index) { - uint16_t Id; + uint16_t Id, PortNo; uint8_t Streaming; /* read Waveform[Index] */ @@ -231,18 +232,30 @@ static int load_acb_waveform(acb_header* acb, int16_t Index) { if (acb->is_memory) { if (!utf_query_u16(acb->WaveformTable, Index, "MemoryAwbId", &Id)) goto fail; + PortNo = 0xFFFF; } else { if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbId", &Id)) goto fail; + if (!utf_query_u16(acb->WaveformTable, Index, "StreamAwbPortNo", &PortNo)) + PortNo = 0; /* assumed */ } } + else { + PortNo = 0xFFFF; + } + if (!utf_query_u8(acb->WaveformTable, Index, "Streaming", &Streaming)) goto fail; - //;VGM_LOG("ACB: Waveform[%i]: Id=%i, Streaming=%i\n", Index, Id, Streaming); + //;VGM_LOG("ACB: Waveform[%i]: Id=%i, PortNo=%i, Streaming=%i\n", Index, Id, PortNo, Streaming); /* not found but valid */ if (Id != acb->target_waveid) return 1; + + /* correct AWB port (check ignored if set to -1) */ + if (acb->target_port >= 0 && PortNo != 0xFFFF && PortNo != acb->target_port) + return 1; + /* must match our target's (0=memory, 1=streaming, 2=memory (prefetch)+stream) */ if ((acb->is_memory && Streaming == 1) || (!acb->is_memory && Streaming == 0)) return 1; @@ -694,7 +707,7 @@ fail: } -void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is_memory) { +void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int port, int is_memory) { acb_header acb = {0}; int i, CueName_rows; @@ -722,9 +735,12 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is * Atom Craft may only target certain .acb versions so some links are later removed * Not all cues to point to Waveforms, some are just config events/commands. * .acb link to .awb by name (loaded manually), though they have a checksum/hash/header to validate. + * + * .acb can contain info for multiple .awb, that are loaded sequentially and assigned "port numbers" (0 to N). + * Both Wave ID and port number must be passed externally to find appropriate song name. */ - //;VGM_LOG("ACB: find waveid=%i\n", waveid); + //;VGM_LOG("ACB: find waveid=%i, port=%i\n", waveid, port); acb.acbFile = sf; @@ -732,6 +748,7 @@ void load_acb_wave_name(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int is if (!acb.Header) goto fail; acb.target_waveid = waveid; + acb.target_port = port; acb.is_memory = is_memory; acb.has_TrackEventTable = utf_query_data(acb.Header, 0, "TrackEventTable", NULL,NULL); acb.has_CommandTable = utf_query_data(acb.Header, 0, "CommandTable", NULL,NULL); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ads_midway.c similarity index 50% rename from Frameworks/vgmstream/vgmstream/src/meta/ads.c rename to Frameworks/vgmstream/vgmstream/src/meta/ads_midway.c index 692531ec0..cc9a2ef56 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ads.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ads_midway.c @@ -1,78 +1,80 @@ -#include "meta.h" -#include "../util.h" -#include "../coding/coding.h" - -/* ADS - from Gauntlet Dark Legacy (GC/Xbox) */ -VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count, codec; - - - /* check extension, case insensitive */ - if (!check_extensions(streamFile,"ads")) goto fail; - - if (read_32bitBE(0x00,streamFile) != 0x64685353) /* "dhSS" */ - goto fail; - if (read_32bitBE(0x20,streamFile) != 0x64625353) /* "dbSS" */ - goto fail; - - loop_flag = 1; - channel_count = read_32bitBE(0x10,streamFile); - - if (channel_count > 2) - goto fail; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); - - codec = read_32bitBE(0x08,streamFile); - switch (codec) { - case 0x00000020: /* GC */ - start_offset = 0x28 + 0x60 * channel_count; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0x28,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - if (channel_count == 1) { - vgmstream->layout_type = layout_none; - } else if (channel_count == 2) { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); - } - - dsp_read_coefs_be(vgmstream, streamFile, 0x44,0x60); - break; - - case 0x00000021: /* Xbox */ - start_offset = 0x28; - vgmstream->coding_type = coding_XBOX_IMA_int; - vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,streamFile), vgmstream->channels); - vgmstream->layout_type = channel_count == 1 ? layout_none : layout_interleave; - vgmstream->interleave_block_size = 0x24; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - break; - - default: - goto fail; - } - - vgmstream->meta_type = meta_ADS; - - if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +/* .ADS - from Gauntlet Dark Legacy (GC/Xbox) */ +VGMSTREAM* init_vgmstream_ads_midway(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels, codec; + + + /* checks */ + if (!check_extensions(sf,"ads")) + goto fail; + + /* fake PS2 .ads but BE */ + if (!is_id32be(0x00,sf, "dhSS")) + goto fail; + if (!is_id32be(0x20,sf, "dbSS")) + goto fail; + + loop_flag = 1; + channels = read_32bitBE(0x10,sf); + if (channels > 2) + goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitBE(0x0c,sf); + + codec = read_32bitBE(0x08,sf); + switch (codec) { + case 0x00000020: /* GC */ + start_offset = 0x28 + 0x60 * channels; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x28,sf); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if (channels == 1) { + vgmstream->layout_type = layout_none; + } else if (channels == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x14,sf); + } + + dsp_read_coefs_be(vgmstream, sf, 0x44,0x60); + break; + + case 0x00000021: /* Xbox */ + start_offset = 0x28; + vgmstream->coding_type = coding_XBOX_IMA_int; + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitBE(0x24,sf), vgmstream->channels); + vgmstream->layout_type = channels == 1 ? layout_none : layout_interleave; + vgmstream->interleave_block_size = 0x24; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + break; + + default: + goto fail; + } + + vgmstream->meta_type = meta_ADS_MIDWAY; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awb.c b/Frameworks/vgmstream/vgmstream/src/meta/awb.c index ece4b8f48..e5843529c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/awb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/awb.c @@ -190,6 +190,7 @@ fail: static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { int is_memory = (sf_acb != NULL); + int port = 0; /* .acb is passed when loading memory .awb inside .acb */ if (!is_memory) { @@ -198,7 +199,7 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre int len_name, len_cmp; /* try parsing TXTM if present */ - sf_acb = read_filemap_file(sf, 0); + sf_acb = read_filemap_file_pos(sf, 0, &port); /* try (name).awb + (name).awb */ if (!sf_acb) { @@ -233,27 +234,12 @@ static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre } } - /* try (name)_(name)_R001.awb + (name).acb [Sengoku Basara Battle Party (Mobile)] */ - if (!sf_acb) { - char *cmp = "_R001"; - get_streamfile_basename(sf, filename, sizeof(filename)); - len_name = strlen(filename); - len_cmp = strlen(cmp); - - if (len_name > len_cmp && strcmp(filename + len_name - len_cmp, cmp) == 0) { - filename[(len_name - len_cmp) / 2] = '\0'; - strcat(filename, ".acb"); - VGM_LOG("%s\n", filename); - sf_acb = open_streamfile_by_filename(sf, filename); - } - } - /* probably loaded */ - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); close_streamfile(sf_acb); } else { - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/cpk.c b/Frameworks/vgmstream/vgmstream/src/meta/cpk.c index 22dcccd6b..3e59c8aca 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/cpk.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/cpk.c @@ -222,6 +222,7 @@ fail: static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid) { int is_memory = (sf_acb != NULL); + int port = -1; /* cpk has no port numbers */ /* .acb is passed when loading memory .awb inside .acb */ if (!is_memory) { @@ -238,11 +239,11 @@ static void load_cpk_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre return; /* companion .acb probably loaded */ - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); close_streamfile(sf_acb); } else { - load_acb_wave_name(sf_acb, vgmstream, waveid, is_memory); + load_acb_wave_name(sf_acb, vgmstream, waveid, port, is_memory); } } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/csmp.c b/Frameworks/vgmstream/vgmstream/src/meta/csmp.c index 30915b290..c57cb8e9f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/csmp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/csmp.c @@ -1,55 +1,55 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */ -VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, first_offset = 0x08, chunk_offset; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "csmp")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x43534D50) /* "CSMP" */ - goto fail; - if (read_32bitBE(0x04, streamFile) != 1) /* version? */ - goto fail; - - if (!find_chunk(streamFile, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/ - goto fail; - - /* contains standard DSP header, but somehow some validations (start/loop ps) - * don't seem to work, so no point to handle as standard DSP */ - - channel_count = 1; - loop_flag = read_16bitBE(chunk_offset+0x0c,streamFile); - start_offset = chunk_offset + 0x60; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_CSMP; - vgmstream->sample_rate = read_32bitBE(chunk_offset+0x08,streamFile); - vgmstream->num_samples = read_32bitBE(chunk_offset+0x00,streamFile); - vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(chunk_offset+0x10,streamFile)); - vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bitBE(chunk_offset+0x14,streamFile))+1; - if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - dsp_read_coefs_be(vgmstream, streamFile, chunk_offset+0x1c, 0x00); - dsp_read_hist_be(vgmstream, streamFile, chunk_offset+0x40, 0x00); - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */ +VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, first_offset = 0x08, chunk_offset; + int loop_flag, channels; + + + /* checks */ + if (!check_extensions(sf, "csmp")) + goto fail; + if (!is_id32be(0x00, sf, "CSMP")) + goto fail; + if (read_u32be(0x04, sf) != 1) + goto fail; + + if (!find_chunk(sf, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/ + goto fail; + + /* contains standard DSP header, but somehow some validations (start/loop ps) + * don't seem to work, so no point to handle as standard DSP */ + + channels = 1; + loop_flag = read_s16be(chunk_offset+0x0c,sf); + start_offset = chunk_offset + 0x60; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_CSMP; + vgmstream->sample_rate = read_s32be(chunk_offset+0x08,sf); + vgmstream->num_samples = read_s32be(chunk_offset+0x00,sf); + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x10,sf)); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x14,sf)) + 1; + if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + dsp_read_coefs_be(vgmstream, sf, chunk_offset+0x1c, 0x00); + dsp_read_hist_be(vgmstream, sf, chunk_offset+0x40, 0x00); + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c index dacf66ded..0bade7e6a 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffmpeg.c @@ -35,6 +35,10 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { if (get_streamfile_size(sf) <= 0x1000) goto fail; + /* reject some formats handled elsewhere (better fail and check there than let buggy FFmpeg take over) */ + if (check_extensions(sf, "at3")) + goto fail; + if (target_subsong == 0) target_subsong = 1; /* init ffmpeg */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c b/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c index ce32b772b..42aab2222 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ktsr.c @@ -53,7 +53,7 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) { * This accepts ktsl2asbin with internal data, or opening external streams as subsongs. * Some info from KTSR.bt */ - if (read_u32be(0x00, sf) != 0x4B545352) /* "KTSR" */ + if (!is_id32be(0x00, sf, "KTSR")) goto fail; if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */ goto fail; @@ -482,6 +482,7 @@ static int parse_ktsr(ktsr_header* ktsr, STREAMFILE* sf) { case 0xBD888C36: /* config (floats, stream id, etc, may have extended name) */ case 0xC9C48EC1: /* unknown (has some string inside like "boss") */ case 0xA9D23BF1: /* "state container", some kind of config/floats, witgh names like 'State_bgm01'..N */ + case 0x836FBECA: /* unknown (~0x300, encrypted? table + data) */ break; case 0xC5CCCB70: /* sound (internal data or external stream) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/kwb.c b/Frameworks/vgmstream/vgmstream/src/meta/kwb.c index 746b57a6c..1d922564d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/kwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/kwb.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF } kwb_codec; +typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF, XMA2 } kwb_codec; typedef struct { int big_endian; @@ -187,6 +187,27 @@ static VGMSTREAM* init_vgmstream_koei_wavebank(kwb_header* kwb, STREAMFILE* sf_h break; +#ifdef VGM_USE_FFMPEG + case XMA2: { + uint8_t buf[0x100]; + size_t bytes, block_size, block_count; + + if (kwb->channels > 1) goto fail; + + block_size = 0x800; /* ? */ + block_count = kwb->stream_size / block_size; + + bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), vgmstream->num_samples, kwb->stream_size, kwb->channels, kwb->sample_rate, block_count, block_size); + vgmstream->codec_data = init_ffmpeg_header_offset(sf_b, buf,bytes, kwb->stream_offset, kwb->stream_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + xma_fix_raw_samples(vgmstream, sf_b, kwb->stream_offset, kwb->stream_size, 0, 0,0); /* assumed */ + break; + } +#endif + #ifdef VGM_USE_ATRAC9 case AT9: { atrac9_config cfg = {0}; @@ -357,7 +378,7 @@ static int parse_type_k4hd(kwb_header* kwb, off_t offset, off_t body_offset, STR ppva_offset += offset; /* PPVA table: */ - if (read_u32be(ppva_offset + 0x00, sf_h) != 0x50505641) /* "PPVA" */ + if (!is_id32be(ppva_offset + 0x00, sf_h, "PPVA")) goto fail; entry_size = read_u32le(ppva_offset + 0x08, sf_h); @@ -403,8 +424,57 @@ fail: } static int parse_type_sdsd(kwb_header* kwb, off_t offset, off_t body_offset, STREAMFILE* sf_h) { - /* has Vers, Head, Prog, Smpl sections (like Sony VABs) - unknown codec, blocked with some common start, variable sized */ + off_t smpl_offset, header_offset; + int entries, current_subsongs, relative_subsong; + size_t entry_size; + + + /* format somewhat similar to Sony VABs */ + /* 00: SDsdVers */ + /* 08: chunk size */ + /* 0c: null */ + /* 10: SDsdHead */ + /* 18: chunk size */ + /* 1c: ? size */ + /* 20: null */ + /* 24: SDsdProg offset ('program'? cues?) */ + /* 28: SDsdSmpl offset ('samples'? waves?) */ + /* rest: ? */ + smpl_offset = read_u32le(offset + 0x28, sf_h); + smpl_offset += offset; + + /* Smpl table: */ + if (!is_id64be(smpl_offset + 0x00, sf_h, "SDsdSmpl")) + goto fail; + + /* 0x08: ? */ + entries = read_u32le(smpl_offset + 0x0c, sf_h); + entry_size = 0x9c; + + current_subsongs = kwb->total_subsongs; + kwb->total_subsongs += entries; + if (kwb->target_subsong - 1 < current_subsongs || kwb->target_subsong > kwb->total_subsongs) + return 1; + kwb->found = 1; + + relative_subsong = kwb->target_subsong - current_subsongs; + header_offset = smpl_offset + 0x10 + (relative_subsong-1) * entry_size; + + kwb->stream_offset = read_u32le(header_offset + 0x00, sf_h); + /* 08: ? + channels? */ + /* 0c: bps? */ + kwb->sample_rate = read_u32le(header_offset + 0x0c, sf_h); + kwb->num_samples = read_u32le(header_offset + 0x10, sf_h) / sizeof(int16_t); /* PCM */ + /* rest: ? (flags, etc) */ + kwb->stream_size = read_u32le(header_offset + 0x44, sf_h); + + kwb->codec = XMA2; + kwb->channels = 1; + + kwb->stream_offset += body_offset; + + return 1; +fail: return 0; } @@ -429,8 +499,7 @@ static int parse_type_sdwi(kwb_header* kwb, off_t offset, off_t body_offset, STR smpl_offset += offset; /* Smpl table: */ - if (read_u32be(smpl_offset + 0x00, sf_h) != 0x53447364 && /* "SDsd" */ - read_u32be(smpl_offset + 0x04, sf_h) != 0x536D706C) /* "Smpl" */ + if (!is_id64be(smpl_offset + 0x00, sf_h, "SDsdSmpl")) goto fail; /* 0x08: ? */ @@ -534,7 +603,7 @@ static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) { goto fail; break; - case 0x53447364: /* "SDsd" (PS3? leftover files) */ + case 0x53447364: /* "SDsd" [Bladestorm Nightmare (PC)-X360 leftover files] */ if (!parse_type_sdsd(kwb, head_offset, body_offset, sf_h)) goto fail; break; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 2b9dea9a8..8c7077f67 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -66,8 +66,8 @@ VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rfrm(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_ads(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ads_container(STREAMFILE* sf); VGMSTREAM * init_vgmstream_nps(STREAMFILE *streamFile); @@ -79,8 +79,8 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_xa(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_rxws(STREAMFILE* sf); +VGMSTREAM * init_vgmstream_rxws_badrip(STREAMFILE* sf); VGMSTREAM * init_vgmstream_raw_int(STREAMFILE *streamFile); @@ -384,7 +384,7 @@ VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_ads_midway(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile); @@ -508,8 +508,6 @@ VGMSTREAM * init_vgmstream_ps3_past(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_sgxd(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ngca(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_spm(STREAMFILE* streamFile); @@ -848,7 +846,7 @@ VGMSTREAM * init_vgmstream_awb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_awb_memory(STREAMFILE * streamFile, STREAMFILE *acbFile); VGMSTREAM * init_vgmstream_acb(STREAMFILE * streamFile); -void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int is_memory); +void load_acb_wave_name(STREAMFILE *acbFile, VGMSTREAM* vgmstream, int waveid, int port, int is_memory); VGMSTREAM * init_vgmstream_rad(STREAMFILE * streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msb_msh.c b/Frameworks/vgmstream/vgmstream/src/meta/msb_msh.c index 14ade6c7a..4887fc69c 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/msb_msh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/msb_msh.c @@ -8,7 +8,9 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) { off_t start_offset, header_offset = 0; size_t stream_size; int loop_flag, channels, sample_rate; + int32_t loop_start, loop_end; int total_subsongs, target_subsong = sf->stream_index; + uint32_t config; /* checks */ @@ -20,12 +22,12 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) { if (read_u32le(0x00,sh) != get_streamfile_size(sh)) goto fail; - /* 0x04: unknown */ + /* 0x04: flags? (0x04/34*/ /* parse entries */ { int i; - int entries = read_s32le(0x08,sh); + int entries = read_s32le(0x08,sh); /* may be less than file size, or include dummies (all dummies is possible too) */ total_subsongs = 0; if (target_subsong == 0) target_subsong = 1; @@ -45,15 +47,20 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) { } - loop_flag = 0; - channels = 1; - stream_size = read_u32le(header_offset+0x00, sh); - if (read_u32le(header_offset+0x04, sh) != 0) /* stereo flag? */ - goto fail; + config = read_u32le(header_offset+0x04, sh); /* volume (0~100), null, null, loop (0/1) */ start_offset = read_u32le(header_offset+0x08, sh); sample_rate = read_u32le(header_offset+0x0c, sh); /* Ace Combat 2 seems to set wrong values but probably their bug */ + loop_flag = (config & 1); + channels = 1; + + /* rare [Dr. Seuss Cat in the Hat (PS2)] */ + if (loop_flag) { + /* when loop is set ADPCM has loop flags, but rarely appear too without loop set */ + loop_flag = ps_find_loop_offsets(sf, start_offset, stream_size, channels, 0, &loop_start, &loop_end); + } + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag); @@ -62,6 +69,8 @@ VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) { vgmstream->meta_type = meta_MSB_MSH; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; vgmstream->num_streams = total_subsongs; vgmstream->stream_size = stream_size; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c b/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c index 230cb9225..44c3a1637 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf_banpresto.c @@ -1,62 +1,62 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */ -VGMSTREAM * init_vgmstream_msf_banpresto_wmsf(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t subfile_offset = 0x10; - size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; - - - /* checks */ - if ( !check_extensions(streamFile,"msf")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x574D5346) /* "WMSF" */ - goto fail; - /* 0x04: size, 0x08: flags? 0x0c: null? */ - - temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); - if (!temp_streamFile) goto fail; - - vgmstream = init_vgmstream_msf(temp_streamFile); - if (!vgmstream) goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} - -/* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */ -VGMSTREAM * init_vgmstream_msf_banpresto_2msf(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t subfile_offset = 0x14; - size_t subfile_size = get_streamfile_size(streamFile) - subfile_offset; - - - /* checks */ - if ( !check_extensions(streamFile,"at9")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x324D5346) /* "2MSF" */ - goto fail; - /* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */ - - temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); - if (!temp_streamFile) goto fail; - - vgmstream = init_vgmstream_riff(temp_streamFile); - if (!vgmstream) goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* WMSF - Banpresto MSFx wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS3)] */ +VGMSTREAM* init_vgmstream_msf_banpresto_wmsf(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + off_t subfile_offset = 0x10; + size_t subfile_size = get_streamfile_size(sf) - subfile_offset; + + + /* checks */ + if (!check_extensions(sf,"msf")) + goto fail; + if (!is_id32be(0x00,sf,"WMSF")) + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null? */ + + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream_msf(temp_sf); + if (!vgmstream) goto fail; + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} + +/* 2MSF - Banpresto RIFF wrapper [Dai-2-Ji Super Robot Taisen OG: The Moon Dwellers (PS4)] */ +VGMSTREAM* init_vgmstream_msf_banpresto_2msf(STREAMFILE *sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE*temp_sf = NULL; + off_t subfile_offset = 0x14; + size_t subfile_size = get_streamfile_size(sf) - subfile_offset; + + + /* checks */ + if ( !check_extensions(sf,"at9")) + goto fail; + if (!is_id32be(0x00,sf,"2MSF")) + goto fail; + /* 0x04: size, 0x08: flags? 0x0c: null?, 0x10: 0x01? (BE values even though RIFF is LE) */ + + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, NULL); + if (!temp_sf) goto fail; + + 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; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msf_konami.c b/Frameworks/vgmstream/vgmstream/src/meta/msf_konami.c index 6c8b5fe0c..8551e5d67 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/msf_konami.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/msf_konami.c @@ -1,58 +1,58 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (PS3), Metal Gear Solid 3 HD (PS3)] */ -VGMSTREAM * init_vgmstream_msf_konami(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - uint32_t codec; - int loop_flag, channel_count, sample_rate; - size_t data_size; - - - /* checks */ - if (!check_extensions(streamFile,"msf")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x4D534643) /* "MSFC" */ - goto fail; - - start_offset = 0x20; - - codec = read_32bitBE(0x04,streamFile); - channel_count = read_32bitBE(0x08,streamFile); - sample_rate = read_32bitBE(0x0c,streamFile); - data_size = read_32bitBE(0x10,streamFile); /* without header */ - if (data_size + start_offset != get_streamfile_size(streamFile)) - goto fail; - loop_flag = 0; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_MSF_KONAMI; - vgmstream->sample_rate = sample_rate; - - switch (codec) { - case 0x01: - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - break; - - default: - goto fail; - } - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* MSFC - Konami (Armature?) variation [Metal Gear Solid 2 HD (PS3), Metal Gear Solid 3 HD (PS3)] */ +VGMSTREAM* init_vgmstream_msf_konami(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + uint32_t codec; + int loop_flag, channels, sample_rate; + size_t data_size; + + + /* checks */ + if (!check_extensions(sf,"msf")) + goto fail; + if (!is_id32be(0x00,sf,"MSFC")) + goto fail; + + start_offset = 0x20; + + codec = read_u32be(0x04,sf); + channels = read_s32be(0x08,sf); + sample_rate = read_s32be(0x0c,sf); + data_size = read_u32be(0x10,sf); /* without header */ + if (data_size + start_offset != get_streamfile_size(sf)) + goto fail; + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MSF_KONAMI; + vgmstream->sample_rate = sample_rate; + + switch (codec) { + case 0x01: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + vgmstream->num_samples = ps_bytes_to_samples(data_size, channels); + break; + + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngca.c b/Frameworks/vgmstream/vgmstream/src/meta/ngca.c deleted file mode 100644 index fb1352045..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngca.c +++ /dev/null @@ -1,68 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* NGCA (from GoldenEye 007) */ -VGMSTREAM * init_vgmstream_ngca(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("ngca",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x4E474341) /* "NGCA" */ - goto fail; - - loop_flag = 0; - channel_count = 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 32000; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = (((read_32bitBE(0x4,streamFile))/2) - 1) / 8 * 14; - - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_NGCA; - vgmstream->allow_dual_stereo = 1; - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0xC+i*2,streamFile); - } - } - - /* 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/ps2_ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c index 75559c6b1..e4444b1e4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ads.c @@ -1,368 +1,368 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* .ADS - Sony's "Audio Stream" format [Edit Racing (PS2), Evergrace II (PS2), Pri-Saga! Portable (PSP)] */ -VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count, sample_rate, interleave, is_loop_samples = 0; - size_t body_size, stream_size, file_size; - uint32_t codec, loop_start_sample = 0, loop_end_sample = 0, loop_start_offset = 0, loop_end_offset = 0; - coding_t coding_type; - int ignore_silent_frame_cavia = 0, ignore_silent_frame_capcom = 0; - - - /* checks */ - /* .ads: actual extension - * .ss2: demuxed videos (fake?) - * .pcm: Taisho Mononoke Ibunroku (PS2) - * .adx: Armored Core 3 (PS2) - * [no actual extension]: MotoGP (PS2) - * .800: Mobile Suit Gundam: The One Year War (PS2) */ - if (!check_extensions(streamFile, "ads,ss2,pcm,adx,,800")) - goto fail; - - if (read_32bitBE(0x00,streamFile) != 0x53536864 && /* "SShd" */ - read_32bitBE(0x20,streamFile) != 0x53536264) /* "SSbd" */ - goto fail; - if (read_32bitLE(0x04,streamFile) != 0x18 && /* standard header size */ - read_32bitLE(0x04,streamFile) != 0x20) /* True Fortune (PS2) */ - goto fail; - - - /* base values (a bit unorderly since devs hack ADS too much and detection is messy) */ - { - codec = read_32bitLE(0x08,streamFile); - sample_rate = read_32bitLE(0x0C,streamFile); - channel_count = read_32bitLE(0x10,streamFile); /* up to 4 [Eve of Extinction (PS2)] */ - interleave = read_32bitLE(0x14,streamFile); /* set even when mono */ - - - switch(codec) { - case 0x01: /* official definition */ - case 0x80000001: /* [Evergrace II (PS2), but not other From Soft games] */ - coding_type = coding_PCM16LE; - - /* Angel Studios/Rockstar San Diego videos codec hijack [Red Dead Revolver (PS2), Spy Hunter 2 (PS2)] */ - if (sample_rate == 12000 && interleave == 0x200) { - sample_rate = 48000; - interleave = 0x40; - coding_type = coding_DVI_IMA_int; - /* should try to detect IMA data but it's not so easy, this works ok since - * no known games use these settings, videos normally are 48000/24000hz */ - } - break; - - case 0x10: /* official definition */ - case 0x02: /* Capcom games extension, stereo only [Megaman X7 (PS2), Breath of Fire V (PS2), Clock Tower 3 (PS2)] */ - coding_type = coding_PSX; - break; - - case 0x00: /* PCM16BE from official docs, probably never used */ - default: - VGM_LOG("ADS: unknown codec\n"); - goto fail; - } - } - - - /* sizes */ - { - file_size = get_streamfile_size(streamFile); - body_size = read_32bitLE(0x24,streamFile); - - /* bigger than file_size in rare cases, even if containing all data (ex. Megaman X7's SY04.ADS) */ - if (body_size + 0x28 > file_size) { - body_size = file_size - 0x28; - } - - /* True Fortune: weird stream size */ - if (body_size * 2 == file_size - 0x18) { - body_size = (body_size * 2) - 0x10; - } - - stream_size = body_size; - } - - - /* offset */ - { - start_offset = 0x28; - - /* start padding (body size is ok, may have end padding) [Evergrace II (PS2), Armored Core 3 (PS2)] */ - /* detection depends on files being properly ripped, so broken/cut files won't play ok */ - if (file_size - body_size >= 0x800) { - start_offset = 0x800; /* aligned to sector */ - - /* too much end padding, happens in Super Galdelic Hour's SEL.ADS, maybe in bad rips too */ - VGM_ASSERT(file_size - body_size > 0x8000, "ADS: big end padding %x\n", file_size - body_size); - } - - /* "ADSC" container */ - if (coding_type == coding_PSX - && read_32bitLE(0x28,streamFile) == 0x1000 /* real start */ - && read_32bitLE(0x2c,streamFile) == 0 - && read_32bitLE(0x1008,streamFile) != 0) { - int i; - int is_adsc = 1; - - /* should be empty up to data start */ - for (i = 0; i < 0xFDC/4; i++) { - if (read_32bitLE(0x2c+(i*4),streamFile) != 0) { - is_adsc = 0; - break; - } - } - - if (is_adsc) { - start_offset = 0x1000 - 0x08; /* remove "ADSC" alignment */ - /* stream_size doesn't count start offset padding */ - } - } - } - - - /* loops */ - { - uint32_t loop_start, loop_end; - - loop_start = read_32bitLE(0x18,streamFile); - loop_end = read_32bitLE(0x1C,streamFile); - - loop_flag = 0; - - /* detect loops the best we can; docs say those are loop block addresses, - * but each maker does whatever (no games seem to use PS-ADPCM loop flags though) */ - - - if (loop_start != 0xFFFFFFFF && loop_end == 0xFFFFFFFF) { - - if (codec == 0x02) { /* Capcom codec */ - /* Capcom games: loop_start is address * 0x10 [Mega Man X7, Breath of Fire V, Clock Tower 3] */ - loop_flag = ((loop_start * 0x10) + 0x200 < body_size); /* near the end (+0x20~80) means no loop */ - loop_start_offset = loop_start * 0x10; - ignore_silent_frame_capcom = 1; - } - else if (read_32bitBE(0x28,streamFile) == 0x50414421) { /* "PAD!" padding until 0x800 */ - /* Super Galdelic Hour: loop_start is PCM bytes */ - loop_flag = 1; - loop_start_sample = loop_start / 2 / channel_count; - is_loop_samples = 1; - } - else if ((loop_start % 0x800 == 0) && loop_start > 0) { /* sector-aligned, min/0 is 0x800 */ - /* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */ - /* offset is absolute from the "cavia stream format" container that adjusts ADS start */ - loop_flag = 1; - loop_start_offset = loop_start - 0x800; - ignore_silent_frame_cavia = 1; - } - else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */ - /* Katakamuna: loop_start is address * 0x10 */ - loop_flag = 1; - loop_start_offset = loop_start * 0x10; - } - } - else if (loop_start != 0xFFFFFFFF && loop_end != 0xFFFFFFFF - && loop_end > 0) { /* ignore Kamen Rider Blade and others */ -#if 0 - //todo improve detection to avoid clashing with address*0x20 - if (loop_end == body_size / 0x10) { /* always body_size? but not all files should loop */ - /* Akane Iro ni Somaru Saka - Parallel: loops is address * 0x10 */ - loop_flag = 1; - loop_start_offset = loop_start * 0x10; - loop_end_offset = loop_end * 0x10; - } -#endif - if (loop_end <= body_size / 0x200 && coding_type == coding_PCM16LE) { /* close to body_size */ - /* Gofun-go no Sekai: loops is address * 0x200 */ - loop_flag = 1; - loop_start_offset = loop_start * 0x200; - loop_end_offset = loop_end * 0x200; - } - else if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */ - /* Armored Core - Nexus: loops is address * 0x70 */ - loop_flag = 1; - loop_start_offset = loop_start * 0x70; - loop_end_offset = loop_end * 0x70; - } - else if (loop_end <= body_size / 0x20 && coding_type == coding_PCM16LE) { /* close to body_size */ - /* Armored Core - Nine Breaker: loops is address * 0x20 */ - loop_flag = 1; - loop_start_offset = loop_start * 0x20; - loop_end_offset = loop_end * 0x20; - } - else if (loop_end <= body_size / 0x20 && coding_type == coding_PSX) { - /* various games: loops is address * 0x20 [Fire Pro Wrestling Returns, A.C.E. - Another Century's Episode] */ - loop_flag = 1; - loop_start_offset = loop_start * 0x20; - loop_end_offset = loop_end * 0x20; - } - else if (loop_end <= body_size / 0x10 && coding_type == coding_PSX - && (read_32bitBE(0x28 + loop_end*0x10 + 0x10 + 0x00, streamFile) == 0x00077777 || - read_32bitBE(0x28 + loop_end*0x10 + 0x20 + 0x00, streamFile) == 0x00077777)) { - /* not-quite-looping sfx, ending with a "non-looping PS-ADPCM end frame" [Kono Aozora ni Yakusoku, Chanter] */ - loop_flag = 0; - } - else if ((loop_end > body_size / 0x20 && coding_type == coding_PSX) || - (loop_end > body_size / 0x70 && coding_type == coding_PCM16LE)) { - /* various games: loops in samples [Eve of Extinction, Culdcept, WWE Smackdown! 3] */ - loop_flag = 1; - loop_start_sample = loop_start; - loop_end_sample = loop_end; - is_loop_samples = 1; - } - } - - //todo Jet Ion Grand Prix seems to have some loop-like values at 0x28 - //todo Yoake mae yori Ruriiro na has loops in unknown format - } - - - /* most games have empty PS-ADPCM frames in the last interleave block that should be skipped for smooth looping */ - if (coding_type == coding_PSX) { - off_t offset, min_offset; - - offset = start_offset + stream_size; - min_offset = offset - interleave; - - do { - offset -= 0x10; - - if (read_8bit(offset+0x01,streamFile) == 0x07) { - stream_size -= 0x10*channel_count;/* ignore don't decode flag/padding frame (most common) [ex. Capcom games] */ - } - else if (read_32bitBE(offset+0x00,streamFile) == 0x00000000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && - read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000) { - stream_size -= 0x10*channel_count; /* ignore null frame [ex. A.C.E. Another Century Episode 1/2/3] */ - } - else if (read_32bitBE(offset+0x00,streamFile) == 0x00007777 && read_32bitBE(offset+0x04,streamFile) == 0x77777777 && - read_32bitBE(offset+0x08,streamFile) == 0x77777777 && read_32bitBE(offset+0x0c,streamFile) == 0x77777777) { - stream_size -= 0x10*channel_count; /* ignore padding frame [ex. Akane Iro ni Somaru Saka - Parallel] */ - } - else if (read_32bitBE(offset+0x00,streamFile) == 0x0C020000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && - read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000 && - ignore_silent_frame_cavia) { - stream_size -= 0x10*channel_count; /* ignore silent frame [ex. cavia games] */ - } - else if (read_32bitBE(offset+0x00,streamFile) == 0x0C010000 && read_32bitBE(offset+0x04,streamFile) == 0x00000000 && - read_32bitBE(offset+0x08,streamFile) == 0x00000000 && read_32bitBE(offset+0x0c,streamFile) == 0x00000000 && - ignore_silent_frame_capcom) { - stream_size -= 0x10*channel_count; /* ignore silent frame [ex. Capcom games] */ - } - else { - break; /* standard frame */ - } - } - while(offset > min_offset); - - /* don't bother fixing loop_end_offset since will be adjusted to num_samples later, if needed */ - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->coding_type = coding_type; - vgmstream->interleave_block_size = interleave; - vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_SShd; - - switch(coding_type) { - case coding_PCM16LE: - vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); - break; - case coding_PSX: - vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); - break; - case coding_DVI_IMA_int: - vgmstream->num_samples = ima_bytes_to_samples(stream_size, channel_count); - break; - default: - goto fail; - } - - if (vgmstream->loop_flag) { - if (is_loop_samples) { - vgmstream->loop_start_sample = loop_start_sample; - vgmstream->loop_end_sample = loop_end_sample; - } - else { - switch(vgmstream->coding_type) { - case coding_PCM16LE: - vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start_offset,channel_count,16); - vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end_offset,channel_count,16); - break; - case coding_PSX: - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start_offset,channel_count); - vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end_offset,channel_count); - break; - default: - goto fail; - } - } - - /* when loop_end = 0xFFFFFFFF */ - if (vgmstream->loop_end_sample == 0) - vgmstream->loop_end_sample = vgmstream->num_samples; - - /* happens even when loops are directly samples, loops sound fine (ex. Culdcept) */ - if (vgmstream->loop_end_sample > vgmstream->num_samples) - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* ****************************************************************************** */ - -/* ADS in containers */ -VGMSTREAM * init_vgmstream_ps2_ads_container(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t subfile_offset; - size_t subfile_size; - - /* checks */ - if (!check_extensions(streamFile, "ads")) - goto fail; - - if (read_32bitBE(0x00,streamFile) == 0x41445343 && /* "ADSC" */ - read_32bitBE(0x04,streamFile) == 0x01000000) { - /* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */ - subfile_offset = 0x08; - } - else if (read_32bitBE(0x00,streamFile) == 0x63617669 && /* "cavi" */ - read_32bitBE(0x04,streamFile) == 0x61207374 && /* "a st" */ - read_32bitBE(0x08,streamFile) == 0x7265616D) { /* "ream" */ - /* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */ - subfile_offset = 0x7d8; - } - else { - goto fail; - } - - subfile_size = get_streamfile_size(streamFile) - subfile_offset; - - temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, NULL); - if (!temp_streamFile) goto fail; - - vgmstream = init_vgmstream_ps2_ads(temp_streamFile); - close_streamfile(temp_streamFile); - - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* .ADS - Sony's "Audio Stream" format [Edit Racing (PS2), Evergrace II (PS2), Pri-Saga! Portable (PSP)] */ +VGMSTREAM* init_vgmstream_ads(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels, sample_rate, interleave, is_loop_samples = 0; + size_t body_size, stream_size, file_size; + uint32_t codec, loop_start_sample = 0, loop_end_sample = 0, loop_start_offset = 0, loop_end_offset = 0; + coding_t coding_type; + int ignore_silent_frame_cavia = 0, ignore_silent_frame_capcom = 0; + + + /* checks */ + /* .ads: actual extension + * .ss2: demuxed videos (fake?) + * .pcm: Taisho Mononoke Ibunroku (PS2) + * .adx: Armored Core 3 (PS2) + * (extensionless): MotoGP (PS2) + * .800: Mobile Suit Gundam: The One Year War (PS2) */ + if (!check_extensions(sf, "ads,ss2,pcm,adx,,800")) + goto fail; + + if (!is_id32be(0x00,sf,"SShd") && + !is_id32be(0x20,sf,"SSbd")) + goto fail; + if (read_32bitLE(0x04,sf) != 0x18 && /* standard header size */ + read_32bitLE(0x04,sf) != 0x20) /* True Fortune (PS2) */ + goto fail; + + + /* base values (a bit unorderly since devs hack ADS too much and detection is messy) */ + { + codec = read_32bitLE(0x08,sf); + sample_rate = read_32bitLE(0x0C,sf); + channels = read_32bitLE(0x10,sf); /* up to 4 [Eve of Extinction (PS2)] */ + interleave = read_32bitLE(0x14,sf); /* set even when mono */ + + + switch(codec) { + case 0x01: /* official definition */ + case 0x80000001: /* [Evergrace II (PS2), but not other From Soft games] */ + coding_type = coding_PCM16LE; + + /* Angel Studios/Rockstar San Diego videos codec hijack [Red Dead Revolver (PS2), Spy Hunter 2 (PS2)] */ + if (sample_rate == 12000 && interleave == 0x200) { + sample_rate = 48000; + interleave = 0x40; + coding_type = coding_DVI_IMA_int; + /* should try to detect IMA data but it's not so easy, this works ok since + * no known games use these settings, videos normally are 48000/24000hz */ + } + break; + + case 0x10: /* official definition */ + case 0x02: /* Capcom games extension, stereo only [Megaman X7 (PS2), Breath of Fire V (PS2), Clock Tower 3 (PS2)] */ + coding_type = coding_PSX; + break; + + case 0x00: /* PCM16BE from official docs, probably never used */ + default: + VGM_LOG("ADS: unknown codec\n"); + goto fail; + } + } + + + /* sizes */ + { + file_size = get_streamfile_size(sf); + body_size = read_32bitLE(0x24,sf); + + /* bigger than file_size in rare cases, even if containing all data (ex. Megaman X7's SY04.ADS) */ + if (body_size + 0x28 > file_size) { + body_size = file_size - 0x28; + } + + /* True Fortune: weird stream size */ + if (body_size * 2 == file_size - 0x18) { + body_size = (body_size * 2) - 0x10; + } + + stream_size = body_size; + } + + + /* offset */ + { + start_offset = 0x28; + + /* start padding (body size is ok, may have end padding) [Evergrace II (PS2), Armored Core 3 (PS2)] */ + /* detection depends on files being properly ripped, so broken/cut files won't play ok */ + if (file_size - body_size >= 0x800) { + start_offset = 0x800; /* aligned to sector */ + + /* too much end padding, happens in Super Galdelic Hour's SEL.ADS, maybe in bad rips too */ + VGM_ASSERT(file_size - body_size > 0x8000, "ADS: big end padding %x\n", file_size - body_size); + } + + /* "ADSC" container */ + if (coding_type == coding_PSX + && read_32bitLE(0x28,sf) == 0x1000 /* real start */ + && read_32bitLE(0x2c,sf) == 0 + && read_32bitLE(0x1008,sf) != 0) { + int i; + int is_adsc = 1; + + /* should be empty up to data start */ + for (i = 0; i < 0xFDC/4; i++) { + if (read_32bitLE(0x2c+(i*4),sf) != 0) { + is_adsc = 0; + break; + } + } + + if (is_adsc) { + start_offset = 0x1000 - 0x08; /* remove "ADSC" alignment */ + /* stream_size doesn't count start offset padding */ + } + } + } + + + /* loops */ + { + uint32_t loop_start, loop_end; + + loop_start = read_32bitLE(0x18,sf); + loop_end = read_32bitLE(0x1C,sf); + + loop_flag = 0; + + /* detect loops the best we can; docs say those are loop block addresses, + * but each maker does whatever (no games seem to use PS-ADPCM loop flags though) */ + + + if (loop_start != 0xFFFFFFFF && loop_end == 0xFFFFFFFF) { + + if (codec == 0x02) { /* Capcom codec */ + /* Capcom games: loop_start is address * 0x10 [Mega Man X7, Breath of Fire V, Clock Tower 3] */ + loop_flag = ((loop_start * 0x10) + 0x200 < body_size); /* near the end (+0x20~80) means no loop */ + loop_start_offset = loop_start * 0x10; + ignore_silent_frame_capcom = 1; + } + else if (read_32bitBE(0x28,sf) == 0x50414421) { /* "PAD!" padding until 0x800 */ + /* Super Galdelic Hour: loop_start is PCM bytes */ + loop_flag = 1; + loop_start_sample = loop_start / 2 / channels; + is_loop_samples = 1; + } + else if ((loop_start % 0x800 == 0) && loop_start > 0) { /* sector-aligned, min/0 is 0x800 */ + /* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */ + /* offset is absolute from the "cavia stream format" container that adjusts ADS start */ + loop_flag = 1; + loop_start_offset = loop_start - 0x800; + ignore_silent_frame_cavia = 1; + } + else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */ + /* Katakamuna: loop_start is address * 0x10 */ + loop_flag = 1; + loop_start_offset = loop_start * 0x10; + } + } + else if (loop_start != 0xFFFFFFFF && loop_end != 0xFFFFFFFF + && loop_end > 0) { /* ignore Kamen Rider Blade and others */ +#if 0 + //todo improve detection to avoid clashing with address*0x20 + if (loop_end == body_size / 0x10) { /* always body_size? but not all files should loop */ + /* Akane Iro ni Somaru Saka - Parallel: loops is address * 0x10 */ + loop_flag = 1; + loop_start_offset = loop_start * 0x10; + loop_end_offset = loop_end * 0x10; + } +#endif + if (loop_end <= body_size / 0x200 && coding_type == coding_PCM16LE) { /* close to body_size */ + /* Gofun-go no Sekai: loops is address * 0x200 */ + loop_flag = 1; + loop_start_offset = loop_start * 0x200; + loop_end_offset = loop_end * 0x200; + } + else if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */ + /* Armored Core - Nexus: loops is address * 0x70 */ + loop_flag = 1; + loop_start_offset = loop_start * 0x70; + loop_end_offset = loop_end * 0x70; + } + else if (loop_end <= body_size / 0x20 && coding_type == coding_PCM16LE) { /* close to body_size */ + /* Armored Core - Nine Breaker: loops is address * 0x20 */ + loop_flag = 1; + loop_start_offset = loop_start * 0x20; + loop_end_offset = loop_end * 0x20; + } + else if (loop_end <= body_size / 0x20 && coding_type == coding_PSX) { + /* various games: loops is address * 0x20 [Fire Pro Wrestling Returns, A.C.E. - Another Century's Episode] */ + loop_flag = 1; + loop_start_offset = loop_start * 0x20; + loop_end_offset = loop_end * 0x20; + } + else if (loop_end <= body_size / 0x10 && coding_type == coding_PSX + && (read_32bitBE(0x28 + loop_end*0x10 + 0x10 + 0x00, sf) == 0x00077777 || + read_32bitBE(0x28 + loop_end*0x10 + 0x20 + 0x00, sf) == 0x00077777)) { + /* not-quite-looping sfx, ending with a "non-looping PS-ADPCM end frame" [Kono Aozora ni Yakusoku, Chanter] */ + loop_flag = 0; + } + else if ((loop_end > body_size / 0x20 && coding_type == coding_PSX) || + (loop_end > body_size / 0x70 && coding_type == coding_PCM16LE)) { + /* various games: loops in samples [Eve of Extinction, Culdcept, WWE Smackdown! 3] */ + loop_flag = 1; + loop_start_sample = loop_start; + loop_end_sample = loop_end; + is_loop_samples = 1; + } + } + + //todo Jet Ion Grand Prix seems to have some loop-like values at 0x28 + //todo Yoake mae yori Ruriiro na has loops in unknown format + } + + + /* most games have empty PS-ADPCM frames in the last interleave block that should be skipped for smooth looping */ + if (coding_type == coding_PSX) { + off_t offset, min_offset; + + offset = start_offset + stream_size; + min_offset = offset - interleave; + + do { + offset -= 0x10; + + if (read_8bit(offset+0x01,sf) == 0x07) { + stream_size -= 0x10*channels;/* ignore don't decode flag/padding frame (most common) [ex. Capcom games] */ + } + else if (read_32bitBE(offset+0x00,sf) == 0x00000000 && read_32bitBE(offset+0x04,sf) == 0x00000000 && + read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000) { + stream_size -= 0x10*channels; /* ignore null frame [ex. A.C.E. Another Century Episode 1/2/3] */ + } + else if (read_32bitBE(offset+0x00,sf) == 0x00007777 && read_32bitBE(offset+0x04,sf) == 0x77777777 && + read_32bitBE(offset+0x08,sf) == 0x77777777 && read_32bitBE(offset+0x0c,sf) == 0x77777777) { + stream_size -= 0x10*channels; /* ignore padding frame [ex. Akane Iro ni Somaru Saka - Parallel] */ + } + else if (read_32bitBE(offset+0x00,sf) == 0x0C020000 && read_32bitBE(offset+0x04,sf) == 0x00000000 && + read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000 && + ignore_silent_frame_cavia) { + stream_size -= 0x10*channels; /* ignore silent frame [ex. cavia games] */ + } + else if (read_32bitBE(offset+0x00,sf) == 0x0C010000 && read_32bitBE(offset+0x04,sf) == 0x00000000 && + read_32bitBE(offset+0x08,sf) == 0x00000000 && read_32bitBE(offset+0x0c,sf) == 0x00000000 && + ignore_silent_frame_capcom) { + stream_size -= 0x10*channels; /* ignore silent frame [ex. Capcom games] */ + } + else { + break; /* standard frame */ + } + } + while(offset > min_offset); + + /* don't bother fixing loop_end_offset since will be adjusted to num_samples later, if needed */ + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->coding_type = coding_type; + vgmstream->interleave_block_size = interleave; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_ADS; + + switch(coding_type) { + case coding_PCM16LE: + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + break; + case coding_PSX: + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + break; + case coding_DVI_IMA_int: + vgmstream->num_samples = ima_bytes_to_samples(stream_size, channels); + break; + default: + goto fail; + } + + if (vgmstream->loop_flag) { + if (is_loop_samples) { + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + } + else { + switch(vgmstream->coding_type) { + case coding_PCM16LE: + vgmstream->loop_start_sample = pcm16_bytes_to_samples(loop_start_offset, channels); + vgmstream->loop_end_sample = pcm16_bytes_to_samples(loop_end_offset, channels); + break; + case coding_PSX: + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start_offset, channels); + vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end_offset, channels); + break; + default: + goto fail; + } + } + + /* when loop_end = 0xFFFFFFFF */ + if (vgmstream->loop_end_sample == 0) + vgmstream->loop_end_sample = vgmstream->num_samples; + + /* happens even when loops are directly samples, loops sound fine (ex. Culdcept) */ + if (vgmstream->loop_end_sample > vgmstream->num_samples) + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* ****************************************************************************** */ + +/* ADS in containers */ +VGMSTREAM* init_vgmstream_ads_container(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + off_t subfile_offset; + size_t subfile_size; + + /* checks */ + if (!check_extensions(sf, "ads")) + goto fail; + + if (read_32bitBE(0x00,sf) == 0x41445343 && /* "ADSC" */ + read_32bitBE(0x04,sf) == 0x01000000) { + /* Kenka Bancho 2, Kamen Rider Hibiki/Kabuto, Shinjuku no Okami */ + subfile_offset = 0x08; + } + else if (read_32bitBE(0x00,sf) == 0x63617669 && /* "cavi" */ + read_32bitBE(0x04,sf) == 0x61207374 && /* "a st" */ + read_32bitBE(0x08,sf) == 0x7265616D) { /* "ream" */ + /* cavia games: Drakengard 1/2, Dragon Quest Yangus, GITS: Stand Alone Complex */ + subfile_offset = 0x7d8; + } + else { + goto fail; + } + + subfile_size = get_streamfile_size(sf) - subfile_offset; + + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, NULL); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream_ads(temp_sf); + close_streamfile(temp_sf); + + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 6efa2fa0f..a91dbeb15 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -794,6 +794,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { /* UE4 uses interleaved mono MSADPCM, try to autodetect without breaking normal MSADPCM */ if (fmt.coding_type == coding_MSADPCM && is_ue4_msadpcm(vgmstream, sf, &fmt, fact_sample_count, start_offset)) { vgmstream->coding_type = coding_MSADPCM_int; + vgmstream->codec_config = 1; /* mark as UE4 MSADPCM */ vgmstream->frame_size = fmt.block_size; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = get_ue4_msadpcm_interleave(sf, &fmt, start_offset, data_size); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c b/Frameworks/vgmstream/vgmstream/src/meta/rxws.c similarity index 52% rename from Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c rename to Frameworks/vgmstream/vgmstream/src/meta/rxws.c index 80daabfd4..ba52a54d0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxws.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/rxws.c @@ -3,52 +3,53 @@ #include "../coding/coding.h" /* RXWS - from Sony SCEI PS2 games (Okage: Shadow King, Genji, Bokura no Kazoku) */ -VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; +VGMSTREAM* init_vgmstream_rxws(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sh = NULL; off_t start_offset, chunk_offset, name_offset = 0; size_t stream_size, chunk_size; - int loop_flag = 0, channel_count, is_separate = 0, type, sample_rate; + int loop_flag = 0, channels, is_separate = 0, type, sample_rate; int32_t num_samples, loop_start; - int total_subsongs, target_subsong = streamFile->stream_index; + int total_subsongs, target_subsong = sf->stream_index; /* checks */ /* .xws: header and data * .xwh+xwb: header + data (.bin+dat are also found in Wild Arms 4/5) */ - if (!check_extensions(streamFile,"xws,xwb")) + if (!check_extensions(sf,"xws,xwb")) goto fail; - is_separate = check_extensions(streamFile,"xwb"); + is_separate = check_extensions(sf,"xwb"); /* xwh+xwb: use xwh as header; otherwise use the current file */ if (is_separate) { /* extra check to reject Microsoft's XWB faster */ - if ((read_32bitBE(0x00,streamFile) == 0x57424E44) || /* "WBND" (LE) */ - (read_32bitBE(0x00,streamFile) == 0x444E4257)) /* "DNBW" (BE) */ + if (is_id32be(0x00,sf,"WBND") || /* (LE) */ + is_id32be(0x00,sf,"DNBW")) /* (BE) */ goto fail; - streamHeader = open_streamfile_by_ext(streamFile, "xwh"); - if (!streamHeader) goto fail; + sh = open_streamfile_by_ext(sf, "xwh"); + if (!sh) goto fail; } else { - streamHeader = streamFile; + sh = sf; } - if (read_32bitBE(0x00,streamHeader) != 0x52585753) /* "RXWS" */ + if (!is_id32be(0x00,sh,"RXWS")) goto fail; /* file size (just the .xwh/xws) */ - if (read_32bitLE(0x04,streamHeader)+0x10 != get_streamfile_size(streamHeader)) + if (read_u32le(0x04,sh) + 0x10 != get_streamfile_size(sh)) goto fail; - /* 0x08(4): version (0x100/0x200), 0x0C: null */ + /* 0x08: version (0x100/0x200) + * 0x0C: null */ /* typical chunks: FORM, FTXT, MARK, BODY (for .xws) */ - if (read_32bitBE(0x10,streamHeader) != 0x464F524D) /* "FORM", main header (always first) */ + if (!is_id32be(0x10,sh,"FORM")) /* main header (always first) */ goto fail; - chunk_size = read_32bitLE(0x10+0x04,streamHeader); /* size - 0x10 */ + chunk_size = read_u32le(0x10+0x04,sh); /* size - 0x10 */ /* 0x08 version (0x100), 0x0c: null */ chunk_offset = 0x20; /* check multi-streams */ - total_subsongs = read_32bitLE(chunk_offset+0x00,streamHeader); + total_subsongs = read_s32le(chunk_offset+0x00,sh); if (target_subsong == 0) target_subsong = 1; if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; @@ -58,15 +59,18 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { off_t header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong-1); /* position in FORM */ off_t stream_offset, next_stream_offset, data_offset = 0; - type = read_8bit(header_offset+0x00, streamHeader); - /* 0x01(1): unknown (always 0x1c), 0x02(2): flags? (usually 8002/0002, & 0x01 if looped) */ - /* 0x04(4): vol/pan stuff? (0x00007F7F), 0x08(1): null?, 0x0c(4): null? */ - channel_count = read_8bit(header_offset+0x09, streamHeader); - sample_rate = (uint16_t)read_16bitLE(header_offset+0x0a,streamHeader); - stream_offset = read_32bitLE(header_offset+0x10,streamHeader); - num_samples = read_32bitLE(header_offset+0x14,streamHeader); - loop_start = read_32bitLE(header_offset+0x18,streamHeader); - loop_flag = (loop_start != 0xFFFFFFFF); + type = read_u8(header_offset+0x00, sh); + /* 0x01: unknown (always 0x1c) */ + /* 0x02: flags? (usually 8002/0002, & 0x01 if looped) */ + /* 0x04: vol/pan stuff? (0x00007F7F) */ + /* 0x08: null? */ + channels = read_u8(header_offset+0x09, sh); + /* 0x0c: null? */ + sample_rate = read_u16le(header_offset+0x0a,sh); + stream_offset = read_u32le(header_offset+0x10,sh); + num_samples = read_s32le(header_offset+0x14,sh); + loop_start = read_s32le(header_offset+0x18,sh); + loop_flag = (loop_start >= 0); /* find data start and size */ if (is_separate) { @@ -75,21 +79,21 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { else { off_t current_chunk = 0x10; /* note the extra 0x10 in chunk_size/offsets */ - while (current_chunk < get_streamfile_size(streamFile)) { - if (read_32bitBE(current_chunk,streamFile) == 0x424F4459) { /* "BODY" chunk_type */ + while (current_chunk < get_streamfile_size(sf)) { + if (is_id32be(current_chunk,sf, "BODY")) { data_offset = 0x10 + current_chunk; break; } - current_chunk += 0x10 + read_32bitLE(current_chunk+4,streamFile); + current_chunk += 0x10 + read_u32le(current_chunk+4,sf); } if (!data_offset) goto fail; } if (target_subsong == total_subsongs) { - next_stream_offset = get_streamfile_size(is_separate ? streamFile : streamHeader) - data_offset; + next_stream_offset = get_streamfile_size(is_separate ? sf : sh) - data_offset; } else { off_t next_header_offset = chunk_offset + 0x4 + 0x1c * (target_subsong); - next_stream_offset = read_32bitLE(next_header_offset+0x10,streamHeader); + next_stream_offset = read_u32le(next_header_offset+0x10,sh); } stream_size = next_stream_offset - stream_offset; @@ -97,24 +101,24 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { } /* get stream name (always follows FORM) */ - if (read_32bitBE(0x10+0x10 + chunk_size,streamHeader) == 0x46545854) { /* "FTXT" */ + if (is_id32be(0x10+0x10 + chunk_size,sh, "FTXT")) { chunk_offset = 0x10+0x10 + chunk_size + 0x10; - if (read_32bitLE(chunk_offset+0x00,streamHeader) == total_subsongs) { - name_offset = chunk_offset + read_32bitLE(chunk_offset+0x04 + (target_subsong-1)*0x04,streamHeader); + if (read_s32le(chunk_offset+0x00,sh) == total_subsongs) { + name_offset = chunk_offset + read_u32le(chunk_offset+0x04 + (target_subsong-1)*0x04,sh); } } /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; + vgmstream->meta_type = meta_RXWS; vgmstream->sample_rate = sample_rate; vgmstream->num_streams = total_subsongs; vgmstream->stream_size = stream_size; - vgmstream->meta_type = meta_PS2_RXWS; if (name_offset) - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamHeader); + read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sh); switch (type) { case 0x00: /* PS-ADPCM */ @@ -122,8 +126,8 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->num_samples = ps_bytes_to_samples(num_samples, channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); + vgmstream->num_samples = ps_bytes_to_samples(num_samples, channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels); vgmstream->loop_end_sample = vgmstream->num_samples; break; @@ -132,8 +136,8 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x2; - vgmstream->num_samples = pcm_bytes_to_samples(num_samples, channel_count, 16); - vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16); + vgmstream->num_samples = pcm_bytes_to_samples(num_samples, channels, 16); + vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channels, 16); vgmstream->loop_end_sample = vgmstream->num_samples; break; @@ -141,11 +145,11 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { case 0x02: { /* ATRAC3 */ int block_align, encoder_delay; - block_align = 0xc0 * channel_count; + block_align = 0xc0 * channels; encoder_delay = 1024 + 69*2; /* observed default */ vgmstream->num_samples = num_samples - encoder_delay; - vgmstream->codec_data = init_ffmpeg_atrac3_raw(streamFile, start_offset,stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); + vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,stream_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -160,57 +164,58 @@ VGMSTREAM * init_vgmstream_ps2_rxws(STREAMFILE *streamFile) { } /* open the file for reading */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; - if (is_separate && streamHeader) close_streamfile(streamHeader); + if (is_separate && sh) close_streamfile(sh); return vgmstream; fail: - if (is_separate && streamHeader) close_streamfile(streamHeader); + if (is_separate && sh) close_streamfile(sh); close_vgmstream(vgmstream); return NULL; } /* .RXW - legacy fake ext/header for poorly split XWH+XWB files generated by old tools (incorrect header/chunk sizes) */ -VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int loop_flag=0, channel_count; +VGMSTREAM* init_vgmstream_rxws_badrip(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int loop_flag=0, channels; off_t start_offset; /* check extension, case insensitive */ - if (!check_extensions(streamFile,"rxw")) goto fail; - - /* check RXWS/FORM Header */ - if (!((read_32bitBE(0x00,streamFile) == 0x52585753) && - (read_32bitBE(0x10,streamFile) == 0x464F524D))) + if (!check_extensions(sf,"rxw")) goto fail; - loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); - channel_count=2; /* Always stereo files */ + /* check RXWS/FORM Header */ + if (!((read_32bitBE(0x00,sf) == 0x52585753) && + (read_32bitBE(0x10,sf) == 0x464F524D))) + goto fail; + + loop_flag = (read_32bitLE(0x3C,sf)!=0xFFFFFFFF); + channels=2; /* Always stereo files */ /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); - vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; + vgmstream->sample_rate = read_32bitLE(0x2E,sf); + vgmstream->num_samples = (read_32bitLE(0x38,sf)*28/16)/2; /* Get loop point values */ if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; - vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; + vgmstream->loop_start_sample = read_32bitLE(0x3C,sf)/16*14; + vgmstream->loop_end_sample = read_32bitLE(0x38,sf)/16*14; } - vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; + vgmstream->interleave_block_size = read_32bitLE(0x1c,sf)+0x10; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_RXWS; + vgmstream->meta_type = meta_RXWS; start_offset = 0x40; /* open the file for reading */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c index 35bb8bc0c..cb53d60fa 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -1,38 +1,39 @@ #include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" -#include "sqex_scd_streamfile.h" #ifdef VGM_USE_VORBIS -static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource); -static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource); +static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource); +static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource); #endif /* SCD - Square-Enix games (FF XIII, XIV) */ -VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; +VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0; int32_t stream_size, extradata_size, loop_start, loop_end; - int loop_flag = 0, channel_count, codec, sample_rate; + int loop_flag = 0, channels, codec, sample_rate; int version, target_entry, aux_chunk_count; - int total_subsongs, target_subsong = streamFile->stream_index; + int total_subsongs, target_subsong = sf->stream_index; + int big_endian; int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - /* check extension, case insensitive */ - if ( !check_extensions(streamFile, "scd") ) + /* checks */ + if (!check_extensions(sf, "scd")) goto fail; /** main header **/ - if (read_32bitBE(0x00,streamFile) != 0x53454442 && /* "SEDB" */ - read_32bitBE(0x04,streamFile) != 0x53534346) /* "SSCF" */ + if (!is_id32be(0x00,sf, "SEDB") && + !is_id32be(0x04,sf, "SSCF")) goto fail; - if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */ + big_endian = read_u8(0x0c,sf) == 0x01; + if (big_endian) { /* big endian flag */ //size_offset = 0x14; read_32bit = read_32bitBE; read_16bit = read_16bitBE; @@ -42,21 +43,20 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { read_16bit = read_16bitLE; } - /* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */ - if (read_8bit(0x0d,streamFile) != 0x04) - goto fail; - /* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */ - version = read_32bit(0x08,streamFile); + version = read_32bit(0x08,sf); if (version != 2 && version != 3 && version != 4) goto fail; - tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */ + /* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */ + if (read_u8(0x0d,sf) != 0x04) + goto fail; + + tables_offset = read_16bit(0x0e,sf); /* usually 0x30 or 0x20 */ #if 0 - /* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ - /* check file size with header value */ - if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile)) + /* FFXIII music_68tak.ps3.scd is 0x80 shorter? */ + if (read_32bit(size_offset,sf) != get_streamfile_size(sf)) goto fail; #endif @@ -80,8 +80,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* find meta_offset in table3 (headers) and total subsongs */ { int i; - int headers_entries = read_16bit(tables_offset+0x04,streamFile); - off_t headers_offset = read_32bit(tables_offset+0x0c,streamFile); + int headers_entries = read_16bit(tables_offset+0x04,sf); + off_t headers_offset = read_32bit(tables_offset+0x0c,sf); if (target_subsong == 0) target_subsong = 1; total_subsongs = 0; @@ -89,9 +89,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */ for (i = 0; i < headers_entries; i++) { - off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile); + off_t entry_offset = read_32bit(headers_offset + i*0x04,sf); - if (read_32bit(entry_offset+0x0c,streamFile) == -1) + if (read_32bit(entry_offset+0x0c,sf) == -1) continue; /* codec -1 when dummy */ total_subsongs++; @@ -105,15 +105,15 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } /** stream header **/ - stream_size = read_32bit(meta_offset+0x00,streamFile); - channel_count = read_32bit(meta_offset+0x04,streamFile); - sample_rate = read_32bit(meta_offset+0x08,streamFile); - codec = read_32bit(meta_offset+0x0c,streamFile); + stream_size = read_32bit(meta_offset+0x00,sf); + channels = read_32bit(meta_offset+0x04,sf); + sample_rate = read_32bit(meta_offset+0x08,sf); + codec = read_32bit(meta_offset+0x0c,sf); - loop_start = read_32bit(meta_offset+0x10,streamFile); - loop_end = read_32bit(meta_offset+0x14,streamFile); - extradata_size = read_32bit(meta_offset+0x18,streamFile); - aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); + loop_start = read_32bit(meta_offset+0x10,sf); + loop_end = read_32bit(meta_offset+0x14,sf); + extradata_size = read_32bit(meta_offset+0x18,sf); + aux_chunk_count = read_32bit(meta_offset+0x1c,sf); /* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */ loop_flag = (loop_end > 0); @@ -127,19 +127,19 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } /* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */ - if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */ - extradata_offset += read_32bit(extradata_offset+0x04, streamFile); + if (aux_chunk_count && is_id32be(extradata_offset, sf, "MARK")) { + extradata_offset += read_32bit(extradata_offset+0x04, sf); } /* find name if possible */ if (version == 4) { - int info_entries = read_16bit(tables_offset+0x00,streamFile); - int headers_entries = read_16bit(tables_offset+0x04,streamFile); + int info_entries = read_16bit(tables_offset+0x00,sf); + int headers_entries = read_16bit(tables_offset+0x04,sf); off_t info_offset = tables_offset+0x20; /* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */ if (info_entries == headers_entries) { - off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile); + off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,sf); name_offset = entry_offset+0x30; } } @@ -157,17 +157,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { ovmi.disable_reordering = 1; /* already ordered */ /* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */ - ogg_version = read_8bit(extradata_offset + 0x00, streamFile); + ogg_version = read_u8(extradata_offset + 0x00, sf); /* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */ - ogg_byte = read_8bit(extradata_offset + 0x02, streamFile); + ogg_byte = read_u8(extradata_offset + 0x02, sf); /* 0x03(1): ? in v3 */ if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */ ovmi.stream_size = stream_size; } else { /* 0x20 header, then seek table */ - size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile); - size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile); + size_t seek_table_size = read_32bit(extradata_offset+0x10, sf); + size_t vorb_header_size = read_32bit(extradata_offset+0x14, sf); /* 0x18(4): ? (can be 0) */ if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size) @@ -192,16 +192,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } /* actual Ogg init */ - ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi); + ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi); if (ogg_vgmstream && name_offset) - read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); + read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf); return ogg_vgmstream; } #endif /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; vgmstream->sample_rate = sample_rate; @@ -209,7 +209,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->stream_size = stream_size; vgmstream->meta_type = meta_SQEX_SCD; if (name_offset) - read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile); + read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf); switch (codec) { case 0x01: /* PCM */ @@ -217,10 +217,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x02; - vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); + vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channels, 16); if (loop_flag) { - vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16); - vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16); + vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channels, 16); + vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channels, 16); } break; @@ -229,10 +229,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); if (loop_flag) { - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); - vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channel_count); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels); + vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channels); } break; @@ -246,7 +246,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */ cfg.data_size = stream_size; - vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg); + vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg); if (!vgmstream->codec_data) goto fail; vgmstream->layout_type = layout_none; @@ -268,9 +268,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */ vgmstream->coding_type = coding_MSADPCM; vgmstream->layout_type = layout_none; - vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, streamFile); + vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, sf); /* WAVEFORMATEX in extradata_offset */ - if (!msadpcm_check_coefs(streamFile, extradata_offset + 0x14)) + if (!msadpcm_check_coefs(sf, extradata_offset + 0x14)) goto fail; vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->frame_size, vgmstream->channels); @@ -282,83 +282,53 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */ case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */ - const off_t interleave_size = 0x800; - const off_t stride_size = interleave_size * channel_count; - int i; - size_t total_size; - layered_layout_data * data = NULL; - - /* interleaved DSPs including the header (so the first 0x800 is 0x60 header + 0x740 data) - * so interleave layout can't used; we'll setup de-interleaving streamfiles as layers/channels instead */ - //todo this could be simplified using a block layout or adding interleave_first_block vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_layered; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + vgmstream->interleave_first_skip = 0x60; + vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip; - /* read from the first DSP header and verify other channel headers */ - { - total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; /* rounded nibbles / 2 */ - vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end + 1; - } + /* standard dsp header at start_offset */ + dsp_read_coefs_be(vgmstream, sf, start_offset+0x1c, vgmstream->interleave_block_size); + dsp_read_hist_be(vgmstream, sf, start_offset+0x40, vgmstream->interleave_block_size); - for (i = 1; i < channel_count; i++) { - if ((read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size || - read_32bitBE(start_offset+interleave_size*i+0x00,streamFile) != vgmstream->num_samples) { - goto fail; - } - } + vgmstream->num_samples = read_32bit(start_offset+0x00,sf); + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end + 1; } - - /* init layout */ - data = init_layout_layered(channel_count); - if (!data) goto fail; - vgmstream->layout_data = data; - - /* open each layer subfile */ - for (i = 0; i < channel_count; i++) { - STREAMFILE* temp_streamFile = setup_scd_dsp_streamfile(streamFile, start_offset+interleave_size*i, interleave_size, stride_size, total_size); - if (!temp_streamFile) goto fail; - - data->layers[i] = init_vgmstream_ngc_dsp_std(temp_streamFile); - close_streamfile(temp_streamFile); - if (!data->layers[i]) goto fail; - } - - /* setup layered VGMSTREAMs */ - if (!setup_layout_layered(data)) - goto fail; - + + start_offset += vgmstream->interleave_first_skip; + break; } #ifdef VGM_USE_FFMPEG case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */ - ffmpeg_codec_data *ffmpeg_data = NULL; - uint8_t buf[200]; + uint8_t buf[0x100]; int32_t bytes; - /* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */ - bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1); - ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size); - if (!ffmpeg_data) goto fail; - vgmstream->codec_data = ffmpeg_data; + /* extradata: + * 0x00: fmt0x166 header (BE X360, LE XBone) + * 0x34: seek table */ + bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, extradata_offset,0x34, stream_size, sf, big_endian); + vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, stream_size); + if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = ffmpeg_data->totalSamples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; //todo +1? + xma2_parse_fmt_chunk_extra(sf, extradata_offset, NULL, &vgmstream->num_samples, NULL, NULL, big_endian); + vgmstream->loop_start_sample = loop_start; /* same loops in chunk */ + vgmstream->loop_end_sample = loop_end; - xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */ + xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, extradata_offset, 1,1); break; } case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */ int fact_samples = 0; - vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, &fact_samples); + vgmstream->codec_data = init_ffmpeg_atrac3_riff(sf, start_offset, &fact_samples); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -377,17 +347,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { /* post header has various typical ATRAC9 values */ cfg.channels = vgmstream->channels; - cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile); - cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile); + cfg.config_data = read_32bit(extradata_offset+0x0c,sf); + cfg.encoder_delay = read_32bit(extradata_offset+0x18,sf); vgmstream->codec_data = init_atrac9(&cfg); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_ATRAC9; vgmstream->layout_type = layout_none; - vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */ - vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile); - vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) + 1; + vgmstream->num_samples = read_32bit(extradata_offset+0x10,sf); /* loop values above are also weird and ignored */ + vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, sf); + vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, sf) + 1; if (loop_flag) { vgmstream->loop_start_sample -= cfg.encoder_delay; vgmstream->loop_end_sample -= cfg.encoder_delay; @@ -403,7 +373,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { } - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; return vgmstream; @@ -415,7 +385,7 @@ fail: #ifdef VGM_USE_VORBIS -static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { +static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) { uint8_t *ptr8 = ptr; size_t bytes_read = size * nmemb; ogg_vorbis_io *io = datasource; @@ -438,7 +408,7 @@ static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, } } -static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) { +static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) { /* V3 decryption table found in the .exe of FF XIV Heavensward */ static const uint8_t scd_ogg_v3_lookuptable[256] = { 0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h deleted file mode 100644 index 2d54bc831..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd_streamfile.h +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef _SQEX_SCD_STREAMFILE_H_ -#define _SQEX_SCD_STREAMFILE_H_ -#include "../streamfile.h" - - -typedef struct { - off_t start_physical_offset; /* interleaved data start, for this substream */ - size_t interleave_block_size; /* max size that can be read before encountering other substreams */ - size_t stride_size; /* step size between interleave blocks (interleave*channels) */ - size_t total_size; /* final size of the deinterleaved substream */ -} scd_dsp_io_data; - - -/* Handles deinterleaving of complete files, skipping portions or other substreams. */ -static size_t scd_dsp_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, scd_dsp_io_data* data) { - size_t total_read = 0; - - while (length > 0) { - size_t to_read; - size_t length_available; - off_t block_num; - off_t intrablock_offset; - off_t physical_offset; - - block_num = offset / data->interleave_block_size; - intrablock_offset = offset % data->interleave_block_size; - physical_offset = data->start_physical_offset + block_num*data->stride_size + intrablock_offset; - length_available = data->interleave_block_size - intrablock_offset; - - if (length < length_available) { - to_read = length; - } - else { - to_read = length_available; - } - - if (to_read > 0) { - size_t bytes_read; - - bytes_read = read_streamfile(dest, physical_offset, to_read, streamfile); - total_read += bytes_read; - - if (bytes_read != to_read) { - return total_read; - } - - dest += bytes_read; - offset += bytes_read; - length -= bytes_read; - } - } - - return total_read; -} - -static size_t scd_dsp_io_size(STREAMFILE *streamfile, scd_dsp_io_data* data) { - return data->total_size; -} - - -static STREAMFILE* setup_scd_dsp_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t interleave_block_size, size_t stride_size, size_t total_size) { - STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - scd_dsp_io_data io_data = {0}; - size_t io_data_size = sizeof(scd_dsp_io_data); - - io_data.start_physical_offset = start_offset; - io_data.interleave_block_size = interleave_block_size; - io_data.stride_size = stride_size; - io_data.total_size = total_size; - - - /* setup subfile */ - new_streamFile = open_wrap_streamfile(streamFile); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, scd_dsp_io_read,scd_dsp_io_size); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"dsp"); - if (!new_streamFile) goto fail; - temp_streamFile = new_streamFile; - - return temp_streamFile; - -fail: - close_streamfile(temp_streamFile); - return NULL; -} - -#endif /* _SCD_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/thp.c b/Frameworks/vgmstream/vgmstream/src/meta/thp.c index b6d71364a..006399566 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/thp.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/thp.c @@ -2,12 +2,12 @@ #include "../layout/layout.h" /* THP - Nintendo movie format found in GC/Wii games */ -VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; +VGMSTREAM* init_vgmstream_thp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset, component_type_offset, component_data_offset; uint32_t version, max_audio_size; int num_components; - int loop_flag, channel_count; + int loop_flag, channels; int i; @@ -15,14 +15,14 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) { /* .thp: actual extension * .dsp: fake extension? * (extensionless): Fragile (Wii) */ - if (!check_extensions(streamFile, "thp,dsp,")) + if (!check_extensions(sf, "thp,dsp,")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x54485000) /* "THP\0" */ + if (!is_id32be(0x00,sf, "THP\0")) goto fail; - version = read_32bitBE(0x04,streamFile); /* 16b+16b major/minor */ + version = read_u32be(0x04,sf); /* 16b+16b major/minor */ /* 0x08: max buffer size */ - max_audio_size = read_32bitBE(0x0C,streamFile); + max_audio_size = read_u32be(0x0C,sf); /* 0x10: fps in float */ /* 0x14: block count */ /* 0x18: first block size */ @@ -33,19 +33,19 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) { if (max_audio_size == 0) /* no sound */ goto fail; - component_type_offset = read_32bitBE(0x20,streamFile); + component_type_offset = read_u32be(0x20,sf); /* 0x24: block offsets table offset (optional, for seeking) */ - start_offset = read_32bitBE(0x28,streamFile); + start_offset = read_u32be(0x28,sf); /* 0x2c: last block offset */ /* first component "type" x16 then component headers */ - num_components = read_32bitBE(component_type_offset,streamFile); + num_components = read_u32be(component_type_offset,sf); component_type_offset += 0x04; component_data_offset = component_type_offset + 0x10; /* parse "component" (data that goes into blocks) */ for (i = 0; i < num_components; i++) { - int type = read_8bit(component_type_offset + i,streamFile); + int type = read_u8(component_type_offset + i,sf); if (type == 0x00) { /* video */ if (version == 0x00010000) @@ -73,24 +73,24 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE *streamFile) { * adjusted, but we can't detect Wii (non adjusted) .thp tho */ loop_flag = 0; - channel_count = read_32bitBE(component_data_offset + 0x00,streamFile); + channels = read_u32be(component_data_offset + 0x00,sf); /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = read_32bitBE(component_data_offset + 0x04,streamFile); - vgmstream->num_samples = read_32bitBE(component_data_offset + 0x08,streamFile); + vgmstream->sample_rate = read_u32be(component_data_offset + 0x04,sf); + vgmstream->num_samples = read_u32be(component_data_offset + 0x08,sf); vgmstream->meta_type = meta_THP; vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_blocked_thp; /* coefs are in every block */ - vgmstream->full_block_size = read_32bitBE(0x18,streamFile); /* next block size */ + vgmstream->full_block_size = read_u32be(0x18,sf); /* next block size */ - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c index f957f0f0a..02fb1fa70 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_bao.c @@ -599,75 +599,32 @@ fail: } -static size_t silence_io_read(STREAMFILE* streamfile, uint8_t *dest, off_t offset, size_t length, void* data) { - int i; - for (i = 0; i < length; i++) { - dest[i] = 0; - } - return length; /* pretend we read zeroes */ -} -static size_t silence_io_size(STREAMFILE* streamfile, void* data) { - return 0x7FFFFFF; /* whatevs */ -} -static STREAMFILE* setup_silence_streamfile(STREAMFILE* sf) { - STREAMFILE* temp_sf = NULL, *new_sf = NULL; - - /* setup custom streamfile */ - new_sf = open_wrap_streamfile(sf); - if (!new_sf) goto fail; - temp_sf = new_sf; - - new_sf = open_io_streamfile(temp_sf, NULL,0, silence_io_read,silence_io_size); - if (!new_sf) goto fail; - temp_sf = new_sf; - - return temp_sf; - -fail: - close_streamfile(temp_sf); - return NULL; -} - static VGMSTREAM* init_vgmstream_ubi_bao_silence(ubi_bao_header* bao, STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - STREAMFILE* temp_sf = NULL; - int channel_count, sample_rate; + int channels, sample_rate; + int32_t num_samples; - channel_count = bao->channels; + /* by default silences don't have settings */ + channels = bao->channels; + if (channels == 0) + channels = 2; sample_rate = bao->sample_rate; - - /* by default silences don't have settings so let's pretend */ - if (channel_count == 0) - channel_count = 2; if (sample_rate == 0) sample_rate = 48000; + num_samples = bao->duration * sample_rate; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, 0); + /* init the VGMSTREAM */ + vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples); if (!vgmstream) goto fail; vgmstream->meta_type = meta_UBI_BAO; - vgmstream->sample_rate = sample_rate; - - vgmstream->num_samples = bao->duration * sample_rate; vgmstream->num_streams = bao->total_subsongs; - vgmstream->stream_size = vgmstream->num_samples * channel_count * 0x02; /* PCM size */ - vgmstream->coding_type = coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - - temp_sf = setup_silence_streamfile(sf); - if ( !vgmstream_open_stream(vgmstream, temp_sf, 0x00) ) - goto fail; - - close_streamfile(temp_sf); return vgmstream; fail: close_vgmstream(vgmstream); - close_streamfile(temp_sf); return vgmstream; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 3803105c7..3f8f4bd17 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -1526,74 +1526,33 @@ fail: return NULL; } -static size_t silence_io_read(STREAMFILE* sf, uint8_t *dest, off_t offset, size_t length, void* data) { - int i; - for (i = 0; i < length; i++) { - dest[i] = 0; - } - return length; /* pretend we read zeroes */ -} -static size_t silence_io_size(STREAMFILE* sf, void* data) { - return 0x7FFFFFF; /* whatevs */ -} -static STREAMFILE* setup_silence_streamfile(STREAMFILE* sf) { - STREAMFILE *temp_sf = NULL, *new_sf = NULL; - - /* setup custom streamfile */ - new_sf = open_wrap_streamfile(sf); - if (!new_sf) goto fail; - temp_sf = new_sf; - - new_sf = open_io_streamfile(temp_sf, NULL,0, silence_io_read,silence_io_size); - if (!new_sf) goto fail; - temp_sf = new_sf; - - return temp_sf; - -fail: - close_streamfile(temp_sf); - return NULL; -} static VGMSTREAM* init_vgmstream_ubi_sb_silence(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - STREAMFILE* temp_sf = NULL; - int channel_count, sample_rate; + int channels, sample_rate; + int32_t num_samples; - channel_count = sb->channels; + /* by default silences don't have settings */ + channels = sb->channels; + if (channels == 0) + channels = 2; sample_rate = sb->sample_rate; - - /* by default silences don't have settings so let's pretend */ - if (channel_count == 0) - channel_count = 2; if (sample_rate == 0) sample_rate = 48000; + num_samples = sb->duration * sample_rate; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, 0); + /* init the VGMSTREAM */ + vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples); if (!vgmstream) goto fail; vgmstream->meta_type = meta_UBI_SB; - vgmstream->sample_rate = sample_rate; - - vgmstream->num_samples = (int32_t)(sb->duration * (float)sample_rate); vgmstream->num_streams = sb->total_subsongs; - vgmstream->stream_size = vgmstream->num_samples * channel_count * 0x02; /* PCM size */ - vgmstream->coding_type = coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - - temp_sf = setup_silence_streamfile(sf); - if ( !vgmstream_open_stream(vgmstream, temp_sf, 0x00) ) - goto fail; - close_streamfile(temp_sf); return vgmstream; fail: close_vgmstream(vgmstream); - close_streamfile(temp_sf); return vgmstream; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c b/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c index b3a3e489d..5ddc2adb7 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ue4opus.c @@ -1,62 +1,61 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* UE4OPUS - from Unreal Engine 4 games [ARK: Survival Evolved (PC), Fortnite (PC)] */ -VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count, sample_rate, num_samples, skip; - size_t data_size; - - - /* checks*/ - /* .opus/lopus: possible real extension - * .ue4opus: header id */ - if (!check_extensions(streamFile, "opus,lopus,ue4opus")) - goto fail; - if (read_32bitBE(0x00, streamFile) != 0x5545344F && /* "UE4O" */ - read_32bitBE(0x00, streamFile) != 0x50555300) /* "PUS\0" */ - goto fail; - - - sample_rate = (uint16_t)read_16bitLE(0x08, streamFile); - num_samples = read_32bitLE(0x0a, streamFile); /* may be less or equal to file num_samples */ - channel_count = read_8bit(0x0e, streamFile); - /* 0x0f(2): frame count */ - loop_flag = 0; - - start_offset = 0x11; - data_size = get_streamfile_size(streamFile) - start_offset; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_UE4OPUS; - vgmstream->sample_rate = sample_rate; - -#ifdef VGM_USE_FFMPEG - { - /* usually uses 60ms for music (delay of 360 samples) */ - skip = ue4_opus_get_encoder_delay(start_offset, streamFile); - vgmstream->num_samples = num_samples - skip; - - vgmstream->codec_data = init_ffmpeg_ue4_opus(streamFile, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; - } -#else - goto fail; -#endif - - if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* UE4OPUS - from Unreal Engine 4 games [ARK: Survival Evolved (PC), Fortnite (PC)] */ +VGMSTREAM * init_vgmstream_ue4opus(STREAMFILE *sf) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channels, sample_rate, num_samples, skip; + size_t data_size; + + + /* checks*/ + /* .opus/lopus: possible real extension + * .ue4opus: header id */ + if (!check_extensions(sf, "opus,lopus,ue4opus")) + goto fail; + if (!is_id64be(0x00, sf, "UE4OPUS\0")) + goto fail; + + + sample_rate = read_u16le(0x08, sf); + num_samples = read_s32le(0x0a, sf); /* may be less or equal to file num_samples */ + channels = read_u8(0x0e, sf); + /* 0x0f(2): frame count */ + loop_flag = 0; + + start_offset = 0x11; + data_size = get_streamfile_size(sf) - start_offset; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_UE4OPUS; + vgmstream->sample_rate = sample_rate; + +#ifdef VGM_USE_FFMPEG + { + /* usually uses 60ms for music (delay of 360 samples) */ + skip = ue4_opus_get_encoder_delay(start_offset, sf); + vgmstream->num_samples = num_samples - skip; + + vgmstream->codec_data = init_ffmpeg_ue4_opus(sf, start_offset,data_size, vgmstream->channels, skip, vgmstream->sample_rate); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + } +#else + goto fail; +#endif + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/plugins.c b/Frameworks/vgmstream/vgmstream/src/plugins.c index af03eed3f..2f4669484 100644 --- a/Frameworks/vgmstream/vgmstream/src/plugins.c +++ b/Frameworks/vgmstream/vgmstream/src/plugins.c @@ -532,3 +532,17 @@ void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels) { return; } + +void vgmstream_mixing_stereo_only(VGMSTREAM *vgmstream, int start) { + if (start < 0) + return; + /* could check to avoid making mono files in edge cases but meh */ + + /* remove channels before start */ + while (start) { + mixing_push_downmix(vgmstream, 0); + start--; + } + /* remove channels after stereo */ + mixing_push_killmix(vgmstream, start + 2); +} diff --git a/Frameworks/vgmstream/vgmstream/src/plugins.h b/Frameworks/vgmstream/vgmstream/src/plugins.h index b31b4862d..917c8c9b9 100644 --- a/Frameworks/vgmstream/vgmstream/src/plugins.h +++ b/Frameworks/vgmstream/vgmstream/src/plugins.h @@ -215,7 +215,10 @@ void vgmstream_tags_close(VGMSTREAM_TAGS* tags); void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int *input_channels, int *output_channels); /* sets automatic downmixing if vgmstream's channels are higher than max_channels */ -void vgmstream_mixing_autodownmix(VGMSTREAM *vgmstream, int max_channels); +void vgmstream_mixing_autodownmix(VGMSTREAM* vgmstream, int max_channels); + +/* downmixes to get stereo from start channel */ +void vgmstream_mixing_stereo_only(VGMSTREAM* vgmstream, int start); /* sets a fadeout */ //void vgmstream_mixing_fadeout(VGMSTREAM *vgmstream, float start_second, float duration_seconds); diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c index 9dd5e736e..6c187e200 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.c +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -1123,9 +1123,14 @@ fail: } STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { + return read_filemap_file_pos(sf, file_num, NULL); +} + +STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) { char filename[PATH_LIMIT]; off_t txt_offset, file_size; STREAMFILE* sf_map = NULL; + int file_pos = 0; sf_map = open_streamfile_by_filename(sf, ".txtm"); if (!sf_map) goto fail; @@ -1136,10 +1141,10 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { file_size = get_streamfile_size(sf_map); /* skip BOM if needed */ - if ((uint16_t)read_16bitLE(0x00, sf_map) == 0xFFFE || - (uint16_t)read_16bitLE(0x00, sf_map) == 0xFEFF) { + if (read_u16le(0x00, sf_map) == 0xFFFE || + read_u16le(0x00, sf_map) == 0xFEFF) { txt_offset = 0x02; - } else if (((uint32_t)read_32bitBE(0x00, sf_map) & 0xFFFFFF00) == 0xEFBBBF00) { + } else if ((read_u32be(0x00, sf_map) & 0xFFFFFF00) == 0xEFBBBF00) { txt_offset = 0x03; } @@ -1174,8 +1179,9 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { if (ok != 1) goto fail; - if (i == file_num) - { + if (i == file_num) { + if (p_pos) *p_pos = file_pos; + close_streamfile(sf_map); return open_streamfile_by_filename(sf, subval); } @@ -1185,6 +1191,7 @@ STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { current++; } } + file_pos++; } fail: diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.h b/Frameworks/vgmstream/vgmstream/src/streamfile.h index d21f0077b..6bd04397f 100644 --- a/Frameworks/vgmstream/vgmstream/src/streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.h @@ -361,7 +361,9 @@ size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf); /* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match * then loads the associated companion file if one is found */ -STREAMFILE *read_filemap_file(STREAMFILE *sf, int file_num); +STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num); +STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos); + /* hack to allow relative paths in various OSs */ void fix_dir_separators(char* filename); diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 8b9bedf1e..105c6bee4 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -40,12 +40,11 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_rfrm, init_vgmstream_cstr, init_vgmstream_gcsw, - init_vgmstream_ps2_ads, + init_vgmstream_ads, init_vgmstream_nps, init_vgmstream_rwsd, init_vgmstream_xa, - init_vgmstream_ps2_rxws, - init_vgmstream_ps2_rxw, + init_vgmstream_rxws, init_vgmstream_ngc_dsp_stm, init_vgmstream_exst, init_vgmstream_svag_kcet, @@ -194,7 +193,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_nds_rrds, init_vgmstream_ps2_tk5, init_vgmstream_ps2_vsf_tta, - init_vgmstream_ads, + init_vgmstream_ads_midway, init_vgmstream_ps2_mcg, init_vgmstream_zsd, init_vgmstream_ps2_vgs, @@ -262,11 +261,9 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_sqex_scd, init_vgmstream_ngc_nst_dsp, init_vgmstream_baf, - init_vgmstream_baf_badrip, init_vgmstream_msf, init_vgmstream_ps3_past, init_vgmstream_sgxd, - init_vgmstream_ngca, init_vgmstream_wii_ras, init_vgmstream_ps2_spm, init_vgmstream_x360_tra, @@ -395,7 +392,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_dsp_switch_audio, init_vgmstream_sadf, init_vgmstream_h4m, - init_vgmstream_ps2_ads_container, + init_vgmstream_ads_container, init_vgmstream_asf, init_vgmstream_xmd, init_vgmstream_cks, @@ -539,6 +536,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ init_vgmstream_raw_al, /* .al/al2 raw A-LAW */ init_vgmstream_zwdsp, /* fake format */ + init_vgmstream_baf_badrip, /* crap, to be removed */ + init_vgmstream_rxws_badrip, /* crap, to be removed */ #ifdef VGM_USE_FFMPEG init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */ #endif @@ -1409,7 +1408,7 @@ static int get_vgmstream_file_bitrate_from_streamfile(STREAMFILE* sf, int sample return get_vgmstream_file_bitrate_from_size(get_streamfile_size(sf), sample_rate, length_samples); } -static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* br) { +static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* br, int* p_uniques) { int i, ch; int bitrate = 0; @@ -1423,15 +1422,18 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* * become a bit high since its hard to detect only part of the file is needed. */ if (vgmstream->layout_type == layout_segmented) { + int uniques = 0; segmented_layout_data *data = (segmented_layout_data *) vgmstream->layout_data; for (i = 0; i < data->segment_count; i++) { - bitrate += get_vgmstream_file_bitrate_main(data->segments[i], br); + bitrate += get_vgmstream_file_bitrate_main(data->segments[i], br, &uniques); } + if (uniques) + bitrate /= uniques; /* average */ } else if (vgmstream->layout_type == layout_layered) { layered_layout_data *data = vgmstream->layout_data; for (i = 0; i < data->layer_count; i++) { - bitrate += get_vgmstream_file_bitrate_main(data->layers[i], br); + bitrate += get_vgmstream_file_bitrate_main(data->layers[i], br, NULL); } } else { @@ -1467,6 +1469,8 @@ static int get_vgmstream_file_bitrate_main(VGMSTREAM* vgmstream, bitrate_info_t* br->subsong[br->count] = subsong_cur; br->count++; + if (p_uniques) + (*p_uniques)++; if (vgmstream->stream_size) { /* stream_size applies to both channels but should add once and detect repeats (for current subsong) */ @@ -1494,7 +1498,7 @@ int get_vgmstream_average_bitrate(VGMSTREAM* vgmstream) { bitrate_info_t br = {0}; br.count_max = BITRATE_FILES_MAX; - return get_vgmstream_file_bitrate_main(vgmstream, &br); + return get_vgmstream_file_bitrate_main(vgmstream, &br, NULL); } diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 6b4869d5b..0bb148a1b 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -362,9 +362,9 @@ typedef enum { meta_BNSF, /* Bandai Namco Sound Format */ meta_XA, /* CD-ROM XA */ - meta_PS2_SShd, /* .ADS with SShd header */ + meta_ADS, meta_NPS, - meta_PS2_RXWS, /* Sony games (Genji, Okage Shadow King, Arc The Lad Twilight of Spirits) */ + meta_RXWS, meta_RAW_INT, meta_EXST, meta_SVAG_KCET, @@ -460,7 +460,7 @@ typedef enum { meta_SAT_BAKA, /* Crypt Killer */ meta_VSF, meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ - meta_ADS, /* Gauntlet Dark Legends (GC) */ + meta_ADS_MIDWAY, meta_PS2_SPS, /* Ape Escape 2 */ meta_PS2_XA2_RRP, /* RC Revenge Pro */ meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ @@ -568,7 +568,6 @@ typedef enum { meta_MSF, meta_PS3_PAST, /* Bakugan Battle Brawlers (PS3) */ meta_SGXD, /* Sony: Folklore, Genji, Tokyo Jungle (PS3), Brave Story, Kurohyo (PSP) */ - meta_NGCA, /* GoldenEye 007 (Wii) */ meta_WII_RAS, /* Donkey Kong Country Returns (Wii) */ meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */ meta_X360_TRA, /* Def Jam Rapstar */