From 18c22cd6b241a657389cf619761cd728d0efa146 Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Sun, 6 Jan 2019 01:34:00 -0800 Subject: [PATCH] Updated VGMStream to r1050-1973-g34f962eb --- .../libvgmstream.xcodeproj/project.pbxproj | 28 +- Frameworks/vgmstream/vgmstream/src/formats.c | 9 +- .../vgmstream/vgmstream/src/meta/ea_eaac.c | 54 +- .../vgmstream/vgmstream/src/meta/meta.h | 10 +- .../vgmstream/vgmstream/src/meta/pc_smp.c | 93 - .../vgmstream/vgmstream/src/meta/ps2_psh.c | 72 - Frameworks/vgmstream/vgmstream/src/meta/smp.c | 130 ++ .../vgmstream/vgmstream/src/meta/ubi_sb.c | 1642 +++++++++-------- Frameworks/vgmstream/vgmstream/src/meta/vsv.c | 85 + ...{ps2_psh_streamfile.h => vsv_streamfile.h} | 27 +- .../vgmstream/vgmstream/src/meta/wii_smp.c | 75 - Frameworks/vgmstream/vgmstream/src/meta/xwb.c | 2 +- .../vgmstream/vgmstream/src/vgmstream.c | 6 +- .../vgmstream/vgmstream/src/vgmstream.h | 5 +- 14 files changed, 1158 insertions(+), 1080 deletions(-) delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/smp.c create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/vsv.c rename Frameworks/vgmstream/vgmstream/src/meta/{ps2_psh_streamfile.h => vsv_streamfile.h} (50%) delete mode 100644 Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 289c33aee..8d676dc08 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -201,7 +201,6 @@ 834FE108215C79ED000A5D3D /* hd3_bd3.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0DF215C79EB000A5D3D /* hd3_bd3.c */; }; 834FE109215C79ED000A5D3D /* idsp_ie.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0E0215C79EB000A5D3D /* idsp_ie.c */; }; 834FE10A215C79ED000A5D3D /* nub_idsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0E1215C79EB000A5D3D /* nub_idsp.c */; }; - 834FE10B215C79ED000A5D3D /* ps2_psh_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0E2215C79EB000A5D3D /* ps2_psh_streamfile.h */; }; 834FE10C215C79ED000A5D3D /* fsb5_interleave_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 834FE0E3215C79EC000A5D3D /* fsb5_interleave_streamfile.h */; }; 834FE10D215C79ED000A5D3D /* vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0E4215C79EC000A5D3D /* vag.c */; }; 834FE10E215C79ED000A5D3D /* ahv.c in Sources */ = {isa = PBXBuildFile; fileRef = 834FE0E5215C79EC000A5D3D /* ahv.c */; }; @@ -323,7 +322,6 @@ 836F6FC018BDC2190095E648 /* p3d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8418BDC2180095E648 /* p3d.c */; }; 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8518BDC2180095E648 /* pc_adp.c */; }; 836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8618BDC2180095E648 /* pc_mxst.c */; }; - 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8718BDC2180095E648 /* pc_smp.c */; }; 836F6FC418BDC2190095E648 /* pc_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8818BDC2180095E648 /* pc_snds.c */; }; 836F6FC718BDC2190095E648 /* pona.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8B18BDC2180095E648 /* pona.c */; }; 836F6FC818BDC2190095E648 /* pos.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8C18BDC2180095E648 /* pos.c */; }; @@ -362,7 +360,6 @@ 836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB118BDC2180095E648 /* ps2_npsf.c */; }; 836F6FEE18BDC2190095E648 /* ps2_p2bt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB218BDC2180095E648 /* ps2_p2bt.c */; }; 836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB318BDC2180095E648 /* ps2_pnb.c */; }; - 836F6FF018BDC2190095E648 /* ps2_psh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB418BDC2180095E648 /* ps2_psh.c */; }; 836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB618BDC2180095E648 /* ps2_rnd.c */; }; 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB718BDC2180095E648 /* ps2_rstm.c */; }; 836F6FF418BDC2190095E648 /* rws.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB818BDC2180095E648 /* rws.c */; }; @@ -425,7 +422,6 @@ 836F703C18BDC2190095E648 /* wii_bns.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0018BDC2190095E648 /* wii_bns.c */; }; 836F703D18BDC2190095E648 /* wii_mus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0118BDC2190095E648 /* wii_mus.c */; }; 836F703E18BDC2190095E648 /* wii_ras.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0218BDC2190095E648 /* wii_ras.c */; }; - 836F703F18BDC2190095E648 /* wii_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0318BDC2190095E648 /* wii_smp.c */; }; 836F704018BDC2190095E648 /* wii_sng.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0418BDC2190095E648 /* wii_sng.c */; }; 836F704218BDC2190095E648 /* wii_sts.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0618BDC2190095E648 /* wii_sts.c */; }; 836F704318BDC2190095E648 /* wpd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0718BDC2190095E648 /* wpd.c */; }; @@ -521,6 +517,9 @@ 83EED5D3203A8BC7008BEB45 /* ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */; }; 83EED5D4203A8BC7008BEB45 /* aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D2203A8BC7008BEB45 /* aus.c */; }; 83EED5D6203A8BD7008BEB45 /* blocked_ea_swvr.c in Sources */ = {isa = PBXBuildFile; fileRef = 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */; }; + 83F0AA5F21E2028C004BBC04 /* smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F0AA5C21E2028B004BBC04 /* smp.c */; }; + 83F0AA6021E2028C004BBC04 /* vsv_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83F0AA5D21E2028B004BBC04 /* vsv_streamfile.h */; }; + 83F0AA6121E2028C004BBC04 /* vsv.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F0AA5E21E2028C004BBC04 /* vsv.c */; }; 83F5F8831908D0A400C8E65F /* fsb5.c in Sources */ = {isa = PBXBuildFile; fileRef = 83F5F8821908D0A400C8E65F /* fsb5.c */; }; 83FF0EBC1E93282100C58054 /* wwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 83FF0EBB1E93282100C58054 /* wwise.c */; }; /* End PBXBuildFile section */ @@ -840,7 +839,6 @@ 834FE0DF215C79EB000A5D3D /* hd3_bd3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hd3_bd3.c; sourceTree = ""; }; 834FE0E0215C79EB000A5D3D /* idsp_ie.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = idsp_ie.c; sourceTree = ""; }; 834FE0E1215C79EB000A5D3D /* nub_idsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub_idsp.c; sourceTree = ""; }; - 834FE0E2215C79EB000A5D3D /* ps2_psh_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ps2_psh_streamfile.h; sourceTree = ""; }; 834FE0E3215C79EC000A5D3D /* fsb5_interleave_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fsb5_interleave_streamfile.h; sourceTree = ""; }; 834FE0E4215C79EC000A5D3D /* vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vag.c; sourceTree = ""; }; 834FE0E5215C79EC000A5D3D /* ahv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahv.c; sourceTree = ""; }; @@ -964,7 +962,6 @@ 836F6E8418BDC2180095E648 /* p3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p3d.c; sourceTree = ""; }; 836F6E8518BDC2180095E648 /* pc_adp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_adp.c; sourceTree = ""; }; 836F6E8618BDC2180095E648 /* pc_mxst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_mxst.c; sourceTree = ""; }; - 836F6E8718BDC2180095E648 /* pc_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_smp.c; sourceTree = ""; }; 836F6E8818BDC2180095E648 /* pc_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_snds.c; sourceTree = ""; }; 836F6E8B18BDC2180095E648 /* pona.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pona.c; sourceTree = ""; }; 836F6E8C18BDC2180095E648 /* pos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pos.c; sourceTree = ""; }; @@ -1003,7 +1000,6 @@ 836F6EB118BDC2180095E648 /* ps2_npsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_npsf.c; sourceTree = ""; }; 836F6EB218BDC2180095E648 /* ps2_p2bt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_p2bt.c; sourceTree = ""; }; 836F6EB318BDC2180095E648 /* ps2_pnb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pnb.c; sourceTree = ""; }; - 836F6EB418BDC2180095E648 /* ps2_psh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_psh.c; sourceTree = ""; }; 836F6EB618BDC2180095E648 /* ps2_rnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rnd.c; sourceTree = ""; }; 836F6EB718BDC2180095E648 /* ps2_rstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rstm.c; sourceTree = ""; }; 836F6EB818BDC2180095E648 /* rws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rws.c; sourceTree = ""; }; @@ -1066,7 +1062,6 @@ 836F6F0018BDC2190095E648 /* wii_bns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_bns.c; sourceTree = ""; }; 836F6F0118BDC2190095E648 /* wii_mus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_mus.c; sourceTree = ""; }; 836F6F0218BDC2190095E648 /* wii_ras.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_ras.c; sourceTree = ""; }; - 836F6F0318BDC2190095E648 /* wii_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_smp.c; sourceTree = ""; }; 836F6F0418BDC2190095E648 /* wii_sng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_sng.c; sourceTree = ""; }; 836F6F0618BDC2190095E648 /* wii_sts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_sts.c; sourceTree = ""; }; 836F6F0718BDC2190095E648 /* wpd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wpd.c; sourceTree = ""; }; @@ -1159,6 +1154,9 @@ 83EED5D1203A8BC7008BEB45 /* ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_swvr.c; sourceTree = ""; }; 83EED5D2203A8BC7008BEB45 /* aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aus.c; sourceTree = ""; }; 83EED5D5203A8BD7008BEB45 /* blocked_ea_swvr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_ea_swvr.c; sourceTree = ""; }; + 83F0AA5C21E2028B004BBC04 /* smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = smp.c; sourceTree = ""; }; + 83F0AA5D21E2028B004BBC04 /* vsv_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vsv_streamfile.h; sourceTree = ""; }; + 83F0AA5E21E2028C004BBC04 /* vsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsv.c; sourceTree = ""; }; 83F412871E932F9A002E37D0 /* Vorbis.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Vorbis.xcodeproj; path = ../Vorbis/macosx/Vorbis.xcodeproj; sourceTree = ""; }; 83F5F8821908D0A400C8E65F /* fsb5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb5.c; sourceTree = ""; }; 83FF0EBB1E93282100C58054 /* wwise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wwise.c; sourceTree = ""; }; @@ -1609,7 +1607,6 @@ 83345A4C1F8AEB2700B2EAA4 /* pc_al2.c */, 8349A8F01FE6257C00E26435 /* pc_ast.c */, 836F6E8618BDC2180095E648 /* pc_mxst.c */, - 836F6E8718BDC2180095E648 /* pc_smp.c */, 836F6E8818BDC2180095E648 /* pc_snds.c */, 83CAB8DC1F0B0744001BC993 /* pc_xa30.c */, 8306B0D12098458F000302D4 /* pcm_sre.c */, @@ -1654,8 +1651,6 @@ 836F6EB218BDC2180095E648 /* ps2_p2bt.c */, 8349A8F21FE6257D00E26435 /* ps2_pcm.c */, 836F6EB318BDC2180095E648 /* ps2_pnb.c */, - 834FE0E2215C79EB000A5D3D /* ps2_psh_streamfile.h */, - 836F6EB418BDC2180095E648 /* ps2_psh.c */, 836F6EB618BDC2180095E648 /* ps2_rnd.c */, 836F6EB718BDC2180095E648 /* ps2_rstm.c */, 83709E021ECBC1A4005C03D3 /* ps2_rxws.c */, @@ -1716,6 +1711,7 @@ 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */, 836F6EF218BDC2190095E648 /* sli.c */, 8306B0D32098458F000302D4 /* smc_smh.c */, + 83F0AA5C21E2028B004BBC04 /* smp.c */, 8306B0C72098458D000302D4 /* smv.c */, 83A21F82201D8981000F04B9 /* sps_n1.c */, 836F6EF318BDC2190095E648 /* spt_spd.c */, @@ -1757,6 +1753,8 @@ 836F6EFE18BDC2190095E648 /* vs.c */, 8349A8F91FE6257E00E26435 /* vsf_tta.c */, 836F6EFF18BDC2190095E648 /* vsf.c */, + 83F0AA5D21E2028B004BBC04 /* vsv_streamfile.h */, + 83F0AA5E21E2028C004BBC04 /* vsv.c */, 8349A9011FE6258000E26435 /* vxn.c */, 8306B0C22098458C000302D4 /* waf.c */, 8306B0D02098458F000302D4 /* wave_segmented.c */, @@ -1766,7 +1764,6 @@ 836F6F0018BDC2190095E648 /* wii_bns.c */, 836F6F0118BDC2190095E648 /* wii_mus.c */, 836F6F0218BDC2190095E648 /* wii_ras.c */, - 836F6F0318BDC2190095E648 /* wii_smp.c */, 836F6F0418BDC2190095E648 /* wii_sng.c */, 836F6F0618BDC2190095E648 /* wii_sts.c */, 836F6F0718BDC2190095E648 /* wpd.c */, @@ -1869,8 +1866,8 @@ 834FE0B5215C798C000A5D3D /* acm_decoder_libacm.h in Headers */, 839E21E61F2EDAF100EE54D7 /* vorbis_custom_data_wwise.h in Headers */, 834FE103215C79ED000A5D3D /* ea_schl_streamfile.h in Headers */, + 83F0AA6021E2028C004BBC04 /* vsv_streamfile.h in Headers */, 48C2650F1A5D420800A0A3D6 /* vorbisfile.h in Headers */, - 834FE10B215C79ED000A5D3D /* ps2_psh_streamfile.h in Headers */, 836F705718BDC2190095E648 /* util.h in Headers */, 836F6F9A18BDC2190095E648 /* meta.h in Headers */, 8306B0D820984590000302D4 /* ea_eaac_streamfile.h in Headers */, @@ -2162,6 +2159,8 @@ 836F6FA818BDC2190095E648 /* nds_swav.c in Sources */, 8306B0D920984590000302D4 /* ngc_str_cauldron.c in Sources */, 834FE0FB215C79ED000A5D3D /* xau_konami.c in Sources */, + 83F0AA6121E2028C004BBC04 /* vsv.c in Sources */, + 83F0AA5F21E2028C004BBC04 /* smp.c in Sources */, 833A7A2E1ED11961003EC53E /* xau.c in Sources */, 836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */, 832BF81E21E0514B006F50F1 /* xps.c in Sources */, @@ -2282,7 +2281,6 @@ 834FE0BF215C79A9000A5D3D /* flat.c in Sources */, 836F6FE318BDC2190095E648 /* ps2_khv.c in Sources */, 836F6F6B18BDC2190095E648 /* agsc.c in Sources */, - 836F6FF018BDC2190095E648 /* ps2_psh.c in Sources */, 836F700E18BDC2190095E648 /* ps2_xa2.c in Sources */, 836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */, 836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */, @@ -2306,7 +2304,6 @@ 832BF80121E050B7006F50F1 /* pcfx_decoder.c in Sources */, 83AA5D271F6E2F9C0020821C /* stm.c in Sources */, 831BA61D1EAC61A500CF89B0 /* ubi_raki.c in Sources */, - 836F703F18BDC2190095E648 /* wii_smp.c in Sources */, 8306B0A520984552000302D4 /* blocked_ea_wve_au00.c in Sources */, 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */, 836F701518BDC2190095E648 /* ps3_past.c in Sources */, @@ -2334,7 +2331,6 @@ 834FE0F0215C79ED000A5D3D /* apc.c in Sources */, 836F6FFA18BDC2190095E648 /* ps2_spm.c in Sources */, 834D3A6E19F47C98001C54F6 /* g1l.c in Sources */, - 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */, 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */, 832BF82A21E0514B006F50F1 /* vs_square.c in Sources */, 834FE0B4215C798C000A5D3D /* ffmpeg_decoder_custom_opus.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index 0f2e3cd50..cabcf7829 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -308,7 +308,7 @@ static const char* extension_list[] = { "pona", "pos", "ps2stm", //fake extension for .stm (renamed? to be removed?) - "psh", // fake extension for VSV(?) Dawn of Mana needs to be checked again + "psh", //fake extension for .vsv (to be removed) "psnd", "psw", //fake extension for .wam (renamed, to be removed) @@ -452,7 +452,7 @@ static const char* extension_list[] = { "vpk", "vs", "vsf", - "vsv", // official extension for PSH? TODO: recheck Dawn of Mana + "vsv", "vxn", "waa", @@ -833,7 +833,7 @@ static const meta_info meta_info_list[] = { {meta_MUS_ACM, "InterPlay MUS ACM header"}, {meta_PS2_KCES, "Konami KCES Header"}, {meta_PS2_DXH, "Tokobot Plus DXH Header"}, - {meta_PS2_PSH, "Square Enix PSH/VSV Header"}, + {meta_VSV, "Square Enix .vsv Header"}, {meta_RIFF_WAVE_labl, "RIFF WAVE header with loop markers"}, {meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"}, {meta_RIFF_WAVE_wsmp, "RIFF WAVE header with wsmp looping info"}, @@ -907,7 +907,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_JOE, "Asobo Studio .JOE header"}, {meta_VGS, "Guitar Hero VGS Header"}, {meta_DC_DCSW_DCS, "Evil Twin DCS file with helper"}, - {meta_WII_SMP, "SMP DSP Header"}, + {meta_SMP, "Infernal Engine .smp header"}, {meta_MUL, "Crystal Dynamics .MUL header"}, {meta_THP, "THP Movie File Format Header"}, {meta_STS_WII, "Shikigami no Shiro (WII) Header"}, @@ -969,7 +969,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_GCM, "GCM 'MCG' Header"}, {meta_PS2_SMPL, "Homura SMPL header"}, {meta_PS2_MSA, "Success .MSA header"}, - {meta_PC_SMP, "Ghostbusters .smp Header"}, {meta_NGC_PDT, "Hudson .PDT header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, {meta_DSP_DDSP, ".DDSP header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c index 8c0d274da..21b905681 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_eaac.c @@ -133,53 +133,6 @@ fail: return NULL; } -/* .SPS - from Frostbite engine games, v1 header */ -VGMSTREAM * init_vgmstream_ea_sps_fb(STREAMFILE *streamFile) { //todo remove in the future, use better extractors - VGMSTREAM * vgmstream = NULL; - off_t start_offset = 0, header_offset = 0, sps_offset, max_offset; - - /* checks */ - /* should be .sps once extracted (filenames are hashed) */ - if (!check_extensions(streamFile,"sps")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x011006C0 && /* Need for Speed: The Run (PS3), Need for Speed: Rivals (PS4) */ - read_32bitBE(0x00,streamFile) != 0x01100180 && /* Need for Speed: The Run (X360) */ - read_32bitBE(0x00,streamFile) != 0x01100000) /* Need for Speed: The Run (PC) */ - goto fail; - - /* file has a Frostbite descriptor (SoundWaveAsset segments) data before actual .sps, exact size unknown. - * 0x00: segments/flags/sizes? 0x04: SegmentLength?, 0x08: SeekTableOffset?, 0x0c: mini SPS header - * rest: unknown fields? may be padded? (ex. 0x22 > 0x24, 0x1d > 0x20 */ - - /* actual offsets are probably somewhere but for now just manually search. */ - sps_offset = read_32bitBE(0x08, streamFile); /* seek table, number of entries unknown */ - max_offset = sps_offset + 0x3000; - if (max_offset > get_streamfile_size(streamFile)) - max_offset = get_streamfile_size(streamFile); - - /* find .sps start block */ - while (sps_offset < max_offset) { - if ((read_32bitBE(sps_offset, streamFile) & 0xFFFFFF00) == 0x48000000) { - header_offset = sps_offset + 0x04; - start_offset = sps_offset + (read_32bitBE(sps_offset, streamFile) & 0x00FFFFFF); - break; - } - sps_offset += 0x04; - } - - if (!start_offset) - goto fail; /* not found */ - - vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, header_offset, start_offset, meta_EA_SPS); - if (!vgmstream) goto fail; - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - /* EA ABK - ABK header seems to be same as in the old games but the sound table is different and it contains SNR/SNS sounds instead */ VGMSTREAM * init_vgmstream_ea_abk_new(STREAMFILE *streamFile) { int is_dupe, total_sounds = 0, target_stream = streamFile->stream_index; @@ -467,9 +420,8 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE *streamFile) { uint32_t num_sounds; uint8_t version, sub_version, block_id; off_t table_offset, entry_offset, snr_offset, sns_offset; - size_t snr_size, sns_size; + size_t /*snr_size,*/ sns_size; int32_t(*read_32bit)(off_t, STREAMFILE*); - int16_t(*read_16bit)(off_t, STREAMFILE*); STREAMFILE *musFile = NULL; VGMSTREAM *vgmstream = NULL; int target_stream = streamFile->stream_index; @@ -481,10 +433,8 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE *streamFile) { /* detect endianness */ if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */ read_32bit = read_32bitBE; - read_16bit = read_16bitBE; } else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */ read_32bit = read_32bitLE; - read_16bit = read_16bitLE; } else { goto fail; } @@ -520,7 +470,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus_new(STREAMFILE *streamFile) { entry_offset = table_offset + (target_stream - 1) * 0x1c; snr_offset = read_32bit(entry_offset + 0x08, musFile) * 0x10; sns_offset = read_32bit(entry_offset + 0x0c, musFile) * 0x80; - snr_size = read_32bit(entry_offset + 0x10, musFile); + //snr_size = read_32bit(entry_offset + 0x10, musFile); sns_size = read_32bit(entry_offset + 0x14, musFile); block_id = read_8bit(sns_offset, musFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 3b4fdbe0d..24c9f5fc9 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -227,7 +227,7 @@ VGMSTREAM * init_vgmstream_ps2_kces(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_dxh(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_vsv(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE * streamFile); @@ -360,8 +360,6 @@ VGMSTREAM * init_vgmstream_vgs(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_mul(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile); @@ -476,8 +474,6 @@ VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile); @@ -736,8 +732,6 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_smc_smh(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_sps_fb(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_ppst(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_opus_sps_n1_segmented(STREAMFILE *streamFile); @@ -827,4 +821,6 @@ VGMSTREAM * init_vgmstream_nus3audio(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_imc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_imc_container(STREAMFILE * streamFile); +VGMSTREAM * init_vgmstream_smp(STREAMFILE * streamFile); + #endif /*_META_H*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c deleted file mode 100644 index 52ab77623..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c +++ /dev/null @@ -1,93 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -/* .smp file, with MS ADPCM. From Ghostbusters (PC). */ - -VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - int channel_count; - off_t start_offset; - int interleave; - - int loop_flag = 0; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("smp",filename_extension(filename))) goto fail; - - /* 6? */ - if (6 != read_32bitLE(0,streamFile)) goto fail; - if (0 != read_32bitLE(0x14,streamFile)) goto fail; - if (4 != read_32bitLE(0x24,streamFile)) goto fail; - if (4 != read_32bitLE(0x2C,streamFile)) goto fail; - - start_offset = read_32bitLE(0x1c, streamFile); - /* check body start + body size = total size */ - if (start_offset + read_32bitLE(0x20,streamFile) != get_streamfile_size(streamFile)) goto fail; - - /* might also be codec id? */ - channel_count = read_32bitLE(0x28,streamFile); - if (channel_count != 1 && channel_count != 2) goto fail; - - /* verify MS ADPCM codec setup */ - { - int i; - /* coefficients and statement of 0x100 samples per block?? */ - static const uint8_t ms_setup[0x20] = { - 0x00,0x01,0x07,0x00,0x00,0x01,0x00,0x00, - 0x00,0x02,0x00,0xFF,0x00,0x00,0x00,0x00, - 0xC0,0x00,0x40,0x00,0xF0,0x00,0x00,0x00, - 0xCC,0x01,0x30,0xFF,0x88,0x01,0x18,0xFF}; - - for (i = 0; i < 0x20; i++) - { - if ((uint8_t)read_8bit(0x34+i,streamFile) != ms_setup[i]) goto fail; - } - - /* verify padding */ - for (i = 0x20; i+0x34 < start_offset; i++) - { - if (read_8bit(0x34+i,streamFile) != 0) goto fail; - } - } - - /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitLE(0x18,streamFile); - vgmstream->sample_rate = read_32bitLE(0x30,streamFile); - - vgmstream->coding_type = coding_MSADPCM; - vgmstream->layout_type = layout_none; // MS ADPCM does own interleave - interleave = 0x86*channel_count; - vgmstream->interleave_block_size = interleave; - - vgmstream->meta_type = meta_PC_SMP; - - /* open the file, set up each channel */ - { - int i; - - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[0].streamfile) goto fail; - - for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; - vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = - start_offset; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c deleted file mode 100644 index e0b11df27..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "ps2_psh_streamfile.h" - - -/* PSH/VSV - from Square Enix games [Dawn of Mana: Seiken Densetsu 4 (PS2), Kingdom Hearts Re:Chain of Memories (PS2)] */ -VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t loop_start, adjust, data_size, interleave; - - - /* checks */ - /* .psh: assumed? [Romancing SaGa: Minstrel's Song (PS2)] - * .vsv: official? [Kingdom Hearts HD I.5 + II.5 ReMIX (PS4)] */ - if (!check_extensions(streamFile, "psh,vsv")) - goto fail; - /* 0x00(2): 0x0000 (RS:MS) / 0x6440 (KH:RCoM) / varies (DoM) */ - if ((uint16_t)read_16bitBE(0x02,streamFile) != 0x6400) - goto fail; - - channel_count = 2; - start_offset = 0x00; /* correct, but needs some tricks to fix sound (see below) */ - interleave = 0x800; - - adjust = (uint16_t)read_16bitLE(0x04,streamFile) & 0x7FF; /* upper bits = ??? */ - data_size = (uint16_t)read_16bitLE(0x0c,streamFile) * interleave; - /* 0x0e: ? (may be 0x0001, or a low-ish value, not related to looping?) */ - loop_start = ((uint16_t)read_16bitLE(0x06,streamFile) & 0x7FFF) * interleave; /* uper bit == loop flag? */ - loop_flag = (loop_start != 0); /* (no known files loop from beginning to end) */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_PS2_PSH; - vgmstream->sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(data_size,channel_count); - - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start,channel_count); - vgmstream->loop_end_sample = vgmstream->num_samples; - - /* loops are odd, but comparing the audio wave with the OSTs these values seem correct */ - if (adjust == 0) { /* Romancing SaGa (PS2) */ - vgmstream->loop_start_sample -= ps_bytes_to_samples(channel_count*interleave,channel_count); /* maybe *before* loop block? */ - vgmstream->loop_start_sample -= ps_bytes_to_samples(0x200*channel_count,channel_count); /* maybe default adjust? */ - } - else { /* all others */ - vgmstream->loop_end_sample -= ps_bytes_to_samples((0x800 - adjust)*channel_count,channel_count); /* at last block + adjust is a 0x03 flag */ - } - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - - temp_streamFile = setup_ps2_psh_streamfile(streamFile, start_offset, data_size); - if (!temp_streamFile) goto fail; - - if (!vgmstream_open_stream(vgmstream, temp_streamFile, start_offset)) - goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/smp.c b/Frameworks/vgmstream/vgmstream/src/meta/smp.c new file mode 100644 index 000000000..2ddd52999 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/smp.c @@ -0,0 +1,130 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* .smp - Terminal Reality's Infernal Engine 'samples' [Ghostbusters: The Video Game (PS2/PS3/X360/PC/PSP), Chandragupta (PS2/PSP)] */ +VGMSTREAM * init_vgmstream_smp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + int loop_flag, channel_count, sample_rate, codec, version, num_samples, bps; + size_t data_size; + + + /* checks */ + if (!check_extensions(streamFile, "smp")) + goto fail; + + version = read_32bitLE(0x00,streamFile); + if (version != 0x05 && /* Ghostbusters (PS2), Mushroom Men (Wii) */ + version != 0x06 && /* Ghostbusters (PS3/X360/PC) */ + version != 0x07 && /* Ghostbusters (PSP) */ + version != 0x08) /* Chandragupta (PS2/PSP), Street Cricket Champions 1/2 (PSP) */ + goto fail; + + /* 0x04~14: guid? */ + if (read_32bitLE(0x14,streamFile) != 0) /* reserved? */ + goto fail; + num_samples = read_32bitLE(0x18,streamFile); + start_offset = read_32bitLE(0x1c,streamFile); + data_size = read_32bitLE(0x20,streamFile); + codec = read_32bitLE(0x24,streamFile); + channel_count = read_32bitLE(0x28,streamFile); + bps = read_32bitLE(0x2c,streamFile); + sample_rate = read_32bitLE(0x30,streamFile); + + loop_flag = 0; + if (start_offset + data_size != get_streamfile_size(streamFile)) + goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SMP; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + + switch(codec) { +#ifdef VGM_USE_FFMPEG + case 0x01: { + uint8_t buf[0x100]; + int bytes, block_size, joint_stereo, skip_samples; + + if (bps != 16) goto fail; + + block_size = 0x98 * vgmstream->channels; + joint_stereo = 0; + skip_samples = 0; /* unknown */ + + bytes = ffmpeg_make_riff_atrac3(buf,sizeof(buf), vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_size, joint_stereo, skip_samples); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + break; + } +#endif + + case 0x02: + if (bps != 4) goto fail; + if (channel_count > 1) goto fail; /* not known */ + /* 0x34: standard DSP header, but LE */ + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + dsp_read_coefs_le(vgmstream,streamFile,0x50,0x00); + break; + + case 0x04: + if (bps != 4) goto fail; + /* 0x34: standard MSADPCM coef table */ + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x86*channel_count; + break; + + case 0x06: + if (bps != 4) goto fail; + if (channel_count > 1) goto fail; /* not known */ + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + break; + +#ifdef VGM_USE_FFMPEG + case 0x07: { + uint8_t buf[0x100]; + int bytes, block_size, block_count; + + if (bps != 16) goto fail; + /* 0x34(0x28): XMA config/table? */ + + block_size = 0x8000; /* assumed, @0x3e(2)? */ + block_count = data_size / block_size + (data_size % block_size ? 1 : 0); /* @0x54(2)? */ + + bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size); + vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + //xma_fix_raw_samples(vgmstream, streamFile, start_offset,data_size, 0, ); //todo + break; + } +#endif + + default: + goto fail; + } + + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c index 3183310dd..b9bef55e5 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_sb.c @@ -3,7 +3,7 @@ typedef enum { UBI_ADPCM, RAW_PCM, RAW_PSX, RAW_DSP, RAW_XBOX, FMT_VAG, FMT_AT3, RAW_AT3, FMT_XMA1, RAW_XMA1, FMT_OGG } ubi_sb_codec; -typedef enum { UBI_PC, UBI_PS2, UBI_XBOX, UBI_GC, UBI_X360, UBI_3DS, UBI_PS3, UBI_WII, UBI_PSP } ubi_sb_platform; +typedef enum { UBI_PC, UBI_PS2, UBI_XBOX, UBI_GC, UBI_X360, UBI_PSP, UBI_PS3, UBI_WII, UBI_3DS } ubi_sb_platform; typedef struct { ubi_sb_platform platform; int big_endian; @@ -12,13 +12,26 @@ typedef struct { int autodetect_external; ubi_sb_codec codec; - /* main/fixed info */ + /* map base header info */ + off_t map_start; + off_t map_num; + size_t map_entry_size; + + uint32_t map_type; + uint32_t map_zero; + off_t map_offset; + off_t map_size; + char map_name[255]; + uint32_t map_unknown; + + /* SB main/fixed info */ uint32_t version; + uint32_t version_empty; size_t section1_num; size_t section2_num; size_t section3_num; size_t section4_num; - size_t extra_size; + size_t sectionX_size; int flag1; int flag2; @@ -26,74 +39,74 @@ typedef struct { int is_map; int map_version; - /* stream info config (format varies slightly per game) */ + /* header/stream info config */ + /* audio header varies slightly per game but not enough parse case by case, + * instead we configure sizes and offsets to where each variable is */ size_t section1_entry_size; size_t section2_entry_size; size_t section3_entry_size; - off_t stream_size_offset; - off_t extra_pointer_offset; - off_t stream_pointer_offset; - off_t external_flag_offset; - off_t samples_flag_offset; - off_t num_samples_offset; - off_t num_samples_offset2; - off_t sample_rate_offset; - off_t channels_offset; - off_t stream_type_offset; - off_t stream_name_offset; - off_t extra_name_offset; - size_t stream_name_size; - off_t stream_id_offset; - off_t xma_pointer_offset; - int has_short_channels; - int has_internal_names; - int has_extra_name_flag; - int has_rotating_ids; + size_t resource_name_size; + off_t cfg_stream_size; + off_t cfg_stream_offset; + off_t cfg_extra_offset; + off_t cfg_stream_id; + off_t cfg_stream_type; + + off_t cfg_external_flag; /* if the song is internal or external */ + off_t cfg_samples_flag; /* some headers have two possible locations for num_samples */ + off_t cfg_samples_bitflag; + off_t cfg_num_samples; + off_t cfg_num_samples2; + off_t cfg_sample_rate; + off_t cfg_channels; + off_t cfg_stream_name; /* where the resource name is within the header */ + off_t cfg_extra_name; /* where the resource name is within sectionX */ + off_t cfg_xma_offset; + int has_short_channels; /* channels value can be 16b or 32b */ + int has_internal_names; /* resource name doubles as internal name in some cases */ + int has_extra_name_flag; /* if cfg_extra_name is set (since often extra_name = -1 is 'not set' and >= 0 is offset) */ + int has_rotating_ids; /* stream id isn't set but is assigned using sequential rotation of sorts */ + //todo see if has_extra_name_flag can be removed /* derived */ size_t section1_offset; size_t section2_offset; size_t section3_offset; size_t section4_offset; - size_t extra_section_offset; + size_t sectionX_offset; size_t sounds_offset; - /* map info */ - off_t map_header_offset; - off_t map_num; - off_t map_offset; - char map_name[255]; + /* header/stream info */ + uint32_t header_id; /* 16b+16b group+sound id identifier (should be unique within sbX, but not smX) */ + uint32_t header_type; /* audio type (we only need 'standard audio' or 'layered audio') */ + size_t stream_size; /* size of the audio data */ + off_t stream_offset; /* offset within the data section (internal) or absolute (external) to the audio */ + off_t extra_offset; /* offset within sectionX to extra data */ - /* stream info */ - uint32_t header_id; - uint32_t header_type; - size_t stream_size; - off_t extra_offset; - off_t stream_offset; - uint32_t stream_id; - off_t xma_header_offset; - - int stream_samples; /* usually only for external resources */ + uint32_t stream_id; /* internal resource id needed to locate info */ + uint32_t stream_type; /* rough codec value */ + int num_samples; /* usually only for external resources */ int sample_rate; int channels; - uint32_t stream_type; - char stream_name[255]; - char extra_name[255]; - int header_idx; - off_t header_offset; + char resource_name[255]; /* filename to the external stream, or internal stream info for some games */ + char readable_name[255]; /* constructed name to show externally */ - int subtypes[16]; + int header_index; /* position within section2 (considering all possible header types) */ + off_t header_offset; /* offset of parsed audio header */ + off_t xma_header_offset; /* XMA has some extra header stuff*/ + + int types[16]; /* counts for each possible header types, for debugging */ } ubi_sb_header; static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *streamFile); static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int target_stream); -static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile); +static int config_sb_platform(ubi_sb_header * sb, STREAMFILE *streamFile); +static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile); -/* .SBx - banks from Ubisoft's sound engine ("DARE" / "UbiSound Driver") games in ~2000-2008 */ +/* .SBx - banks from Ubisoft's sound engine ("DARE" / "UbiSound Driver") games in ~2000-2008+ */ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { STREAMFILE *streamTest = NULL; int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; - //int16_t(*read_16bit)(off_t, STREAMFILE*) = NULL; ubi_sb_header sb = { 0 }; int ok; int target_stream = streamFile->stream_index; @@ -102,95 +115,53 @@ VGMSTREAM * init_vgmstream_ubi_sb(STREAMFILE *streamFile) { if (!check_extensions(streamFile, "sb0,sb1,sb2,sb3,sb4,sb5,sb6,sb7")) goto fail; - if (target_stream == 0) target_stream = 1; - - /* .sb0 (sound bank) is a small multisong format (loaded in memory?) that contains SFX data + /* .sbX (sound bank) is a small multisong format (loaded in memory?) that contains SFX data * but can also reference .ss0/ls0 (sound stream) external files for longer streams. * A companion .sp0 (sound project) describes files and if it uses BANKs (.sb0) or MAPs (.sm0). */ - /* sigh... PSP hijacks not one but *two* platform indexes */ - /* please add any PSP game versions under sb4 and sb5 sections so we can properly identify platform */ - sb.version = read_32bitLE(0x00, streamFile); - if (check_extensions(streamFile, "sb0")) { - sb.platform = UBI_PC; - } else if (check_extensions(streamFile, "sb1")) { - sb.platform = UBI_PS2; - } else if (check_extensions(streamFile, "sb2")) { - sb.platform = UBI_XBOX; - } else if (check_extensions(streamFile, "sb3")) { - sb.platform = UBI_GC; - } else if (check_extensions(streamFile, "sb4")) { - switch (sb.version) { - case 0x0012000C: /* Prince of Persia: Revelations (2005) */ - sb.platform = UBI_PSP; - break; - default: - sb.platform = UBI_X360; - break; - } - } else if (check_extensions(streamFile, "sb5")) { - switch (sb.version) { - case 0x00180005: /* Prince of Persia: Rival Swords (2007) */ - case 0x00180006: /* Rainbow Six Vegas (2007) */ - sb.platform = UBI_PSP; - break; - default: - sb.platform = UBI_3DS; - break; - } - } else if (check_extensions(streamFile, "sb6")) { - sb.platform = UBI_PS3; - } else if (check_extensions(streamFile, "sb7")) { - sb.platform = UBI_WII; - } else { + /* PLATFORM DETECTION */ + if (!config_sb_platform(&sb, streamFile)) goto fail; - } - - sb.big_endian = (sb.platform == UBI_GC || - sb.platform == UBI_PS3 || - sb.platform == UBI_X360 || - sb.platform == UBI_WII); if (sb.big_endian) { read_32bit = read_32bitBE; - //read_16bit = read_16bitBE; } else { read_32bit = read_32bitLE; - //read_16bit = read_16bitLE; } - /* file layout is: base header, section1, section2, extra section, section3, data (all except base header can be null) */ - - sb.version = read_32bit(0x00, streamFile); /* 16b+16b major/minor version */ - sb.section1_num = read_32bit(0x04, streamFile); /* group headers? */ - sb.section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ - sb.section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ - sb.extra_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */ - sb.flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */ - sb.flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */ - - ok = config_sb_header_version(&sb, streamFile); - if (!ok) { - VGM_LOG("UBI SB: unknown SB version+platform\n"); - goto fail; - } - - sb.section1_offset = 0x1c; - sb.section2_offset = sb.section1_offset + sb.section1_entry_size * sb.section1_num; - sb.extra_section_offset = sb.section2_offset + sb.section2_entry_size * sb.section2_num; - sb.section3_offset = sb.extra_section_offset + sb.extra_size; - sb.sounds_offset = sb.section3_offset + sb.section3_entry_size * sb.section3_num; - sb.is_map = 0; + if (target_stream == 0) target_stream = 1; /* use smaller I/O buffer for performance, as this read lots of small headers all over the place */ streamTest = reopen_streamfile(streamFile, 0x100); if (!streamTest) goto fail; - /* main parse */ + + /* SB HEADER */ + /* SBx layout: base header, section1, section2, extra section, section3, data (all except base header can be null) */ + sb.is_map = 0; + sb.version = read_32bit(0x00, streamFile); /* 16b+16b major/minor version */ + sb.section1_num = read_32bit(0x04, streamFile); /* group headers? */ + sb.section2_num = read_32bit(0x08, streamFile); /* streams headers (internal or external) */ + sb.section3_num = read_32bit(0x0c, streamFile); /* internal streams table */ + sb.sectionX_size = read_32bit(0x10, streamFile); /* extra table, unknown (config for non-audio types) except with DSP = coefs */ + sb.flag1 = read_32bit(0x14, streamFile); /* unknown, usually -1 but can be others (0/1/2/etc) */ + sb.flag2 = read_32bit(0x18, streamFile); /* unknown, usually -1 but can be others */ + + ok = config_sb_version(&sb, streamFile); + if (!ok) goto fail; + + sb.section1_offset = 0x1c; + sb.section2_offset = sb.section1_offset + sb.section1_entry_size * sb.section1_num; + sb.sectionX_offset = sb.section2_offset + sb.section2_entry_size * sb.section2_num; + sb.section3_offset = sb.sectionX_offset + sb.sectionX_size; + sb.sounds_offset = sb.section3_offset + sb.section3_entry_size * sb.section3_num; + if (!parse_sb_header(&sb, streamTest, target_stream)) goto fail; close_streamfile(streamTest); + + /* CREATE VGMSTREAM */ return init_vgmstream_ubi_sb_main(&sb, streamFile); fail: @@ -198,129 +169,96 @@ fail: return NULL; } -/* .SMx - essentially a set of SBx files, one per map, compiled into one file */ +/* .SMx - maps (sets of custom SBx files) also from Ubisoft's sound engine games in ~2000-2008+ */ VGMSTREAM * init_vgmstream_ubi_sm(STREAMFILE *streamFile) { STREAMFILE *streamTest = NULL; int32_t(*read_32bit)(off_t, STREAMFILE*) = NULL; //int16_t(*read_16bit)(off_t, STREAMFILE*) = NULL; ubi_sb_header sb = { 0 }; - size_t map_entry_size; int ok, i; int target_stream = streamFile->stream_index; + /* check extension (number represents the platform, see later) */ if (!check_extensions(streamFile, "sm0,sm1,sm2,sm3,sm4,sm5,sm6,sm7,lm0,lm1,lm2,lm3,lm4,lm5,lm6,lm7")) goto fail; - if (target_stream == 0) target_stream = 1; + /* .smX (sound map) is a set of slightly different sbX files, compiled into one "map" file. + * Map has a sbX per named area (example: menu, level1, boss1, level2...). + * This counts subsongs from all sbX, so totals can be massive, but there are splitters into mini-smX. */ - /* sigh... PSP hijacks not one but *two* platform indexes */ - /* please add any PSP game versions under sb4 and sb5 sections so we can properly identify platform */ - sb.version = read_32bitLE(0x00, streamFile); - if (check_extensions(streamFile, "sm0,lm0")) { - sb.platform = UBI_PC; - } else if (check_extensions(streamFile, "sm1,lm1")) { - sb.platform = UBI_PS2; - } else if (check_extensions(streamFile, "sm2,lm2")) { - sb.platform = UBI_XBOX; - } else if (check_extensions(streamFile, "sm3,lm3")) { - sb.platform = UBI_GC; - } else if (check_extensions(streamFile, "sm4,lm4")) { - switch (sb.version) { - case 0x0012000C: /* Splinter Cell: Essentials (2006) */ - sb.platform = UBI_PSP; - break; - default: - sb.platform = UBI_X360; - break; - } - } else if (check_extensions(streamFile, "sm5,lm5")) { - switch (sb.version) { - case 0x00190001: /* TMNT (2007) */ - case 0x00190005: /* Surf's Up (2007) */ - sb.platform = UBI_PSP; - break; - default: - sb.platform = UBI_3DS; - break; - } - } else if (check_extensions(streamFile, "sm6,lm6")) { - sb.platform = UBI_PS3; - } else if (check_extensions(streamFile, "sm7,lm7")) { - sb.platform = UBI_WII; - } else { + /* PLATFORM DETECTION */ + if (!config_sb_platform(&sb, streamFile)) goto fail; - } - - sb.big_endian = (sb.platform == UBI_GC || - sb.platform == UBI_PS3 || - sb.platform == UBI_X360 || - sb.platform == UBI_WII); if (sb.big_endian) { read_32bit = read_32bitBE; - //read_16bit = read_16bitBE; } else { read_32bit = read_32bitLE; - //read_16bit = read_16bitLE; } - sb.is_map = 1; - sb.version = read_32bit(0x00, streamFile); - sb.map_header_offset = read_32bit(0x04, streamFile); - sb.map_num = read_32bit(0x08, streamFile); - - ok = config_sb_header_version(&sb, streamFile); - if (!ok || sb.map_version == 0) { - VGM_LOG("UBI SB: unknown SM version+platform\n"); - goto fail; - } + if (target_stream == 0) target_stream = 1; /* use smaller I/O buffer for performance, as this read lots of small headers all over the place */ streamTest = reopen_streamfile(streamFile, 0x100); if (!streamTest) goto fail; - map_entry_size = (sb.map_version < 2) ? 0x30 : 0x34; + + /* SM BASE HEADER */ + /* SMx layout: base header with N map area offset/sizes (some? offsets within a SBx are relative) */ + /* SBx layout: base header, section1, section2, section4, extra section, section3, data (all except base header can be null?) */ + sb.is_map = 1; + sb.version = read_32bit(0x00, streamFile); + sb.map_start = read_32bit(0x04, streamFile); + sb.map_num = read_32bit(0x08, streamFile); + + ok = config_sb_version(&sb, streamFile); + if (!ok || sb.map_version == 0) goto fail; + + sb.map_entry_size = (sb.map_version < 2) ? 0x30 : 0x34; for (i = 0; i < sb.map_num; i++) { - /* basic layout: - * 0x00 - map type - * 0x04 - zero - * 0x08 - map section offset - * 0x0c - map section size - * 0x10 - map name (20 byte) */ - off_t offset = sb.map_header_offset + i * map_entry_size; - sb.map_offset = read_32bit(offset + 0x08, streamFile); - read_string(sb.map_name, sizeof(sb.map_name), offset + 0x10, streamFile); - /* latest format has another unknown long here or maybe string buffer is 4 bytes bigger */ + off_t offset = sb.map_start + i * sb.map_entry_size; - /* parse map section header */ - sb.section1_offset = read_32bit(sb.map_offset + 0x04, streamFile) + sb.map_offset; - sb.section1_num = read_32bit(sb.map_offset + 0x08, streamFile); - sb.section2_offset = read_32bit(sb.map_offset + 0x0c, streamFile) + sb.map_offset; - sb.section2_num = read_32bit(sb.map_offset + 0x10, streamFile); + /* SM AREA HEADER */ + sb.map_type = read_32bit(offset + 0x00, streamFile); /* usually 0/1=first, 0=rest */ + sb.map_zero = read_32bit(offset + 0x04, streamFile); + sb.map_offset = read_32bit(offset + 0x08, streamFile); + sb.map_size = read_32bit(offset + 0x0c, streamFile); /* includes sbX header, but not internal streams */ + read_string(sb.map_name, 0x20+1, offset + 0x10, streamFile); /* null-terminated and may contain garbage after null */ + if (sb.map_version >= 3) + sb.map_unknown = read_32bit(offset + 0x30, streamFile); /* uncommon, id/config? longer name? mem garbage? */ + + /* SB HEADER */ + sb.version_empty = read_32bit(sb.map_offset + 0x00, streamFile); /* sbX in maps don't set version */ + sb.section1_offset = read_32bit(sb.map_offset + 0x04, streamFile) + sb.map_offset; + sb.section1_num = read_32bit(sb.map_offset + 0x08, streamFile); + sb.section2_offset = read_32bit(sb.map_offset + 0x0c, streamFile) + sb.map_offset; + sb.section2_num = read_32bit(sb.map_offset + 0x10, streamFile); if (sb.map_version < 3) { - sb.section3_offset = read_32bit(sb.map_offset + 0x14, streamFile) + sb.map_offset; - sb.section3_num = read_32bit(sb.map_offset + 0x18, streamFile); - sb.extra_section_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; - sb.extra_size = read_32bit(sb.map_offset + 0x20, streamFile); + sb.section3_offset = read_32bit(sb.map_offset + 0x14, streamFile) + sb.map_offset; + sb.section3_num = read_32bit(sb.map_offset + 0x18, streamFile); + sb.sectionX_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; + sb.sectionX_size = read_32bit(sb.map_offset + 0x20, streamFile); } else { + sb.section4_offset = read_32bit(sb.map_offset + 0x14, streamFile); + sb.section4_num = read_32bit(sb.map_offset + 0x18, streamFile); + sb.section3_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; + sb.section3_num = read_32bit(sb.map_offset + 0x20, streamFile); + sb.sectionX_offset = read_32bit(sb.map_offset + 0x24, streamFile) + sb.map_offset; + sb.sectionX_size = read_32bit(sb.map_offset + 0x28, streamFile); + /* latest map format has another section with sounds after section 2 */ - sb.section4_offset = read_32bit(sb.map_offset + 0x14, streamFile); - sb.section4_num = read_32bit(sb.map_offset + 0x18, streamFile); - sb.section3_offset = read_32bit(sb.map_offset + 0x1c, streamFile) + sb.map_offset; - sb.section3_num = read_32bit(sb.map_offset + 0x20, streamFile); - sb.extra_section_offset = read_32bit(sb.map_offset + 0x24, streamFile) + sb.map_offset; - sb.extra_size = read_32bit(sb.map_offset + 0x28, streamFile); - - /* Let's just merge it with section 2 */ - sb.section2_num += sb.section4_num; - - /* for some reason, this is relative to section 4 here */ - sb.extra_section_offset += sb.section4_offset; + sb.section2_num += sb.section4_num; /* Let's just merge it with section 2 */ + sb.sectionX_offset += sb.section4_offset; /* for some reason, this is relative to section 4 here */ } + VGM_ASSERT(sb.map_type != 0 && sb.map_type != 1, "UBI SM: unknown map_type %x\n", (uint32_t)offset); + VGM_ASSERT(sb.map_zero != 0, "UBI SM: unknown map_zero %x\n", (uint32_t)offset); + //;VGM_ASSERT(sb.map_unknown != 0, "UBI SM: unknown map_unknown at %x\n", (uint32_t)offset); + VGM_ASSERT(sb.version_empty != 0, "UBI SM: unknown version_empty %x\n", (uint32_t)offset); + if (!parse_sb_header(&sb, streamTest, target_stream)) goto fail; } @@ -336,6 +274,8 @@ VGMSTREAM * init_vgmstream_ubi_sm(STREAMFILE *streamFile) { } close_streamfile(streamTest); + + /* CREATE VGMSTREAM */ return init_vgmstream_ubi_sb_main(&sb, streamFile); fail: @@ -351,9 +291,9 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str /* open external stream if needed */ if (sb->autodetect_external) { /* works most of the time but could give false positives */ - VGM_LOG("UBI SB: autodetecting external stream '%s'\n", sb->extra_name); + VGM_LOG("UBI SB: autodetecting external stream '%s'\n", sb->resource_name); - streamData = open_streamfile_by_filename(streamFile,sb->extra_name); + streamData = open_streamfile_by_filename(streamFile,sb->resource_name); if (!streamData) { streamData = streamFile; /* assume internal */ if (sb->stream_size > get_streamfile_size(streamData)) { @@ -365,18 +305,19 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str } } else if (sb->is_external) { - streamData = open_streamfile_by_filename(streamFile,sb->extra_name); + streamData = open_streamfile_by_filename(streamFile,sb->resource_name); if (!streamData) { - VGM_LOG("UBI SB: external stream '%s' not found\n", sb->extra_name); + VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name); goto fail; } } else { streamData = streamFile; } + //;VGM_LOG("UBI SB: stream offset=%x, size=%x, external=%i\n", (uint32_t)sb->stream_offset, sb->stream_size, sb->is_external); start_offset = sb->stream_offset; - //;VGM_LOG("start offset=%lx, external=%i\n", start_offset, sb->is_external); + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(sb->channels,loop_flag); @@ -387,7 +328,6 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->stream_size = sb->stream_size; vgmstream->meta_type = meta_UBI_SB; - switch(sb->codec) { case UBI_ADPCM: vgmstream->coding_type = coding_UBI_IMA; @@ -421,12 +361,8 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->interleave_block_size = sb->stream_size / sb->channels; vgmstream->num_samples = dsp_bytes_to_samples(sb->stream_size, sb->channels); - { - off_t coefs_offset = sb->extra_offset; - coefs_offset += 0x10; /* entry size is 0x40 (first/last 0x10 = unknown), per channel */ - - dsp_read_coefs_be(vgmstream,streamFile,coefs_offset, 0x40); - } + /* DSP extra info entry size is 0x40 (first/last 0x10 = unknown), per channel */ + dsp_read_coefs_be(vgmstream,streamFile,sb->extra_offset + 0x10, 0x40); break; case FMT_VAG: @@ -449,6 +385,7 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str /* skip weird value (3, 4) in Brothers in Arms: D-Day (PSP) */ if (read_32bitBE(start_offset+0x04,streamData) == 0x52494646) { + VGM_LOG("UBI SB: skipping unknown value 0x%x before RIFF\n", read_32bitBE(start_offset+0x00,streamData)); start_offset += 0x04; sb->stream_size -= 0x04; } @@ -459,11 +396,11 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - if (sb->stream_samples == 0) /* sometimes not known */ - sb->stream_samples = ffmpeg_data->totalSamples; - vgmstream->num_samples = sb->stream_samples; - if (sb->stream_samples != ffmpeg_data->totalSamples) { - VGM_LOG("UBI SB: header samples differ (%i vs %i)\n", sb->stream_samples, (size_t)ffmpeg_data->totalSamples); + if (sb->num_samples == 0) /* sometimes not known */ + sb->num_samples = ffmpeg_data->totalSamples; + vgmstream->num_samples = sb->num_samples; + if (sb->num_samples != ffmpeg_data->totalSamples) { + VGM_LOG("UBI SB: header samples differ (%i vs %i)\n", sb->num_samples, (size_t)ffmpeg_data->totalSamples); goto fail; } @@ -481,11 +418,11 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str joint_stereo = 0; encoder_delay = 0x00; /* TODO: this is incorrect */ - bytes = ffmpeg_make_riff_atrac3(buf, 0x100, sb->stream_samples, sb->stream_size, sb->channels, sb->sample_rate, block_size, joint_stereo, encoder_delay); + bytes = ffmpeg_make_riff_atrac3(buf, 0x100, sb->num_samples, sb->stream_size, sb->channels, sb->sample_rate, block_size, joint_stereo, encoder_delay); ffmpeg_data = init_ffmpeg_header_offset(streamData, buf, bytes, start_offset, sb->stream_size); if (!ffmpeg_data) goto fail; vgmstream->codec_data = ffmpeg_data; - vgmstream->num_samples = sb->stream_samples; + vgmstream->num_samples = sb->num_samples; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; break; @@ -531,7 +468,7 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = sb->stream_samples; + vgmstream->num_samples = sb->num_samples; vgmstream->stream_size = data_size; break; } @@ -554,7 +491,7 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->codec_data = ffmpeg_data; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = sb->stream_samples; + vgmstream->num_samples = sb->num_samples; break; } @@ -567,8 +504,8 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - vgmstream->num_samples = sb->stream_samples; /* ffmpeg_data->totalSamples */ - VGM_ASSERT(sb->stream_samples != ffmpeg_data->totalSamples, "UBI SB: header samples differ\n"); + vgmstream->num_samples = sb->num_samples; /* ffmpeg_data->totalSamples */ + VGM_ASSERT(sb->num_samples != ffmpeg_data->totalSamples, "UBI SB: header samples differ\n"); break; } @@ -578,9 +515,9 @@ static VGMSTREAM * init_vgmstream_ubi_sb_main(ubi_sb_header *sb, STREAMFILE *str goto fail; } - strcpy(vgmstream->stream_name, sb->stream_name); + strcpy(vgmstream->stream_name, sb->readable_name); - /* open the file for reading (can be an external stream, different from the current .sb0) */ + /* open the actual for decoding (streamData can be an internal or external stream) */ if ( !vgmstream_open_stream(vgmstream, streamData, start_offset) ) goto fail; @@ -591,111 +528,163 @@ fail: if (sb->is_external && streamData) close_streamfile(streamData); close_vgmstream(vgmstream); return NULL; - } /* debug stuff, for now */ -static void parse_descriptor_subtype(ubi_sb_header * sb, uint32_t descriptor_subtype, off_t offset) { +static void parse_header_type(ubi_sb_header * sb, uint32_t header_type, off_t offset) { - /* type may be flags? */ - /* all types may contain memory garbage, making it harder to identify */ - - switch(descriptor_subtype) { - /* standard audio */ - case 0x01: sb->subtypes[0x01]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* audio/garbage? [Surf's Up-map] */ - /* audio/garbage? [TMNT-map] */ - /* config? [Brothers in Arms: D-Day] */ - /* config? [Surf's Up-bank] */ - case 0x02: sb->subtypes[0x02]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* audio/garbage? [TMNT-map] */ - /* config? [Prince of Persia: The Two Thrones] */ - case 0x03: sb->subtypes[0x03]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* audio/garbage? [TMNT-map] */ - /* config? [Rainbow Six 3] */ - /* config? [Prince of Persia: Warrior Within] */ - /* config? [Prince of Persia: The Two Thrones] */ - /* config? [TMNT-bank] */ - /* config? [Surf's Up-map] */ - /* audio/garbage? [Myst IV demo] */ - /* config? [Brothers in Arms: D-Day] */ - /* config? [Surf's Up-bank] */ - case 0x04: sb->subtypes[0x04]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* audio/garbage? [TMNT-map] */ - /* config? [Prince of Persia: Warrior Within] */ - /* config? [Prince of Persia: The Two Thrones] */ - /* config? [Prince of Persia: Revelations] */ - /* config? [TMNT-bank] */ - case 0x05: sb->subtypes[0x05]++; break; - - /* layer? [Surf's Up-map] */ - /* layer [TMNT-bank] */ - /* layer [TMNT-map] */ - case 0x06: sb->subtypes[0x06]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* config? [Brothers in Arms: D-Day] */ - /* config? [Surf's Up-bank] */ - case 0x07: sb->subtypes[0x07]++; break; - - /* audio/garbage? [Splinter Cell: Chaos Theory] */ - /* audio/garbage? [TMNT-map] */ - /* config? [Prince of Persia: Warrior Within] */ - /* config? [Prince of Persia: The Two Thrones] */ - /* config? [TMNT-bank] */ - /* config? [Surf's Up-map] */ - /* config? [Brothers in Arms: D-Day] */ - /* config? [Surf's Up-bank] */ - case 0x08: sb->subtypes[0x08]++; break; - - /* related to voices? [Prince of Persia: Sands of Time] */ - /* config? [Rainbow Six 3] */ - /* config? [Myst IV demo] */ - case 0x0a: sb->subtypes[0x0a]++; break; - - /* config? [Prince of Persia: Sands of Time] */ - /* config? [Rainbow Six 3] */ - case 0x0c: sb->subtypes[0x0c]++; break; - - /* layer [Prince of Persia: Sands of Time] */ - /* layer [Rainbow Six 3] */ - case 0x0d: sb->subtypes[0x0d]++; break; - - /* config? [Rainbow Six 3] */ - /* config? [Myst IV demo] */ - case 0x0f: sb->subtypes[0x0f]++; break; + /* all types may contain memory garbage, making it harder to identify + * usually next types can contain memory from the previous type header, + * so if some non-audio type looks like audio it's probably repeating old data. + * This even happens for common fields (ex. type 06 at 0x08 has prev garbage, not stream size) */ + switch(header_type) { + case 0x01: sb->types[0x01]++; break; /* audio (all games) */ + case 0x02: sb->types[0x02]++; break; /* config? (later games) */ + case 0x03: sb->types[0x03]++; break; /* config? (later games) */ + case 0x04: sb->types[0x04]++; break; /* config? (all games) [recheck: SC:CT] */ + case 0x05: sb->types[0x05]++; break; /* config? (all games) [recheck: SC:CT] */ + case 0x06: sb->types[0x06]++; break; /* layer (later games) */ + case 0x07: sb->types[0x07]++; break; /* config? (later games) [recheck: SC:CT] */ + case 0x08: sb->types[0x08]++; break; /* config? (all games) [recheck: SC:CT] */ + //case 0x09: sb->types[0x09]++; break; /* ? */ + case 0x0a: sb->types[0x0a]++; break; /* config? (early games) */ + //case 0x0b: sb->types[0x0b]++; break; /* ? */ + case 0x0c: sb->types[0x0c]++; break; /* config? (early games) */ + case 0x0d: sb->types[0x0d]++; break; /* layer (early games) */ + case 0x0e: sb->types[0x0e]++; break; /* config? (early games) */ + case 0x0f: sb->types[0x0f]++; break; /* config? (early games) */ default: - VGM_LOG("UBI SB: unknown subtype %x at %x size %x\n", descriptor_subtype, (uint32_t)offset, sb->section2_entry_size); + VGM_LOG("UBI SB: unknown type %x at %x size %x\n", header_type, (uint32_t)offset, sb->section2_entry_size); break; //goto fail; } - //;VGM_ASSERT(descriptor_subtype != 0x01, "UBI SB: subtype %x at %x size %x\n", descriptor_subtype, (uint32_t)offset, sb->section2_entry_size); + ;VGM_ASSERT(header_type == 0x06 || header_type == 0x0d, + "UBI SB: type %x at %x size %x\n", header_type, (uint32_t)offset, sb->section2_entry_size); + + /* layer info for later + * some values may be flags/config as multiple 0x06 can point to the same layer, with different 'flags' */ + + /* 0x0d layer [Splinter Cell] */ + /* - type header: + * 0x18: stream offset? + * 0x20: (sample rate * layers) + 1? + * 0x24: layers/channels? + * 0x30: external flag + * 0x34: external name + * 0x5C: stream offset + * 0x64: stream size (not including padding) + * 0x78/7c: codec? + * + * - layer header at stream_offset: + * 0x00: version? (0x02000000) + * 0x04: layers + * 0x08: stream size (not including padding) + * 0x0c: size? + * 0x10: count? + * 0x14: min block size? + * + * - blocked data (unlike other layers, first block data is standard Ubi IMA headers, v3): + * 0x00: block number (from 0x01 to block_count) + * 0x04: current offset (within stream_offset) + * - per layer: + * 0x00: layer data size (varies between blocks, and one layer may have more than other, even the header) + */ + + /* Rainbow Six 3 */ //todo also check layer header + /* Prince of Persia: Sands of Time (all) 0x000A0004 */ + /* Batman: Rise of Sin Tzu (2003)(GC)-map - 0x000A0002 */ + /* - type header (bizarrely but thankfully doesn't change between platforms): + * 0x1c: sample rate * layers + * 0x20: layers/channels? + * 0x2c: external flag? + * 0x30: external name + * 0x58: stream offset + * 0x5c: original rate * layers? + * 0x60: stream size (not including padding) + * 0x64: number of samples + * + * - layer header at stream_offset (BE on GC): + * 0x00: version? (0x04) + * 0x04: layers + * 0x08: stream size (not including padding) + * 0x0c: blocks count + * 0x10: block header size + * 0x14: block size + * 0x18: ? + * 0x1c: size of next section + * - per layer: + * 0x00: layer header size + * codec header per layer + * 0x00~0x20: standard Ubi IMA header (version 0x05, LE) + * + * - blocked data: + * 0x00: block number (from 0x01 to block_count) + * 0x04: current offset (within stream_offset) + * 0x08: always 0x03 + * - per layer: + * 0x00: layer data size (varies between blocks, and one layer may have more than other) + */ + + /* Splinter Cell: Essentials (PSP)-map 0x0012000C */ + /* - type header: + * 0x08: header extra offset + * 0x1c: layers + * 0x28: external flag? + * 0x2c: external flag? + * 0x30: stream name + * 0x5c: config? + * 0x60: stream size + * 0x64: stream offset? + * + * - in header extra offset + * 0x00: sample rate + * 0x04: 16? + * 0x08: channels? + * 0x0c: codec? + * + * - layer header at stream_offset: + * 0x00: version? (0x07000000) + * 0x04: 0x03? + * 0x08: layers/channels? + * 0x0c: stream size + * 0x10: blocks count + * 0x14: block header size + * 0x18: block size + * - per layer: + * 0x00: approximate layer data size per block + * - per layer + * 0x00~0x0c: weird header thing? -1/0/0c... + * + * - blocked data: + * 0x00: block number (from 0x01 to block_count) + * 0x04: current offset (within stream_offset) + * 0x08: always 0x03 + * - per layer: + * 0x00: layer data size (varies between blocks, and one layer may have more than other) + */ - /* 0x06 layer [TMNT-bank] */ - /* - subtype header: + /* 0x06 layer [TMNT (PS2)-bank] */ + /* - type header: + * 0x08: header extra offset * 0x1c: external flag? * 0x20: layers/channels? * 0x24: layers/channels? * 0x28: config? same for all * 0x2c: stream size * 0x30: stream offset - * 0x38: always 0x037c - * (todo sample rate?) + * 0x38: name extra offset + * + * - in header extra offset + * 0x00: sample rate + * 0x04: channels? + * 0x08: codec? * * - layer header at stream_offset: * 0x00: version? (0x08000B00) - * 0x04: 0x0e? + * 0x04: config? (0x0e/0x0b/etc) * 0x08: layers/channels? * 0x0c: blocks count * 0x10: block header size @@ -713,58 +702,67 @@ static void parse_descriptor_subtype(ubi_sb_header * sb, uint32_t descriptor_sub * 0x00: layer data size (varies between blocks, and one layer may have more than other) */ - /* 0x06 layer [TMNT-map] */ - /* - subtype header: - * 0x20: layers/channels? - * 0x24: layers/channels * 2? - * 0x28: config? same for all + /* Splinter Cell 3D (2011)(3DS)-map 0x00130001 */ //todo + + /* Open Season (2005)(PS2)-map 0x00180003 */ + /* Rainbow Six Vegas (2007)(PSP)-bank 0x00180006 */ + /* Star Wars - Lethal Alliance (2006)(PSP)-map 0x00180007 */ + /* - type header: + * 0x0c: header extra offset + * 0x20: layers * 0x2c: stream size * 0x30: stream offset - * 0x38: 0x01D0/0118/etc - * 0x40: external flag? - * 0x48: codec? - * 0x54: codec? - * (todo sample rate?) + * 0x38: name extra offset + * + * - in header extra offset + * 0x00: sample rate + * 0x04: 16? + * 0x08: channels? + * 0x0c: codec (03=Ubi, 01=PCM16LE in SW:LA) * * - layer header at stream_offset: * - blocked data: - * same as TMNT-bank, but codec header size is 0 + * same as TMNT PSP-map */ - //todo Surf's Up-map - - /* 0x0d layer [Prince of Persia: Sands of Time] */ - /* 0x0d layer [Rainbow Six 3] */ //todo also check layer header - /* - subtype header (bizarrely but thankfully doesn't change between platforms): - * 0x1c: sample rate * layers - * 0x20: layers/channels? - * 0x2c: external flag? - * 0x30: external name - * 0x58: stream offset - * 0x5c: original rate * layers? - * 0x60: stream size (not including padding) - * 0x64: number of samples + /* TMNT (2007)(PSP)-map 0x00190001 */ + /* - type header: + * 0x0c: header extra offset + * 0x20: layers + * 0x24: total channels? + * 0x28: config? + * 0x2c: stream size + * 0x30: stream offset + * 0x38: name extra offset + * + * - in header extra offset + * 0x00: sample rate + * 0x04: channels? + * 0x08: codec? * * - layer header at stream_offset: - * 0x00: version? (0x04000000) - * 0x04: layers - * 0x08: stream size (not including padding) - * 0x0c: blocks count - * 0x10: block header size - * 0x14: block size - * 0x18: ? - * 0x1c: size of next section? - * - per layer: - * 0x00: layer header size - * codec header per layer - * 0x00~0x20: standard Ubi IMA header (version 0x05) - * * - blocked data: - * 0x00: block number (from 0x01 to block_count) - * 0x04: current offset (within stream_offset) - * 0x08: always 0x03 - * - per layer: - * 0x00: layer data size (varies between blocks, and one layer may have more than other) + * same as TMNT PS2-bank, but codec header size is 0 + */ + + //todo Surf's Up (PC?)-map + + /* Splinter Cell Classic Trilogy HD (2011)(PS3)-map 0x001d0000 */ + /* - type header: + * 0x0c: header extra offset + * 0x20: layers + * 0x44: stream size + * 0x48: stream offset + * 0x54: name extra offset + * + * - in header extra offset + * 0x00: sample rate + * 0x04: channels? + * 0x08: codec? + * + * - layer header at stream_offset: + * - blocked data: + * same as TMNT PS2-bank, but codec header size is 0 */ } @@ -787,24 +785,23 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe /* find target stream info in section2 */ for (i = 0; i < sb->section2_num; i++) { off_t offset = sb->section2_offset + sb->section2_entry_size*i; - uint32_t descriptor_subtype; + uint32_t header_type; - descriptor_subtype = read_32bit(offset + 0x04, streamFile); - parse_descriptor_subtype(sb, descriptor_subtype, offset); + header_type = read_32bit(offset + 0x04, streamFile); + parse_header_type(sb, header_type, offset); /* ignore non-audio entries */ - if (descriptor_subtype != 0x01) + if (header_type != 0x01) continue; - //;VGM_LOG("UBI SB: type at %lx\n", offset); /* weird case when there is no internal substream ID and just seem to rotate every time type changes, joy */ if (sb->has_rotating_ids) { /* assumes certain configs can't happen in this case */ int current_is_external = 0; - int type = read_32bit(offset + sb->stream_type_offset, streamFile); + int type = read_32bit(offset + sb->cfg_stream_type, streamFile); - if (sb->external_flag_offset) { - current_is_external = read_32bit(offset + sb->external_flag_offset, streamFile); - } else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) { + if (sb->cfg_external_flag) { + current_is_external = read_32bit(offset + sb->cfg_external_flag, streamFile); + } else if (sb->has_extra_name_flag && read_32bit(offset + sb->cfg_extra_name, streamFile) != 0xFFFFFFFF) { current_is_external = 1; /* -1 in extra_name means internal */ } @@ -845,83 +842,82 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe bank_streams++; if (sb->total_streams != target_stream) continue; - //;VGM_LOG("target at offset=%lx (size=%x)\n", offset, sb->section2_entry_size); /* parse audio entry based on config */ - sb->header_offset = offset; - sb->header_idx = i; + sb->header_index = i; + sb->header_offset = offset; - sb->header_id = read_32bit(offset + 0x00, streamFile); /* 16b+16b group+sound id */ - sb->header_type = read_32bit(offset + 0x04, streamFile); - sb->stream_size = read_32bit(offset + sb->stream_size_offset, streamFile); - sb->extra_offset = read_32bit(offset + sb->extra_pointer_offset, streamFile) + sb->extra_section_offset; /* within the extra section */ - sb->stream_offset = read_32bit(offset + sb->stream_pointer_offset, streamFile); /* within the data section */ - sb->channels = (sb->has_short_channels) ? - (uint16_t)read_16bit(offset + sb->channels_offset, streamFile) : - (uint32_t)read_32bit(offset + sb->channels_offset, streamFile); - sb->sample_rate = read_32bit(offset + sb->sample_rate_offset, streamFile); - sb->stream_type = read_32bit(offset + sb->stream_type_offset, streamFile); + sb->header_id = read_32bit(offset + 0x00, streamFile); + sb->header_type = read_32bit(offset + 0x04, streamFile); + sb->stream_size = read_32bit(offset + sb->cfg_stream_size, streamFile); + sb->extra_offset = read_32bit(offset + sb->cfg_extra_offset, streamFile) + sb->sectionX_offset; + sb->stream_offset = read_32bit(offset + sb->cfg_stream_offset, streamFile); + sb->channels = (sb->has_short_channels) ? + (uint16_t)read_16bit(offset + sb->cfg_channels, streamFile) : + (uint32_t)read_32bit(offset + sb->cfg_channels, streamFile); + sb->sample_rate = read_32bit(offset + sb->cfg_sample_rate, streamFile); + sb->stream_type = read_32bit(offset + sb->cfg_stream_type, streamFile); - /* Some games may store number of samples at different locations */ - if (sb->samples_flag_offset && - read_32bit(offset + sb->samples_flag_offset, streamFile) != 0) { - sb->stream_samples = read_32bit(offset + sb->num_samples_offset2, streamFile); - } else if (sb->num_samples_offset) { - sb->stream_samples = read_32bit(offset + sb->num_samples_offset, streamFile); + /* some games may store number of samples at different locations */ + if (sb->cfg_samples_flag && read_32bit(offset + sb->cfg_samples_flag, streamFile) != 0) { + sb->num_samples = read_32bit(offset + sb->cfg_num_samples2, streamFile); + } else if (sb->cfg_samples_bitflag && (read_32bit(offset + sb->cfg_samples_bitflag, streamFile) & 0x10)) { + sb->num_samples = read_32bit(offset + sb->cfg_num_samples2, streamFile); + VGM_ASSERT(sb->num_samples == 0, "UBI SB: bad bitflag found\n"); + } else if (sb->cfg_num_samples) { + sb->num_samples = read_32bit(offset + sb->cfg_num_samples, streamFile); } - if (sb-> has_rotating_ids) { - sb->stream_id = current_id; - } else if (sb->stream_id_offset) { - sb->stream_id = read_32bit(offset + sb->stream_id_offset, streamFile); + if (sb->has_rotating_ids) { + sb->stream_id = current_id; + } else if (sb->cfg_stream_id) { + sb->stream_id = read_32bit(offset + sb->cfg_stream_id, streamFile); } - /* external stream name can be found in the header (first versions) or the extra table (later versions) */ - if (sb->stream_name_offset) { - read_string(sb->extra_name, sb->stream_name_size, offset + sb->stream_name_offset, streamFile); + /* external stream name can be found in the header (first versions) or the sectionX table (later versions) */ + if (sb->cfg_stream_name) { + read_string(sb->resource_name, sb->resource_name_size, offset + sb->cfg_stream_name, streamFile); } else { - sb->stream_name_offset = read_32bit(offset + sb->extra_name_offset, streamFile); - read_string(sb->extra_name, sb->stream_name_size, sb->extra_section_offset + sb->stream_name_offset, streamFile); + sb->cfg_stream_name = read_32bit(offset + sb->cfg_extra_name, streamFile); + read_string(sb->resource_name, sb->resource_name_size, sb->sectionX_offset + sb->cfg_stream_name, streamFile); } - /* not always set and must be derived */ - if (sb->external_flag_offset) { - sb->is_external = read_32bit(offset + sb->external_flag_offset, streamFile); - } else if (sb->has_extra_name_flag && read_32bit(offset + sb->extra_name_offset, streamFile) != 0xFFFFFFFF) { + /* external flag is not always set and must be derived */ + if (sb->cfg_external_flag) { + sb->is_external = read_32bit(offset + sb->cfg_external_flag, streamFile); + } else if (sb->has_extra_name_flag && read_32bit(offset + sb->cfg_extra_name, streamFile) != 0xFFFFFFFF) { sb->is_external = 1; /* -1 in extra_name means internal */ } else if (sb->section3_num == 0) { sb->is_external = 1; } else { - sb->autodetect_external = 1; + sb->autodetect_external = 1; /* let the parser guess later */ - if (sb->extra_name[0] == '\0') + if (sb->resource_name[0] == '\0') sb->autodetect_external = 0; /* no name */ - if (sb->extra_size > 0 && sb->stream_name_offset > sb->extra_size) + if (sb->sectionX_size > 0 && sb->cfg_stream_name > sb->sectionX_size) sb->autodetect_external = 0; /* name outside extra table == is internal */ } + //todo check sb->has_internal_names in case of garbage /* build a full name for stream */ if (sb->is_map) { - if (sb->extra_name[0]) { - snprintf(sb->stream_name, sizeof(sb->stream_name), "%s/%d/%s", sb->map_name, bank_streams, sb->extra_name); + if (sb->resource_name[0]) { + snprintf(sb->readable_name, sizeof(sb->readable_name), "%s/%d/%08x/%s", sb->map_name, bank_streams, sb->header_id, sb->resource_name); } else { - snprintf(sb->stream_name, sizeof(sb->stream_name), "%s/%d", sb->map_name, bank_streams); + snprintf(sb->readable_name, sizeof(sb->readable_name), "%s/%d/%08x", sb->map_name, bank_streams, sb->header_id); } } else { - strncpy(sb->stream_name, sb->extra_name, sizeof(sb->stream_name)); + if (sb->resource_name[0]) { + snprintf(sb->readable_name, sizeof(sb->readable_name), "%08x/%s", sb->header_id, sb->resource_name); + } else { + snprintf(sb->readable_name, sizeof(sb->readable_name), "%s", sb->resource_name); + } } + } -#if 0 - { - int i; - VGM_LOG("UBI subtypes: "); - for (i = 0; i < 16; i++) { - VGM_ASSERT(sb->subtypes[i], "%02x=%i ",i,sb->subtypes[i]); - } - VGM_LOG("\n"); - } -#endif + //;VGM_LOG("UBI SB: types "); for (int i = 0; i < 16; i++) { VGM_ASSERT(sb->types[i], "%02x=%i ",i,sb->types[i]); } VGM_LOG("\n"); + if (sb->is_map) { if (bank_streams == 0 || target_stream <= prev_streams || target_stream > sb->total_streams) @@ -938,11 +934,13 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe } } - if (!(sb->stream_id_offset || sb->has_rotating_ids || sb->is_map) && sb->section3_num > 1) { + if (!(sb->cfg_stream_id || sb->has_rotating_ids || sb->is_map) && sb->section3_num > 1) { VGM_LOG("UBI SB: unexpected number of internal stream groups %i\n", sb->section3_num); goto fail; } + //;VGM_LOG("UBI SB: target at %x (cfg %x), extra=%x, name=%s\n", (uint32_t)sb->header_offset, sb->section2_entry_size, (uint32_t)sb->extra_offset, sb->resource_name); + /* happens in some versions */ if (sb->stream_type > 0xFF) { @@ -955,6 +953,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe case 0x00: /* platform default (rarely external) */ switch (sb->platform) { case UBI_PC: + case UBI_3DS: sb->codec = RAW_PCM; break; @@ -991,7 +990,6 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe default: VGM_LOG("UBI SB: unknown internal format\n"); goto fail; - } break; @@ -1026,7 +1024,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe } break; - case 0x06: /* PS ADPCM (later PS3 games?) */ + case 0x06: /* PS ADPCM (later PSP and PS3(?) games) */ sb->codec = RAW_PSX; break; @@ -1045,14 +1043,14 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe if (sb->codec == RAW_XMA1) { /* this field is only seen in X360 games, points at XMA1 header in extra section */ - sb->xma_header_offset = read_32bit(sb->header_offset + sb->xma_pointer_offset, streamFile) + sb->extra_section_offset; + sb->xma_header_offset = read_32bit(sb->header_offset + sb->cfg_xma_offset, streamFile) + sb->sectionX_offset; } /* uncommon but possible */ //VGM_ASSERT(sb->is_external && sb->section3_num != 0, "UBI SS: mixed external and internal streams\n"); /* seems that can be safely ignored */ - //VGM_ASSERT(sb->is_external && sb->stream_id_offset && sb->stream_id > 0, "UBI SB: unexpected external stream with stream id\n"); + //VGM_ASSERT(sb->is_external && sb->cfg_stream_id && sb->stream_id > 0, "UBI SB: unexpected external stream with stream id\n"); /* section 3: internal stream info */ if (!sb->is_external) { @@ -1066,11 +1064,11 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe uint32_t table2_num = read_32bit(offset + 0x10, streamFile); for (j = 0; j < table_num; j++) { - int idx = read_32bit(table_offset + 0x08 * j + 0x00, streamFile) & 0x0000FFFF; + int index = read_32bit(table_offset + 0x08 * j + 0x00, streamFile) & 0x0000FFFF; - if (idx == sb->header_idx) { - if (!(sb->stream_id_offset || sb->has_rotating_ids) && table2_num > 1) { - VGM_LOG("UBI SB: unexpected number of internal stream groups %i\n", table2_num); + if (index == sb->header_index) { + if (!(sb->cfg_stream_id || sb->has_rotating_ids) && table2_num > 1) { + VGM_LOG("UBI SB: unexpected number of internal stream map groups %i\n", table2_num); goto fail; } @@ -1101,7 +1099,7 @@ static int parse_sb_header(ubi_sb_header * sb, STREAMFILE *streamFile, int targe } else { sb->stream_offset += sb->sounds_offset; - if ((sb->stream_id_offset || sb->has_rotating_ids) && sb->section3_num > 1) { + if ((sb->cfg_stream_id || sb->has_rotating_ids) && sb->section3_num > 1) { /* internal sounds are split into groups based on their type with their offsets being relative to group start * this table contains sizes of each group, adjust offset based on group ID of our sound */ for (i = 0; i < sb->section3_num; i++) { @@ -1121,12 +1119,79 @@ fail: return 0; } +static int config_sb_platform(ubi_sb_header * sb, STREAMFILE *streamFile) { + char filename[PATH_LIMIT]; + int filename_len; + char platform_char; + uint32_t version; -static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) { + /* to find out hijacking platforms */ + version = read_32bitLE(0x00, streamFile); + + /* get X from .sbX/smX */ + get_streamfile_name(streamFile,filename,sizeof(filename)); + filename_len = strlen(filename); + platform_char = filename[filename_len - 1]; + + switch(platform_char) { + case '0': + sb->platform = UBI_PC; + break; + case '1': + sb->platform = UBI_PS2; + break; + case '2': + sb->platform = UBI_XBOX; + break; + case '3': + sb->platform = UBI_GC; + break; + case '4': + switch(version) { /* early PSP clashes with X360 */ + case 0x0012000C: /* multiple games use this ID and all are sb4/sm4 */ + sb->platform = UBI_PSP; + break; + default: + sb->platform = UBI_X360; + break; + } + break; + case '5': + switch(version) { /* 3DS could be sb8/sm8 but somehow hijacks extension */ + case 0x00130001: /* Splinter Cell 3DS (2011) */ + sb->platform = UBI_3DS; + break; + default: + sb->platform = UBI_PSP; + break; + } + break; + case '6': + sb->platform = UBI_PS3; + break; + case '7': + sb->platform = UBI_WII; + break; + default: + goto fail; + } + + sb->big_endian = + sb->platform == UBI_GC || + sb->platform == UBI_PS3 || + sb->platform == UBI_X360 || + sb->platform == UBI_WII; + + + return 1; +fail: + return 0; +} + +static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile) { int is_biadd_psp = 0; - - /* The format varies with almost every game + platform (some kind of class serialization?), + /* The type 1 audio header varies with almost every game + platform (some kind of class serialization?), * support is done case-by-case as offsets move slightly. Basic layout: * - fixed part (0x00..0x14) * - garbage, flags @@ -1141,15 +1206,20 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) * Later version don't have filename per header but in the extra section. */ + //todo set samples flag where "varies" /* common */ sb->section3_entry_size = 0x08; - sb->stream_name_size = 0x24; /* maybe 0x28 or 0x20 for some but ok enough (null terminated) */ - + sb->resource_name_size = 0x24; /* maybe 0x28 or 0x20 for some but ok enough (null terminated) */ /* this is same in all games since ~2003 */ - sb->stream_size_offset = 0x08; - sb->extra_pointer_offset = 0x0c; - sb->stream_pointer_offset = 0x10; + sb->cfg_stream_size = 0x08; + sb->cfg_extra_offset = 0x0c; + sb->cfg_stream_offset = 0x10; + + + /* Batman: Vengeance (2001)(PS2)-map 0x00000003 */ + /* Batman: Vengeance (2001)(GC)-map 0x00000003 */ + /* Disney's Tarzan: Untamed (2001)(GC)-map 0x00000003 */ #if 0 /* Donald Duck: Goin' Quackers (2002)(GC)-map */ @@ -1163,28 +1233,29 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 1; - sb->stream_size_offset = 0x0c; - sb->extra_pointer_offset = 0x10; - sb->stream_pointer_offset = 0x14; + sb->cfg_stream_size = 0x0c; + sb->cfg_extra_offset = 0x10; + sb->cfg_stream_offset = 0x14; - sb->external_flag_offset = 0x30; - sb->stream_id_offset = 0x34; - sb->num_samples_offset = 0x48; - sb->sample_rate_offset = 0x50; - sb->channels_offset = 0x56; - sb->stream_type_offset = 0x58; - sb->stream_name_offset = 0x5c; + sb->cfg_external_flag = 0x30; + sb->cfg_stream_id = 0x34; + sb->cfg_num_samples = 0x48; + sb->cfg_sample_rate = 0x50; + sb->cfg_channels = 0x56; + sb->cfg_stream_type = 0x58; + sb->cfg_stream_name = 0x5c; sb->has_short_channels = 1; return 1; } - +#endif +#if 0 /* Splinter Cell (2002)(PC)-map */ /* Splinter Cell: Pandora Tomorrow (2004)(PC)-map */ if (sb->version == 0x00000007 && sb->platform == UBI_PC) { /* Stream types: * 0x01: PCM - * 0x02: unsupported codec, appears to be another version of Ubi IMA + * 0x02: unsupported codec, appears to be Ubi IMA in a blocked layout * 0x04: Ubi IMA v3 (not Vorbis) */ sb->section1_entry_size = 0x58; @@ -1192,17 +1263,17 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 1; - sb->stream_size_offset = 0x0c; - sb->extra_pointer_offset = 0x10; - sb->stream_pointer_offset = 0x14; + sb->cfg_stream_size = 0x0c; + sb->cfg_extra_offset = 0x10; + sb->cfg_stream_offset = 0x14; - sb->external_flag_offset = 0x28; - sb->stream_id_offset = 0x2c; - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4a; - sb->stream_type_offset = 0x4c; - sb->stream_name_offset = 0x50; + sb->cfg_external_flag = 0x28; + sb->cfg_stream_id = 0x2c; + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4a; + sb->cfg_stream_type = 0x4c; + sb->cfg_stream_name = 0x50; sb->has_short_channels = 1; sb->has_internal_names = 1; @@ -1216,15 +1287,16 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x64; sb->section2_entry_size = 0x80; - sb->external_flag_offset = 0x24; /* maybe 0x28 */ - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4a; - sb->stream_type_offset = 0x4c; - sb->stream_name_offset = 0x50; + sb->cfg_external_flag = 0x24; /* maybe 0x28 */ + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4a; + sb->cfg_stream_type = 0x4c; + sb->cfg_stream_name = 0x50; sb->has_short_channels = 1; sb->has_internal_names = 1; + //has layer 0d (main game) return 1; } @@ -1234,13 +1306,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0; /* no apparent flag */ - sb->channels_offset = 0x20; - sb->sample_rate_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->stream_name_offset = 0x40; - sb->stream_type_offset = 0x68; + sb->cfg_external_flag = 0; /* no apparent flag */ + sb->cfg_channels = 0x20; + sb->cfg_sample_rate = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_stream_name = 0x40; + sb->cfg_stream_type = 0x68; + //has layer 0d (main game) return 1; } @@ -1250,15 +1323,39 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x64; sb->section2_entry_size = 0x78; - sb->external_flag_offset = 0x24; /* maybe 0x28 */ - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4a; - sb->stream_type_offset = 0x4c; /* may contain garbage */ - sb->stream_name_offset = 0x50; + sb->cfg_external_flag = 0x24; /* maybe 0x28 */ + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4a; + sb->cfg_stream_type = 0x4c; /* may contain garbage */ + sb->cfg_stream_name = 0x50; sb->has_short_channels = 1; sb->has_internal_names = 1; + //has layer 0d (main game) + return 1; + } + + + //todo Batman offsets are slightly off for some subsongs, or maybe get external wrong (ex. 222~226) + /* Batman: Rise of Sin Tzu (2003)(GC)-map - 0x000A0002 */ + /* Prince of Persia: Sands of Time (2003)(GC)-bank */ + if ((sb->version == 0x000A0002 && sb->platform == UBI_GC) || /* Prince of Persia 1 port */ + (sb->version == 0x000A0004 && sb->platform == UBI_GC)) { /* main game */ + sb->section1_entry_size = 0x64; + sb->section2_entry_size = 0x74; + + sb->map_version = 2; + + sb->cfg_external_flag = 0x20; /* maybe 0x24 */ + sb->cfg_num_samples = 0x2c; + sb->cfg_sample_rate = 0x40; + sb->cfg_channels = 0x46; + sb->cfg_stream_type = 0x48; + sb->cfg_stream_name = 0x4c; + + sb->has_short_channels = 1; + //has layer 0d (POP:SOT main game, Batman) return 1; } @@ -1267,44 +1364,28 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0; /* no apparent flag */ - sb->channels_offset = 0x20; - sb->sample_rate_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->stream_name_offset = 0x40; - sb->stream_type_offset = 0x68; + sb->cfg_external_flag = 0; /* no apparent flag */ + sb->cfg_channels = 0x20; + sb->cfg_sample_rate = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_stream_name = 0x40; + sb->cfg_stream_type = 0x68; + //has layer 0d return 1; } - /* Prince of Persia: Sands of Time (2003)(GC)-bank */ - if ((sb->version == 0x000A0002 && sb->platform == UBI_GC) || /* Prince of Persia 1 port */ - (sb->version == 0x000A0004 && sb->platform == UBI_GC)) { /* main game */ - sb->section1_entry_size = 0x64; - sb->section2_entry_size = 0x74; - - sb->external_flag_offset = 0x20; /* maybe 0x24 */ - sb->num_samples_offset = 0x2c; - sb->sample_rate_offset = 0x40; - sb->channels_offset = 0x46; - sb->stream_type_offset = 0x48; - sb->stream_name_offset = 0x4c; - - sb->has_short_channels = 1; - return 1; - } - - /* Myst IV Demo (2004)(PC) (final game is different)-bank */ - if (sb->version == 0x00100000 && sb->platform == UBI_PC) { + /* Myst IV Demo (2004)(PC)-bank */ + if (sb->version == 0x00100000 && sb->platform == UBI_PC) { /* final game is different */ sb->section1_entry_size = 0x68; sb->section2_entry_size = 0xa4; - sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0x34; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4c; - sb->stream_type_offset = 0x50; - sb->stream_name_offset = 0x54; + sb->cfg_external_flag = 0x24; + sb->cfg_num_samples = 0x34; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4c; + sb->cfg_stream_type = 0x50; + sb->cfg_stream_name = 0x54; sb->has_internal_names = 1; return 1; @@ -1315,14 +1396,15 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x84; - sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4c; - sb->stream_type_offset = 0x50; - sb->stream_name_offset = 0x54; + sb->cfg_external_flag = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4c; + sb->cfg_stream_type = 0x50; + sb->cfg_stream_name = 0x54; sb->has_internal_names = 1; + //no layers return 1; } @@ -1331,13 +1413,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0; /* no apparent flag */ - sb->channels_offset = 0x20; - sb->sample_rate_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->stream_name_offset = 0x40; - sb->stream_type_offset = 0x68; + sb->cfg_external_flag = 0; /* no apparent flag */ + sb->cfg_channels = 0x20; + sb->cfg_sample_rate = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_stream_name = 0x40; + sb->cfg_stream_type = 0x68; + //no layers return 1; } @@ -1346,14 +1429,15 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x90; - sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0x44; - sb->sample_rate_offset = 0x58; - sb->channels_offset = 0x60; - sb->stream_type_offset = 0x64; /* may contain garbage */ - sb->stream_name_offset = 0x68; + sb->cfg_external_flag = 0x24; + sb->cfg_num_samples = 0x44; + sb->cfg_sample_rate = 0x58; + sb->cfg_channels = 0x60; + sb->cfg_stream_type = 0x64; /* may contain garbage */ + sb->cfg_stream_name = 0x68; sb->has_internal_names = 1; + //no layers return 1; } @@ -1362,17 +1446,18 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x6c; sb->section2_entry_size = 0x78; - sb->external_flag_offset = 0x20; - sb->num_samples_offset = 0x2c; - sb->sample_rate_offset = 0x40; - sb->channels_offset = 0x48; - sb->stream_type_offset = 0x4c; - sb->stream_name_offset = 0x50; + sb->cfg_external_flag = 0x20; + sb->cfg_num_samples = 0x2c; + sb->cfg_sample_rate = 0x40; + sb->cfg_channels = 0x48; + sb->cfg_stream_type = 0x4c; + sb->cfg_stream_name = 0x50; + //no layers return 1; } - /* two games with same id; use project file as identifier */ + /* two configs with same id; use project file as identifier */ if (sb->version == 0x0012000C && sb->platform == UBI_PSP) { STREAMFILE * streamTest = open_streamfile_by_filename(streamFile, "BIAAUDIO.SP4"); if (streamTest) { @@ -1383,20 +1468,25 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) /* Prince of Persia: Revelations (2005)(PSP)-bank */ /* Splinter Cell: Essentials (2006)(PSP)-map */ + /* Beowulf - The Game (2007)(PSP)-map */ if (sb->version == 0x0012000C && sb->platform == UBI_PSP && !is_biadd_psp) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x84; sb->map_version = 2; - sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4c; - sb->stream_type_offset = 0x50; - sb->stream_name_offset = 0x54; + sb->cfg_external_flag = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4c; + sb->cfg_stream_type = 0x50; + sb->cfg_stream_name = 0x54; sb->has_internal_names = 1; + //has layers 06 (SC:E only) + + //todo Beowulf needs rotating ids, but fails in some subsong offsets + // (ex. subsong 33415 should point to AT3 but offset is a VAGp) return 1; } @@ -1405,34 +1495,63 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x80; sb->section2_entry_size = 0x94; - sb->stream_id_offset = 0x2c; - sb->external_flag_offset = 0x24; - sb->samples_flag_offset = 0x28; - sb->num_samples_offset = 0x30; - sb->num_samples_offset2 = 0x38; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4c; - sb->stream_type_offset = 0x50; - sb->stream_name_offset = 0x54; + sb->cfg_external_flag = 0x24; + sb->cfg_samples_flag = 0x28; + sb->cfg_stream_id = 0x2c; + sb->cfg_num_samples = 0x30; + sb->cfg_num_samples2 = 0x38; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4c; + sb->cfg_stream_type = 0x50; + sb->cfg_stream_name = 0x54; sb->has_internal_names = 1; return 1; } +#if 0 + /* Splinter Cell 3D (2011)(3DS)-map */ + if (sb->version == 0x00130001 && sb->platform == UBI_3DS) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x4c; + + sb->map_version = 2; + + sb->cfg_external_flag = 0; + //sb->cfg_stream_id = 0; + sb->cfg_num_samples = 0x1c; + sb->cfg_sample_rate = 0x30; + sb->cfg_channels = 0x38; + sb->cfg_stream_type = 0x3c; + sb->cfg_extra_name = 0x40; + + sb->has_extra_name_flag = 1; + sb->has_rotating_ids = 1; //todo? + //has layer 06 + + //todo SC3DS codecs: + // 00: RAW_PCM + // 01: FMT_CWAV + // 03: Ubi IMA + return 1; + } +#endif + /* Prince of Persia: The Two Thrones (2005)(PC)-bank */ if (sb->version == 0x00150000 && sb->platform == UBI_PC) { sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x78; - sb->external_flag_offset = 0x2c; - sb->stream_id_offset = 0x34; - sb->num_samples_offset = 0x40; - sb->sample_rate_offset = 0x54; - sb->channels_offset = 0x5c; - sb->stream_type_offset = 0x60; - sb->extra_name_offset = 0x64; + sb->cfg_external_flag = 0x2c; + sb->cfg_stream_id = 0x34; + sb->cfg_num_samples = 0x40; + sb->cfg_sample_rate = 0x54; + sb->cfg_channels = 0x5c; + sb->cfg_stream_type = 0x60; + sb->cfg_extra_name = 0x64; sb->has_extra_name_flag = 1; + //no layers return 1; } @@ -1441,14 +1560,15 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x5c; - sb->external_flag_offset = 0; - sb->channels_offset = 0x2c; - sb->sample_rate_offset = 0x30; - sb->num_samples_offset = 0x3c; - sb->extra_name_offset = 0x4c; - sb->stream_type_offset = 0x50; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x2c; + sb->cfg_sample_rate = 0x30; + sb->cfg_num_samples = 0x3c; + sb->cfg_extra_name = 0x4c; + sb->cfg_stream_type = 0x50; sb->has_extra_name_flag = 1; + //no layers return 1; } @@ -1457,16 +1577,17 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x58; - sb->external_flag_offset = 0; - sb->num_samples_offset = 0x28; - sb->stream_id_offset = 0; - sb->sample_rate_offset = 0x3c; - sb->channels_offset = 0x44; - sb->stream_type_offset = 0x48; - sb->extra_name_offset = 0x4c; + sb->cfg_external_flag = 0; + sb->cfg_stream_id = 0; + sb->cfg_num_samples = 0x28; + sb->cfg_sample_rate = 0x3c; + sb->cfg_channels = 0x44; + sb->cfg_stream_type = 0x48; + sb->cfg_extra_name = 0x4c; sb->has_extra_name_flag = 1; sb->has_rotating_ids = 1; + //no layers return 1; } @@ -1475,13 +1596,14 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->num_samples_offset = 0x3c; - sb->sample_rate_offset = 0x50; - sb->channels_offset = 0x58; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x60; + sb->cfg_external_flag = 0x28; /* maybe 0x2c */ + sb->cfg_num_samples = 0x3c; + sb->cfg_sample_rate = 0x50; + sb->cfg_channels = 0x58; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x60; + //no layers return 1; } @@ -1492,12 +1614,12 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 2; - sb->external_flag_offset = 0x24; - sb->num_samples_offset = 0x30; - sb->sample_rate_offset = 0x44; - sb->channels_offset = 0x4c; - sb->stream_type_offset = 0x50; - sb->extra_name_offset = 0x54; + sb->cfg_external_flag = 0x24; + sb->cfg_num_samples = 0x30; + sb->cfg_sample_rate = 0x44; + sb->cfg_channels = 0x4c; + sb->cfg_stream_type = 0x50; + sb->cfg_extra_name = 0x54; return 1; } @@ -1509,13 +1631,13 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 2; - sb->external_flag_offset = 0; - sb->num_samples_offset = 0x18; - sb->stream_id_offset = 0; - sb->sample_rate_offset = 0x30; - sb->channels_offset = 0x38; - sb->stream_type_offset = 0x3c; - sb->extra_name_offset = 0x40; + sb->cfg_external_flag = 0; + sb->cfg_stream_id = 0; + sb->cfg_num_samples = 0x18; + sb->cfg_sample_rate = 0x30; + sb->cfg_channels = 0x38; + sb->cfg_stream_type = 0x3c; + sb->cfg_extra_name = 0x40; sb->has_extra_name_flag = 1; sb->has_rotating_ids = 1; @@ -1528,13 +1650,13 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0; - sb->num_samples_offset = 0x28; - sb->stream_id_offset = 0; - sb->sample_rate_offset = 0x3c; - sb->channels_offset = 0x44; - sb->stream_type_offset = 0x48; - sb->extra_name_offset = 0x58; + sb->cfg_external_flag = 0; + sb->cfg_stream_id = 0; + sb->cfg_num_samples = 0x28; + sb->cfg_sample_rate = 0x3c; + sb->cfg_channels = 0x44; + sb->cfg_stream_type = 0x48; + sb->cfg_extra_name = 0x58; return 1; } @@ -1545,12 +1667,12 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->num_samples_offset = 0x3c; - sb->sample_rate_offset = 0x50; - sb->channels_offset = 0x58; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x60; + sb->cfg_external_flag = 0x28; /* maybe 0x2c */ + sb->cfg_num_samples = 0x3c; + sb->cfg_sample_rate = 0x50; + sb->cfg_channels = 0x58; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x60; return 1; } @@ -1562,35 +1684,35 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 3; - sb->external_flag_offset = 0x2c; - sb->stream_id_offset = 0x34; - sb->channels_offset = 0x5c; - sb->sample_rate_offset = 0x54; - sb->num_samples_offset = 0x40; - sb->num_samples_offset2 = 0x48; - sb->stream_type_offset = 0x60; - sb->extra_name_offset = 0x64; + sb->cfg_external_flag = 0x2c; + sb->cfg_stream_id = 0x34; + sb->cfg_channels = 0x5c; + sb->cfg_sample_rate = 0x54; + sb->cfg_num_samples = 0x40; + sb->cfg_num_samples2 = 0x48; + sb->cfg_stream_type = 0x60; + sb->cfg_extra_name = 0x64; return 1; } /* Splinter Cell: Double Agent (2006)(X360)-map */ if (sb->version == 0x00180006 && sb->platform == UBI_X360) { - sb->section1_entry_size = 0x68; - sb->section2_entry_size = 0x78; + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x78; sb->map_version = 3; - sb->external_flag_offset = 0x2c; - sb->stream_id_offset = 0x30; - sb->samples_flag_offset = 0x34; - sb->channels_offset = 0x5c; - sb->sample_rate_offset = 0x54; - sb->num_samples_offset = 0x40; - sb->num_samples_offset2 = 0x48; - sb->stream_type_offset = 0x60; - sb->extra_name_offset = 0x64; - sb->xma_pointer_offset = 0x70; + sb->cfg_external_flag = 0x2c; + sb->cfg_stream_id = 0x30; + sb->cfg_samples_flag = 0x34; + sb->cfg_channels = 0x5c; + sb->cfg_sample_rate = 0x54; + sb->cfg_num_samples = 0x40; + sb->cfg_num_samples2 = 0x48; + sb->cfg_stream_type = 0x60; + sb->cfg_extra_name = 0x64; + sb->cfg_xma_offset = 0x70; return 1; } @@ -1602,13 +1724,13 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 3; - sb->external_flag_offset = 0; - sb->num_samples_offset = 0x28; - sb->stream_id_offset = 0; - sb->sample_rate_offset = 0x3c; - sb->channels_offset = 0x44; - sb->stream_type_offset = 0x48; - sb->extra_name_offset = 0x4c; + sb->cfg_external_flag = 0; + sb->cfg_num_samples = 0x28; + sb->cfg_stream_id = 0; + sb->cfg_sample_rate = 0x3c; + sb->cfg_channels = 0x44; + sb->cfg_stream_type = 0x48; + sb->cfg_extra_name = 0x4c; sb->has_extra_name_flag = 1; sb->has_rotating_ids = 1; @@ -1622,61 +1744,75 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->map_version = 3; - sb->external_flag_offset = 0x28; - sb->stream_id_offset = 0x2c; - sb->num_samples_offset = 0x3c; - sb->sample_rate_offset = 0x50; - sb->channels_offset = 0x58; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x60; + sb->cfg_external_flag = 0x28; + sb->cfg_stream_id = 0x2c; + sb->cfg_num_samples = 0x3c; + sb->cfg_sample_rate = 0x50; + sb->cfg_channels = 0x58; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x60; return 1; } + /* Open Season (2005)(PS2)-map - 0x00180003 */ + /* Open Season (2005)(PSP)-map - 0x00180003 */ + /* Star Wars - Lethal Alliance (2006)(PSP)-map - 0x00180007 */ + if ((sb->version == 0x00180003 && sb->platform == UBI_PS2) || + (sb->version == 0x00180003 && sb->platform == UBI_PSP) || + (sb->version == 0x00180007 && sb->platform == UBI_PSP)) { + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x54; + + sb->map_version = 3; + + sb->cfg_external_flag = 0; + sb->cfg_samples_bitflag = 0x20; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + sb->cfg_num_samples = 0x34; + sb->cfg_num_samples = 0x3c; + sb->cfg_extra_name = 0x44; + sb->cfg_stream_type = 0x48; + + sb->has_extra_name_flag = 1; + //has layer 06 + return 1; + } + /* Prince of Persia: Rival Swords (2007)(PSP)-bank */ if (sb->version == 0x00180005 && sb->platform == UBI_PSP) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x54; - sb->external_flag_offset = 0; - sb->channels_offset = 0x28; - sb->sample_rate_offset = 0x2c; - //sb->num_samples_offset = 0x34 or 0x3c /* varies */ - sb->extra_name_offset = 0x44; - sb->stream_type_offset = 0x48; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + //sb->cfg_num_samples = 0x34 or 0x3c /* varies */ + sb->cfg_extra_name = 0x44; + sb->cfg_stream_type = 0x48; sb->has_extra_name_flag = 1; return 1; } -#if 0 +#if 0 //todo join with other 0x0018000x configs? /* Rainbow Six Vegas (2007)(PSP)-bank */ if (sb->version == 0x00180006 && sb->platform == UBI_PSP) { sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x54; - sb->external_flag_offset = 0; - sb->channels_offset = 0x28; - sb->sample_rate_offset = 0x2c; - //sb->num_samples_offset = 0x34 or 0x3c /* varies */ - sb->extra_name_offset = 0x44; - sb->stream_type_offset = 0x48; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + //sb->cfg_num_samples = 0x34 or 0x3c /* varies */ + sb->cfg_extra_name = 0x44; + sb->cfg_stream_type = 0x48; sb->has_extra_name_flag = 1; - sb->has_rotating_ids = 1; + sb->has_rotating_ids = 1; //??? return 1; } - - /* todo Rainbow Six Vegas changes: - * some streams use type 0x06 instead of 0x01, known values: - * 0x0c: header offset in extra table? - * 0x2c: stream size - * 0x30: stream offset - * most other fields are fixed, comparing different files - * header is in the extra table, after the stream name (repeated?) - * (0x04: sample rate, 0x0c: channels, etc) - * stream data may be newer Ubi ADPCM (see DecUbiSnd) - */ #endif /* Prince of Persia: Rival Swords (2007)(Wii)-bank */ @@ -1684,12 +1820,12 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x70; - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->extra_name_offset = 0x58; - sb->stream_type_offset = 0x5c; + sb->cfg_external_flag = 0x28; /* maybe 0x2c */ + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_extra_name = 0x58; + sb->cfg_stream_type = 0x5c; return 1; } @@ -1699,13 +1835,13 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x74; - sb->external_flag_offset = 0x28; - sb->stream_id_offset = 0x2c; - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; + sb->cfg_external_flag = 0x28; + sb->cfg_stream_id = 0x2c; + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; return 1; } @@ -1715,14 +1851,15 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x48; sb->section2_entry_size = 0x5c; - sb->external_flag_offset = 0; - sb->channels_offset = 0x28; - sb->sample_rate_offset = 0x2c; - //sb->num_samples_offset = 0x34 or 0x3c /* varies */ - sb->extra_name_offset = 0x44; - sb->stream_type_offset = 0x48; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + //sb->cfg_num_samples = 0x34 or 0x3c /* varies */ + sb->cfg_extra_name = 0x44; + sb->cfg_stream_type = 0x48; sb->has_extra_name_flag = 1; + //has layer 06 return 1; } @@ -1731,12 +1868,12 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x6c; - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; + sb->cfg_external_flag = 0x28; /* maybe 0x2c */ + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; return 1; } @@ -1746,34 +1883,35 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x70; - sb->external_flag_offset = 0x28; - sb->samples_flag_offset = 0x30; - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->num_samples_offset2 = 0x50; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; - sb->xma_pointer_offset = 0x6c; + sb->cfg_external_flag = 0x28; + sb->cfg_samples_flag = 0x30; + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_num_samples2 = 0x50; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; + sb->cfg_xma_offset = 0x6c; return 1; } /* TMNT (2007)(PSP)-map */ if (sb->version == 0x00190001 && sb->platform == UBI_PSP) { - sb->section1_entry_size = 0x48; - sb->section2_entry_size = 0x58; + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; sb->map_version = 3; - sb->external_flag_offset = 0; - sb->channels_offset = 0x28; - sb->sample_rate_offset = 0x2c; - sb->num_samples_offset = 0x34; - sb->stream_type_offset = 0x48; - sb->extra_name_offset = 0x44; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + sb->cfg_num_samples = 0x34; + sb->cfg_stream_type = 0x48; + sb->cfg_extra_name = 0x44; sb->has_extra_name_flag = 1; + //has layer 06 return 1; } @@ -1782,12 +1920,12 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) sb->section1_entry_size = 0x68; sb->section2_entry_size = 0x74; - sb->external_flag_offset = 0x28; /* maybe 0x2c */ - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; + sb->cfg_external_flag = 0x28; /* maybe 0x2c */ + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; return 1; } @@ -1795,77 +1933,99 @@ static int config_sb_header_version(ubi_sb_header * sb, STREAMFILE *streamFile) /* Surf's Up (2007)(PS3)-bank */ /* Splinter Cell: Double Agent (2007)(PS3)-map */ if (sb->version == 0x00190005 && sb->platform == UBI_PS3) { - sb->section1_entry_size = 0x68; - sb->section2_entry_size = 0x70; + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; sb->map_version = 3; - sb->external_flag_offset = 0x28; - sb->stream_id_offset = 0x2c; - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; + sb->cfg_external_flag = 0x28; + sb->cfg_stream_id = 0x2c; + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; return 1; } /* Surf's Up (2007)(X360)-bank */ if (sb->version == 0x00190005 && sb->platform == UBI_X360) { - sb->section1_entry_size = 0x68; - sb->section2_entry_size = 0x70; + sb->section1_entry_size = 0x68; + sb->section2_entry_size = 0x70; - sb->external_flag_offset = 0x28; - sb->samples_flag_offset = 0x30; - sb->channels_offset = 0x3c; - sb->sample_rate_offset = 0x40; - sb->num_samples_offset = 0x48; - sb->num_samples_offset2 = 0x50; - sb->stream_type_offset = 0x5c; - sb->extra_name_offset = 0x58; - sb->xma_pointer_offset = 0x6c; + sb->cfg_external_flag = 0x28; + sb->cfg_samples_flag = 0x30; + sb->cfg_channels = 0x3c; + sb->cfg_sample_rate = 0x40; + sb->cfg_num_samples = 0x48; + sb->cfg_num_samples2 = 0x50; + sb->cfg_stream_type = 0x5c; + sb->cfg_extra_name = 0x58; + sb->cfg_xma_offset = 0x6c; return 1; } /* Surf's Up (2007)(PSP)-map */ if (sb->version == 0x00190005 && sb->platform == UBI_PSP) { - sb->section1_entry_size = 0x48; - sb->section2_entry_size = 0x58; + sb->section1_entry_size = 0x48; + sb->section2_entry_size = 0x58; sb->map_version = 3; - sb->external_flag_offset = 0; - sb->channels_offset = 0x28; - sb->sample_rate_offset = 0x2c; - sb->num_samples_offset = 0x34; - sb->stream_type_offset = 0x48; - sb->extra_name_offset = 0x44; + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x2c; + sb->cfg_num_samples = 0x34; + sb->cfg_stream_type = 0x48; + sb->cfg_extra_name = 0x44; sb->has_extra_name_flag = 1; + //no layers + return 1; + } + + /* Michael Jackson: The Experience (2010)(PSP)-map */ + if (sb->version == 0x001d0000 && sb->platform == UBI_PSP) { + sb->section1_entry_size = 0x40; + sb->section2_entry_size = 0x60; + + sb->map_version = 3; + + sb->cfg_external_flag = 0; + sb->cfg_channels = 0x28; + sb->cfg_sample_rate = 0x30; + sb->cfg_num_samples = 0x38; + sb->cfg_extra_name = 0x48; + sb->cfg_stream_type = 0x4c; /* 06|08 */ + + sb->has_extra_name_flag = 1; + //no layers return 1; } /* Splinter Cell Classic Trilogy HD (2011)(PS3)-map */ if (sb->version == 0x001d0000 && sb->platform == UBI_PS3) { - sb->section1_entry_size = 0x5c; - sb->section2_entry_size = 0x80; + sb->section1_entry_size = 0x5c; + sb->section2_entry_size = 0x80; sb->map_version = 3; - sb->external_flag_offset = 0x28; - sb->stream_id_offset = 0x30; - sb->samples_flag_offset = 0x34; - sb->channels_offset = 0x44; - sb->sample_rate_offset = 0x4c; - sb->num_samples_offset = 0x54; - sb->num_samples_offset2 = 0x5c; - sb->stream_type_offset = 0x68; - sb->extra_name_offset = 0x64; + sb->cfg_external_flag = 0x28; + sb->cfg_stream_id = 0x30; + sb->cfg_samples_flag = 0x34; + sb->cfg_channels = 0x44; + sb->cfg_sample_rate = 0x4c; + sb->cfg_num_samples = 0x54; + sb->cfg_num_samples2 = 0x5c; + sb->cfg_stream_type = 0x68; + sb->cfg_extra_name = 0x64; + //has layer 06 return 1; } + VGM_LOG("UBI SB: unknown SB/SM version+platform for %08x\n", sb->version); return 0; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vsv.c b/Frameworks/vgmstream/vgmstream/src/meta/vsv.c new file mode 100644 index 000000000..8240fd285 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsv.c @@ -0,0 +1,85 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "vsv_streamfile.h" + + +/* .VSV - from Square Enix games [Dawn of Mana: Seiken Densetsu 4 (PS2), Kingdom Hearts Re:Chain of Memories (PS2)] */ +VGMSTREAM * init_vgmstream_vsv(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE *temp_streamFile = NULL; + off_t start_offset; + int loop_flag, channel_count, flags, sample_rate, is_rs; + size_t loop_start, adjust, data_size, interleave; + + + /* checks */ + /* .vsv: extension from internal filenames [KH Re:CoM (PS2), DoM (PS2), KH HD I.5 + II.5 ReMIX (PS4)] + * .psh: fake */ + if (!check_extensions(streamFile, "vsv,psh")) + goto fail; + + /* 0x00(1x4): flags/config? */ + if ((uint8_t)read_8bit(0x03,streamFile) > 0x64) /* possibly volume */ + goto fail; + if ((uint8_t)read_8bit(0x0a,streamFile) != 0) /* not seen */ + goto fail; + + /* Romancing SaGa (PS2) uses an earlier? version, this seems to work */ + is_rs = ((uint16_t)read_16bitLE(0x00,streamFile) == 0); + + start_offset = 0x00; /* correct, but needs some tricks to fix sound (see below) */ + interleave = 0x800; + + adjust = (uint16_t)read_16bitLE(0x04,streamFile); + loop_start = ((uint16_t)read_16bitLE(0x06,streamFile) & 0x7FFF) * interleave; + loop_flag = (uint16_t)read_16bitLE(0x06,streamFile) & 0x8000; /* loop_start != 0 works too, no files loop from beginning to end */ + sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); + flags = (uint8_t)read_8bit (0x0b,streamFile); /* values: 0x01=stereo, 0x10=mono */ + data_size = (uint16_t)read_16bitLE(0x0c,streamFile) * interleave; + /* 0x0e: ? (may be a low-ish value) */ + + channel_count = (flags & 1) ? 2 : 1; + + /* must discard to avoid wrong loops and unwanted data (easier to see in voices) */ + if (!is_rs) { /* RS doesn't do this */ + /* adjust & 0xF800 is unknown (values=0x0000|0x0800|0xF800, can be mono/stereo, loop/no, adjust/no) */ + size_t discard = adjust & 0x07FF; + /* at (file_end - 0x800 + discard) is a 0x03 PS flag to check this (adjust 0 does discard full block) */ + data_size -= (0x800 - discard) * channel_count; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_VSV; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count); + vgmstream->loop_end_sample = vgmstream->num_samples; + + /* these loops are odd, but comparing the audio wave with the OSTs values seem correct */ + if (is_rs) { + vgmstream->loop_start_sample -= ps_bytes_to_samples(channel_count*interleave,channel_count); /* maybe *before* loop block? */ + vgmstream->loop_start_sample -= ps_bytes_to_samples(0x200*channel_count,channel_count); /* maybe default adjust? */ + } + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + temp_streamFile = setup_vsv_streamfile(streamFile, start_offset, data_size); + if (!temp_streamFile) goto fail; + + if (!vgmstream_open_stream(vgmstream, temp_streamFile, start_offset)) + goto fail; + + close_streamfile(temp_streamFile); + return vgmstream; + +fail: + close_streamfile(temp_streamFile); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h similarity index 50% rename from Frameworks/vgmstream/vgmstream/src/meta/ps2_psh_streamfile.h rename to Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h index 105ce5660..2f62fa0c0 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh_streamfile.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/vsv_streamfile.h @@ -1,31 +1,36 @@ -#ifndef _PS2_PSH_STREAMFILE_H_ -#define _PS2_PSH_STREAMFILE_H_ +#ifndef _VSV_STREAMFILE_H_ +#define _VSV_STREAMFILE_H_ #include "../streamfile.h" typedef struct { off_t null_offset; -} ps2_psh_io_data; +} vsv_io_data; -static size_t ps2_psh_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, ps2_psh_io_data* data) { +static size_t vsv_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, vsv_io_data* data) { size_t bytes_read; int i; bytes_read = streamfile->read(streamfile, dest, offset, length); - /* PSHs do start at 0x00, but first line is also the header; must null it to avoid clicks */ + /* VSVs do start at 0x00, but first line is also the header; must null it to avoid clicks */ if (offset < data->null_offset) { - for (i = 0; i < data->null_offset - offset; i++) { + int max = data->null_offset - offset; + if (max > bytes_read) + max = bytes_read; + + for (i = 0; i < max; i++) { dest[i] = 0; } } + /* VSV also has last 0x800 block with a PS-ADPCM flag of 0x10 (incorrect), but it's ignored by the decoder */ return bytes_read; } -static STREAMFILE* setup_ps2_psh_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t data_size) { +static STREAMFILE* setup_vsv_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t data_size) { STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL; - ps2_psh_io_data io_data = {0}; - size_t io_data_size = sizeof(ps2_psh_io_data); + vsv_io_data io_data = {0}; + size_t io_data_size = sizeof(vsv_io_data); io_data.null_offset = 0x10; @@ -34,7 +39,7 @@ static STREAMFILE* setup_ps2_psh_streamfile(STREAMFILE *streamFile, off_t start_ if (!new_streamFile) goto fail; temp_streamFile = new_streamFile; - new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, ps2_psh_io_read,NULL); + new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, vsv_io_read,NULL); if (!new_streamFile) goto fail; temp_streamFile = new_streamFile; @@ -45,4 +50,4 @@ fail: return NULL; } -#endif /* _PS2_PSH_STREAMFILE_H_ */ +#endif /* _VSV_STREAMFILE_H_ */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c deleted file mode 100644 index 9ef2531af..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c +++ /dev/null @@ -1,75 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* SMP (Mushroom Men: The Spore Wars ) */ -VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("smp",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x05000000) /* 0x05000000 */ - goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x28,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x1C,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x30,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitLE(0x34,streamFile)/2; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x34,streamFile)/2; - } - - /* We have no interleave, so we have no layout */ - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_WII_SMP; - - /* 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; - - } - } - - /*Retrieving the coef table... - This game has an exception, the coefs are stored in Little Endian... */ - { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitLE(0x50+i*2,streamFile); - } - } - - - 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/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c index 7a8be9c79..ebb74942e 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -409,7 +409,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { xwb.fix_xma_num_samples = 0; } } -VGM_LOG("fix: num=%i, loop=%i\n", xwb.fix_xma_num_samples,xwb.fix_xma_loop_samples); + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(xwb.channels,xwb.loop_flag); diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 0ad83efd8..8e365381b 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -114,7 +114,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_mus_acm, init_vgmstream_ps2_kces, init_vgmstream_ps2_dxh, - init_vgmstream_ps2_psh, + init_vgmstream_vsv, init_vgmstream_scd_pcm, init_vgmstream_ps2_pcm, init_vgmstream_ps2_rkv, @@ -192,7 +192,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_joe, init_vgmstream_vgs, init_vgmstream_dc_dcsw_dcs, - init_vgmstream_wii_smp, init_vgmstream_mul, init_vgmstream_thp, init_vgmstream_wii_sts, @@ -255,7 +254,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_msa, init_vgmstream_ps2_voi, init_vgmstream_ps2_khv, - init_vgmstream_pc_smp, init_vgmstream_ngc_rkv, init_vgmstream_dsp_ddsp, init_vgmstream_p3d, @@ -407,7 +405,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_msb_msh, init_vgmstream_txtp, init_vgmstream_smc_smh, - init_vgmstream_ea_sps_fb, init_vgmstream_ppst, init_vgmstream_opus_sps_n1_segmented, init_vgmstream_ubi_bao_pk, @@ -462,6 +459,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_nus3audio, init_vgmstream_imc, init_vgmstream_imc_container, + init_vgmstream_smp, /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h index 02f8020f5..6c4a2276f 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -378,7 +378,7 @@ typedef enum { meta_PS2_RSTM, /* Midnight Club 3 */ meta_PS2_KCES, /* Dance Dance Revolution */ meta_PS2_DXH, /* Tokobot Plus - Myteries of the Karakuri */ - meta_PS2_PSH, /* Square Enix PSH/VSV (Dawn of Mana/KH Re:CoM) */ + meta_VSV, meta_SCD_PCM, /* Lunar - Eternal Blue */ meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */ meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 (PS2) */ @@ -446,7 +446,7 @@ typedef enum { meta_ZWDSP, /* Zack and Wiki */ meta_VGS, /* Guitar Hero Encore - Rocks the 80s */ meta_DC_DCSW_DCS, /* Evil Twin - Cypriens Chronicles (DC) */ - meta_WII_SMP, /* Mushroom Men - The Spore Wars */ + meta_SMP, meta_WII_SNG, /* Excite Trucks */ meta_MUL, meta_SAT_BAKA, /* Crypt Killer */ @@ -538,7 +538,6 @@ typedef enum { meta_PS2_MSA, /* Psyvariar -Complete Edition- */ meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */ meta_PS2_KHV, /* Kingdom Hearts 2 VAG streams */ - meta_PC_SMP, /* Ghostbusters PC .smp */ meta_P3D, /* Prototype P3D */ meta_PS2_TK1, /* Tekken (NamCollection) */ meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */