diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index 73d091a04..d01281d9e 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj @@ -60,7 +60,7 @@ 8306B0E920984590000302D4 /* opus.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0CE2098458E000302D4 /* opus.c */; }; 8306B0EA20984590000302D4 /* caf.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0CF2098458F000302D4 /* caf.c */; }; 8306B0EB20984590000302D4 /* wave_segmented.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D02098458F000302D4 /* wave_segmented.c */; }; - 8306B0EC20984590000302D4 /* pcm_sre.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D12098458F000302D4 /* pcm_sre.c */; }; + 8306B0EC20984590000302D4 /* sre_pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D12098458F000302D4 /* sre_pcm.c */; }; 8306B0ED20984590000302D4 /* txtp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D22098458F000302D4 /* txtp.c */; }; 8306B0EE20984590000302D4 /* smh_smc.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D32098458F000302D4 /* smh_smc.c */; }; 8306B0EF20984590000302D4 /* ubi_bao.c in Sources */ = {isa = PBXBuildFile; fileRef = 8306B0D420984590000302D4 /* ubi_bao.c */; }; @@ -537,8 +537,7 @@ 836F6FB118BDC2190095E648 /* str_sqex.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7518BDC2180095E648 /* str_sqex.c */; }; 836F6FB318BDC2190095E648 /* lps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7718BDC2180095E648 /* lps.c */; }; 836F6FB418BDC2190095E648 /* nst_monster.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7818BDC2180095E648 /* nst_monster.c */; }; - 836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7918BDC2180095E648 /* ngc_pdt.c */; }; - 836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */; }; + 836F6FB518BDC2190095E648 /* pdt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7918BDC2180095E648 /* pdt.c */; }; 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7B18BDC2180095E648 /* ngc_ssm.c */; }; 836F6FBA18BDC2190095E648 /* ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ymf.c */; }; 836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; }; @@ -549,7 +548,6 @@ 836F6FC918BDC2190095E648 /* 2pfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8D18BDC2180095E648 /* 2pfs.c */; }; 836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8E18BDC2180095E648 /* ps2_adm.c */; }; 836F6FCB18BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8F18BDC2180095E648 /* ads.c */; }; - 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9118BDC2180095E648 /* ps2_ass.c */; }; 836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; }; 836F6FD118BDC2190095E648 /* bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* bg00.c */; }; 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; }; @@ -782,6 +780,7 @@ 83BB84032DF2D125002077FC /* rwar.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BB84022DF2D125002077FC /* rwar.c */; }; 83BB84062DF2D1C2002077FC /* ivb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83BB84042DF2D1C2002077FC /* ivb.c */; }; 83BB84072DF2D1C2002077FC /* ivb_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BB84052DF2D1C2002077FC /* ivb_streamfile.h */; }; + 83BDCD932E418A8F003FC007 /* awb_aac_encryption_streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BDCD922E418A8F003FC007 /* awb_aac_encryption_streamfile.h */; }; 83C0C75D2AA435C60056AFD8 /* squeak.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75C2AA435C60056AFD8 /* squeak.c */; }; 83C0C7602AA436370056AFD8 /* layout_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 83C0C75E2AA436370056AFD8 /* layout_utils.c */; }; 83C0C7612AA436370056AFD8 /* layout_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 83C0C75F2AA436370056AFD8 /* layout_utils.h */; }; @@ -1020,7 +1019,7 @@ 8306B0CE2098458E000302D4 /* opus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = opus.c; sourceTree = ""; }; 8306B0CF2098458F000302D4 /* caf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = caf.c; sourceTree = ""; }; 8306B0D02098458F000302D4 /* wave_segmented.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wave_segmented.c; sourceTree = ""; }; - 8306B0D12098458F000302D4 /* pcm_sre.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcm_sre.c; sourceTree = ""; }; + 8306B0D12098458F000302D4 /* sre_pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sre_pcm.c; sourceTree = ""; }; 8306B0D22098458F000302D4 /* txtp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = txtp.c; sourceTree = ""; }; 8306B0D32098458F000302D4 /* smh_smc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = smh_smc.c; sourceTree = ""; }; 8306B0D420984590000302D4 /* ubi_bao.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_bao.c; sourceTree = ""; }; @@ -1497,8 +1496,7 @@ 836F6E7518BDC2180095E648 /* str_sqex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_sqex.c; sourceTree = ""; }; 836F6E7718BDC2180095E648 /* lps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lps.c; sourceTree = ""; }; 836F6E7818BDC2180095E648 /* nst_monster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nst_monster.c; sourceTree = ""; }; - 836F6E7918BDC2180095E648 /* ngc_pdt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_pdt.c; sourceTree = ""; }; - 836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_sck_dsp.c; sourceTree = ""; }; + 836F6E7918BDC2180095E648 /* pdt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pdt.c; sourceTree = ""; }; 836F6E7B18BDC2180095E648 /* ngc_ssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ssm.c; sourceTree = ""; }; 836F6E7E18BDC2180095E648 /* ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ymf.c; sourceTree = ""; }; 836F6E8118BDC2180095E648 /* nwa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa.c; sourceTree = ""; }; @@ -1509,7 +1507,6 @@ 836F6E8D18BDC2180095E648 /* 2pfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 2pfs.c; sourceTree = ""; }; 836F6E8E18BDC2180095E648 /* ps2_adm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adm.c; sourceTree = ""; }; 836F6E8F18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = ""; }; - 836F6E9118BDC2180095E648 /* ps2_ass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ass.c; sourceTree = ""; }; 836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = ""; }; 836F6E9518BDC2180095E648 /* bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bg00.c; sourceTree = ""; }; 836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = ""; }; @@ -1744,6 +1741,7 @@ 83BB84022DF2D125002077FC /* rwar.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = rwar.c; sourceTree = ""; }; 83BB84042DF2D1C2002077FC /* ivb.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ivb.c; sourceTree = ""; }; 83BB84052DF2D1C2002077FC /* ivb_streamfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ivb_streamfile.h; sourceTree = ""; }; + 83BDCD922E418A8F003FC007 /* awb_aac_encryption_streamfile.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = awb_aac_encryption_streamfile.h; sourceTree = ""; }; 83C0C75C2AA435C60056AFD8 /* squeak.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = squeak.c; sourceTree = ""; }; 83C0C75E2AA436370056AFD8 /* layout_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = layout_utils.c; sourceTree = ""; }; 83C0C75F2AA436370056AFD8 /* layout_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout_utils.h; sourceTree = ""; }; @@ -2354,6 +2352,7 @@ 838A6FF02DCF0850009CBEE7 /* audiopkg_streamfile.h */, 83EED5D2203A8BC7008BEB45 /* aus.c */, 83A16D2722D2ADE700B90C4C /* awb.c */, + 83BDCD922E418A8F003FC007 /* awb_aac_encryption_streamfile.h */, 83AA5D201F6E2F9B0020821C /* awc.c */, 834F7D162C708700003AC386 /* awc_decryption_streamfile.h */, 834F7D172C708701003AC386 /* awc_streamfile.h */, @@ -2557,8 +2556,6 @@ 836F6E6D18BDC2180095E648 /* ngc_adpdtk.c */, 834F7D322C70932C003AC386 /* ngc_dsp_asura.c */, 836F6E7318BDC2180095E648 /* ngc_dsp_std.c */, - 836F6E7918BDC2180095E648 /* ngc_pdt.c */, - 836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */, 836F6E7B18BDC2180095E648 /* ngc_ssm.c */, 8306B0BE2098458C000302D4 /* ngc_str_cauldron.c */, 83C727FC22BC893900678B4A /* npsf.c */, @@ -2587,8 +2584,8 @@ 8349A8FE1FE6257F00E26435 /* pc_adp_otns.c */, 836F6E8618BDC2180095E648 /* pc_mxst.c */, 8349A8F21FE6257D00E26435 /* pcm_kceje.c */, - 8306B0D12098458F000302D4 /* pcm_sre.c */, 83D20076248DDB770048BD24 /* pcm_success.c */, + 836F6E7918BDC2180095E648 /* pdt.c */, 834FBCE926BBC7E50095647F /* piff_tpcm.c */, 836F6E8B18BDC2180095E648 /* pona.c */, 836F6E8C18BDC2180095E648 /* pos.c */, @@ -2597,7 +2594,6 @@ 8306B0C52098458D000302D4 /* ppst_streamfile.h */, 834FE0D5215C79E9000A5D3D /* ps_headerless.c */, 836F6E8E18BDC2180095E648 /* ps2_adm.c */, - 836F6E9118BDC2180095E648 /* ps2_ass.c */, 836F6E9418BDC2180095E648 /* ps2_b1s.c */, 836F6E9618BDC2180095E648 /* ps2_bmdx.c */, 836F6E9F18BDC2180095E648 /* ps2_hsf.c */, @@ -2685,6 +2681,7 @@ 837CEAF023487F2C00E62A4A /* sqex_streamfile.h */, 83C0C75C2AA435C60056AFD8 /* squeak.c */, 832F9EA52E29047F00D08728 /* srcd.c */, + 8306B0D12098458F000302D4 /* sre_pcm.c */, 834FE0D6215C79E9000A5D3D /* sscf.c */, 8396BE792935FC2F00CD0580 /* sscf_encrypted.h */, 8396BE782935FC2F00CD0580 /* sscf_encrypted.c */, @@ -3056,6 +3053,7 @@ 8306B0E820984590000302D4 /* opus_interleave_streamfile.h in Headers */, 83031EDD243C510500C3F3E0 /* xnb_streamfile.h in Headers */, 83D2007B248DDB770048BD24 /* mups_streamfile.h in Headers */, + 83BDCD932E418A8F003FC007 /* awb_aac_encryption_streamfile.h in Headers */, 834F7E912C70A1AB003AC386 /* vgmstream_init.h in Headers */, 83256CCC28666C620036D9C0 /* init_layer12.h in Headers */, 83AFABBD23795202002F3947 /* ea_eaac_opus_streamfile.h in Headers */, @@ -3301,7 +3299,6 @@ 83FF0EBC1E93282100C58054 /* wwise.c in Sources */, 836F46B42820874D005B9B87 /* adm.c in Sources */, 836F6F7018BDC2190095E648 /* apple_caff.c in Sources */, - 836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */, 837CEB072348809400E62A4A /* seb.c in Sources */, 83D26A8126E66DC2001A9475 /* log.c in Sources */, 8306B0DD20984590000302D4 /* waf.c in Sources */, @@ -3428,7 +3425,7 @@ 834F7E082C7093EA003AC386 /* vorbis_custom_utils_vid1.c in Sources */, 83F0AA5F21E2028C004BBC04 /* smp.c in Sources */, 833A7A2E1ED11961003EC53E /* xau.c in Sources */, - 836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */, + 836F6FB518BDC2190095E648 /* pdt.c in Sources */, 832BF81E21E0514B006F50F1 /* xps.c in Sources */, 837CEAFD23487F2C00E62A4A /* psf.c in Sources */, 836F6F6C18BDC2190095E648 /* ahx.c in Sources */, @@ -3634,7 +3631,6 @@ 831BA61F1EAC61A500CF89B0 /* cxs.c in Sources */, 83CBF5432D46339200AA2D75 /* skex.c in Sources */, 834F7E182C709A1D003AC386 /* ea_schl_standard.c in Sources */, - 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */, 83B73C252D8FEC3A00A57F08 /* oor_helpers.c in Sources */, 83CBF5412D4631F300AA2D75 /* i3ds.c in Sources */, 8349A90B1FE6258200E26435 /* pcm_kceje.c in Sources */, @@ -3672,7 +3668,7 @@ 8306B0AB20984552000302D4 /* layered.c in Sources */, 834F7DB62C7093EA003AC386 /* compresswave_lib.c in Sources */, 834F7E042C7093EA003AC386 /* vorbis_custom_utils_awc.c in Sources */, - 8306B0EC20984590000302D4 /* pcm_sre.c in Sources */, + 8306B0EC20984590000302D4 /* sre_pcm.c in Sources */, 832F9EA62E29047F00D08728 /* srcd.c in Sources */, 836F6FC818BDC2190095E648 /* pos.c in Sources */, 836F6F8918BDC2190095E648 /* gca.c in Sources */, diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index a1b983a52..75473319c 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/Frameworks/vgmstream/vgmstream/src/formats.c @@ -77,7 +77,6 @@ static const char* extension_list[] = { "asd", "asf", "asr", - "ass", "ast", "at3", "at9", @@ -95,6 +94,7 @@ static const char* extension_list[] = { "awb", "awc", "awd", + "awx", "b1s", //txth/reserved [7 Wonders of the Ancient World (PS2)] "baf", @@ -116,6 +116,7 @@ static const char* extension_list[] = { "binka", //FFmpeg/not parsed (BINK AUDIO) //"bin", //common "bk2", + "bkh", "bkr", //txth/reserved [P.N.03 (GC), Viewtiful Joe (GC)] "blk", "bmdx", //fake extension (to be removed?) @@ -149,11 +150,14 @@ static const char* extension_list[] = { "cnk", "cpk", "cps", + "crd", "csa", //txth/reserved [LEGO Racers 2 (PS2)] "csb", "csmp", "cvs", //txth/reserved [Aladdin in Nasira's Revenge (PS1)] "cwav", + "cxb", + "cxk", // ,acb+cpk/reserved [Dariusburst: Another Chronicle (AC)] "cxs", "d2", //txth/reserved [Dodonpachi Dai-Ou-Jou (PS2)] @@ -170,12 +174,14 @@ static const char* extension_list[] = { "dic", "diva", "dmsg", //fake extension/header id for .sgt (to be removed) + "drm", //txth/reserved [Ben 10 (HyperScan), IWL (HyperScan)] "ds2", //txth/reserved [Star Wars Bounty Hunter (GC)] "dsb", "dsf", "dsp", "dspw", "dtk", + "dty", "dvi", "dyx", //txth/reserved [Shrek 4 (iOS)] @@ -347,7 +353,7 @@ static const char* extension_list[] = { "mds", "mdsp", "med", - "mhwk", + "mhk", "mjb", "mi4", //fake extension for .mib (renamed, to be removed) "mib", @@ -356,6 +362,7 @@ static const char* extension_list[] = { "mogg", //"m4a", //common //"m4v", //common + "mon", //"mov", //common "move", //"mp+", //common [Moonshine Runners (PC)] @@ -449,6 +456,7 @@ static const char* extension_list[] = { "psf", "psh", //fake extension for .vsv (to be removed) "psn", + "pth", "pwb", "qwv", //txth/reserved [Bishi Bashi Champ Online (AC)] @@ -553,19 +561,22 @@ static const char* extension_list[] = { "snz", //txth/reserved [Killzone HD (PS3)] "sod", "son", - "spd", + "spc", + "sph", + "spt", "spm", "sps", "spsd", "spw", - "srsa", "srcd", + "sre", + "srsa", "ss2", "ssd", //txth/reserved [Zack & Wiki (Wii)] "ssf", "ssm", - "sspr", "ssp", + "sspr", "sss", "ster", "sth", @@ -686,6 +697,7 @@ static const char* extension_list[] = { "wvs", "wvx", "wxd", + "wxv", "x", "x360audio", //fake extension for Unreal Engine 3 XMA (real extension unknown) @@ -1070,7 +1082,7 @@ static const meta_info meta_info_list[] = { {meta_PWB, "Double Fine WB header"}, {meta_RAW_WAVM, "Xbox .wavm raw header"}, {meta_DSP_STR, "Cauldron .STR header"}, - {meta_EA_SCHL, "Electronic Arts SCHl header"}, + {meta_EA_SCHL, "Electronic Arts SCHl header (variable)"}, {meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"}, {meta_CAF, "tri-Crescendo CAF header"}, {meta_VPK, "SCE America VPK header"}, @@ -1151,7 +1163,6 @@ static const meta_info meta_info_list[] = { {meta_SPSD, "Sega Naomi SPSD header"}, {meta_BGW, "Square Enix BGMStream header"}, {meta_SPW, "Square Enix SeWave header"}, - {meta_PS2_ASS, "SystemSoft .ASS header"}, {meta_NUB, "Namco NUB header"}, {meta_IDSP_NL, "Next Level IDSP header"}, {meta_IDSP_IE, "Inevitable Entertainment IDSP Header"}, @@ -1198,7 +1209,6 @@ static const meta_info meta_info_list[] = { {meta_DSP_KCEJE, "Konami .DSP Header"}, {meta_VGV, "Human Head .VGV header"}, {meta_GCUB, "Sega GCub header"}, - {meta_NGC_SCK_DSP, "The Scorpion King SCK Header"}, {meta_CAFF, "Apple Core Audio Format File header"}, {meta_PC_MXST, "Lego Island MxSt Header"}, {meta_SAB, "Sensaura SAB header"}, @@ -1223,7 +1233,7 @@ static const meta_info meta_info_list[] = { {meta_SMPL, "Skonec SMPL header"}, {meta_MSA, "Success .MSA header"}, {meta_VOI, "Irem .VOI header"}, - {meta_NGC_PDT, "Hudson .PDT header"}, + {meta_PDT, "Hudson .PDT header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, {meta_DSP_DDSP, ".DDSP header"}, {meta_P3D, "Radical P3D header"}, @@ -1300,7 +1310,8 @@ static const meta_info meta_info_list[] = { {meta_XA_XA30, "Reflections XA30 header"}, {meta_XA_04SW, "Reflections 04SW header"}, {meta_TXTH, "TXTH generic header"}, - {meta_EA_BNK, "Electronic Arts BNK header"}, + {meta_EA_BNK, "Electronic Arts BNK header (variable)"}, + {meta_EA_BNK_fixed, "Electronic Arts BNK header (fixed)"}, {meta_SK_AUD, "Silicon Knights AUD header"}, {meta_AHX, "CRI AHX header"}, {meta_STMA, "Angel Studios/Rockstar San Diego STMA header"}, @@ -1336,7 +1347,7 @@ static const meta_info meta_info_list[] = { {meta_EA_WVE_AD10, "Electronic Arts WVE (Ad10) header"}, {meta_STHD, "Dream Factory STHD header"}, {meta_MP4, "MP4/AAC header"}, - {meta_PCM_SRE, "Capcom .PCM+SRE header"}, + {meta_SRE_PCM, "Capcom .SRE+PCM header"}, {meta_DSP_MCADPCM, "Bethesda .mcadpcm header"}, {meta_UBI_LYN, "Ubisoft LyN RIFF header"}, {meta_MSB_MSH, "Sony MultiStream MSH+MSB header"}, diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acb.c b/Frameworks/vgmstream/vgmstream/src/meta/acb.c index bc2c52767..5a51fa511 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/acb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/acb.c @@ -14,13 +14,15 @@ VGMSTREAM* init_vgmstream_acb(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "@UTF")) - goto fail; + return NULL; /* mainly for bigger files (utf lib checks smaller) */ if (read_u32be(0x04,sf) + 0x08 != get_streamfile_size(sf)) - goto fail; + return NULL; - if (!check_extensions(sf, "acb")) - goto fail; + /* .acb: standard + * .acx: Dariusburst - Chronicle Saviors (multi) */ + if (!check_extensions(sf, "acb,acx")) + return NULL; /* .acb is a cue sheet that uses @UTF (CRI's generic table format) to store row/columns * with complex info (cues, sequences, spatial info, etc). It can store a memory .awb @@ -53,8 +55,16 @@ VGMSTREAM* init_vgmstream_acb(STREAMFILE* sf) { //;VGM_LOG("acb: subfile offset=%x + %x\n", subfile_offset, subfile_size); - temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "awb"); - if (!temp_sf) goto fail; + // .acb+awb (most common) + if (!temp_sf) + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "awb"); + + // .acx+awx [Dariusburst: Chronicle Saviors (multi)] + if (!temp_sf && check_extensions(sf, "acx")) + temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "awx"); + + if (!temp_sf) + goto fail; if (is_id32be(0x00, temp_sf, "CPK ")) { vgmstream = init_vgmstream_cpk_memory(temp_sf, sf); /* older */ @@ -1209,19 +1219,17 @@ fail: */ void load_acb_wave_info(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int port, int is_memory, int load_loops) { - acb_header acb = {0}; - int i; - if (!sf || !vgmstream || waveid < 0) return; //;VGM_LOG("acb: find waveid=%i, port=%i\n", waveid, port); + acb_header acb = {0}; acb.acbFile = sf; acb.Header = utf_open(acb.acbFile, 0x00, NULL, NULL); - if (!acb.Header) goto fail; + if (!acb.Header) return; acb.target_waveid = waveid; acb.target_port = port; @@ -1230,7 +1238,7 @@ void load_acb_wave_info(STREAMFILE* sf, VGMSTREAM* vgmstream, int waveid, int po /* read all possible cue names and find which waveids are referenced by it */ preload_acb_cuename(&acb); - for (i = 0; i < acb.CueName_rows; i++) { + for (int i = 0; i < acb.CueName_rows; i++) { if (!load_acb_cuename(&acb, i)) goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awb.c b/Frameworks/vgmstream/vgmstream/src/meta/awb.c index 47641ee0c..f16cd1bd4 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/awb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/awb.c @@ -1,10 +1,20 @@ #include "meta.h" +#include "awb_aac_encryption_streamfile.h" #include "../coding/coding.h" #include "../util/companion_files.h" +#include "../util/cri_keys.h" -//typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type_t; +typedef struct { + VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf); + VGMSTREAM* (*init_vgmstream_subkey)(STREAMFILE* sf, uint16_t subkey); + const char* extension; + bool load_loops; + bool use_riff_size; +} meta_info_t; -static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid, int load_loops); +static bool load_meta_type(meta_info_t* meta, STREAMFILE* sf, uint32_t subfile_offset); +static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid, bool load_loops); +static uint64_t load_keycode(STREAMFILE* sf); /* AFS2/AWB (Atom Wave Bank) - CRI container of streaming audio, often together with a .acb cue sheet */ VGMSTREAM* init_vgmstream_awb(STREAMFILE* sf) { @@ -19,20 +29,21 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) { uint8_t offset_size; uint16_t waveid_alignment, offset_alignment, subkey; int waveid; - int load_loops = 0; + bool load_loops = 0; /* checks */ if (!is_id32be(0x00,sf, "AFS2")) - goto fail; + return NULL; /* .awb: standard - * .afs2: sometimes [Okami HD (PS4)] */ - if (!check_extensions(sf, "awb,afs2")) - goto fail; + * .afs2: sometimes [Okami HD (PS4)] + * .awx: Dariusburst - Chronicle Saviors (multi) */ + if (!check_extensions(sf, "awb,afs2,awx")) + return NULL; - /* 0x04(1): version? 0x01=common, 0x02=2018+ (no apparent differences) */ + // 0x04(1): version? 0x01=common, 0x02=2018+ (no apparent differences) offset_size = read_u8 (0x05,sf); - waveid_alignment = read_u16le(0x06,sf); /* usually 0x02, rarely 0x04 [Voice of Cards: The Beasts of Burden (Switch)]*/ + waveid_alignment = read_u16le(0x06,sf); // usually 0x02, rarely 0x04 [Voice of Cards: The Beasts of Burden (Switch)] total_subsongs = read_s32le(0x08,sf); offset_alignment = read_u16le(0x0c,sf); subkey = read_u16le(0x0e,sf); @@ -69,7 +80,7 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) { break; default: vgm_logi("AWB: unknown offset size (report)\n"); - goto fail; + return NULL; } /* offset are absolute but sometimes misaligned (specially first that just points to offset table end) */ @@ -82,76 +93,49 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) { //;VGM_LOG("awb: subfile offset=%x + %x\n", subfile_offset, subfile_size); - /* autodetect as there isn't anything, plus can mix types - * (waveid<>codec info is usually in the companion .acb) */ + /* handle subfile */ { - VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL; - VGMSTREAM* (*init_vgmstream_subkey)(STREAMFILE* sf, uint16_t subkey) = NULL; - const char* extension = NULL; + meta_info_t meta = {0}; - if (read_u16be(subfile_offset, sf) == 0x8000) { /* (type 0=ADX, also 3?) */ - init_vgmstream_subkey = init_vgmstream_adx_subkey; /* Okami HD (PS4) */ - extension = "adx"; + bool meta_ok = load_meta_type(&meta, sf, subfile_offset); + if (!meta_ok) { + // try encrypted meta (loads key after reguylar cases since it's uncommon) + uint64_t keycode = load_keycode(sf); + if (keycode) { + meta.init_vgmstream = init_vgmstream_mp4_aac_ffmpeg; // Final Fantasy Digital Card Game (Browser) + meta.extension = "m4a"; // TODO improve detection (only known to be used for .m4a) + meta_ok = true; + + temp_sf = setup_awb_aac_encryption_streamfile(sf, subfile_offset, subfile_size, meta.extension, keycode); + if (!temp_sf) goto fail; + } } - else if ((read_u32be(subfile_offset,sf) & 0x7f7f7f7f) == get_id32be("HCA\0")) { /* (type 2=HCA, 6=HCA-MX) */ - init_vgmstream_subkey = init_vgmstream_hca_subkey; /* most common */ - extension = "hca"; - } - else if (is_id32be(subfile_offset,sf, "VAGp")) { /* (type 7=VAG, 10=HEVAG) */ - init_vgmstream = init_vgmstream_vag; /* Ukiyo no Roushi (Vita) */ - extension = "vag"; - } - else if (is_id32be(subfile_offset,sf, "RIFF")) { /* (type 8=ATRAC3, 11=ATRAC9, also 18=ATRAC9?) */ - init_vgmstream = init_vgmstream_riff; /* Ukiyo no Roushi (Vita) */ - extension = "wav"; - subfile_size = read_u32le(subfile_offset + 0x04,sf) + 0x08; /* padded size, use RIFF's */ - } - else if (is_id32be(subfile_offset,sf, "CWAV")) { /* (type 9=CWAV) */ - init_vgmstream = init_vgmstream_bcwav; /* Sonic: Lost World (3DS) */ - extension = "bcwav"; - } - else if (read_u32be(subfile_offset + 0x08,sf) >= 8000 && read_u32be(subfile_offset + 0x08,sf) <= 48000 && - read_u16be(subfile_offset + 0x0e,sf) == 0 && - read_u32be(subfile_offset + 0x18,sf) == 2 && - read_u32be(subfile_offset + 0x50,sf) == 0) { /* (type 13=DSP, also 4=Wii?, 5=NDS?), probably should call some check function */ - init_vgmstream = init_vgmstream_ngc_dsp_std; /* Sonic: Lost World (WiiU) */ - extension = "dsp"; - } - else if (is_id32be(subfile_offset,sf, "CWAC")) { /* (type 13=DSP, again) */ - init_vgmstream = init_vgmstream_dsp_cwac; /* Mario & Sonic at the Rio 2016 Olympic Games (WiiU) */ - extension = "dsp"; - } -#ifdef VGM_USE_FFMPEG - else if (read_u32be(subfile_offset+0x00,sf) == 0x00000018 && is_id32be(subfile_offset+0x04,sf, "ftyp")) { /* (type 19=M4A) */ - init_vgmstream = init_vgmstream_mp4_aac_ffmpeg; /* Imperial SaGa Eclipse (Browser) */ - extension = "m4a"; - } -#endif - else if (read_u32be(subfile_offset + 0x00,sf) == 0x01000080) { /* (type 24=NXOpus) */ - init_vgmstream =init_vgmstream_opus_std; /* Super Mario RPG (Switch) */ - extension = "opus"; - load_loops = 1; /* loops not in Opus (rare) but in .acb */ - } - else { /* 12=XMA? */ + + if (!meta_ok) { vgm_logi("AWB: unknown codec (report)\n"); goto fail; } + if (meta.use_riff_size) { + subfile_size = read_u32le(subfile_offset + 0x04,sf) + 0x08; + } - temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, extension); - if (!temp_sf) goto fail; + if (!temp_sf) { + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, meta.extension); + if (!temp_sf) goto fail; + } - if (init_vgmstream_subkey) - vgmstream = init_vgmstream_subkey(temp_sf, subkey); + if (meta.init_vgmstream_subkey) + vgmstream = meta.init_vgmstream_subkey(temp_sf, subkey); else - vgmstream = init_vgmstream(temp_sf); + vgmstream = meta.init_vgmstream(temp_sf); if (!vgmstream) goto fail; vgmstream->num_streams = total_subsongs; } /* try to load cue names+etc */ - load_acb_info(sf, sf_acb, vgmstream, waveid, load_loops); + load_acb_info(sf, sf_acb, vgmstream, waveid, load_loops); close_streamfile(temp_sf); return vgmstream; @@ -163,8 +147,117 @@ fail: } -static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid, int load_loops) { - int is_memory = (sf_acb != NULL); +/* autodetect as waveid<>codec is found in .acb (values/extension from CriAtomCraft decompilations) + * 00: ADX (.adx) [Gunhound EX (PSP), Persona 5 (PS3), Shin Megami Tensei V: Vengeance (PS4)] + * 01: PCM? (.swlpcm?) + * 02: HCA-MX? (.hca) [common] + * 03: alt ADX? + * 04: Wii DSP? (.wiiadpcm?) + * 05: NDS DSP? (.dsadpcm) + * 06: HCA-MX (.hcamx) [common] + * 07: VAG (.vag) [Ukiyo no Roushi (Vita)] + * 08: ATRAC3 (.at3) [Ukiyo no Shishi (PS3)] + * 09: CWAV (.3dsadpcm) [Sonic: Lost World (3DS)] + * 10: HEVAG (.vag) [Ukiyo no Roushi (Vita)] + * 11: ATRAC9 (.at9) [Ukiyo no Roushi (Vita)] + * 12: X360 XMA? (.xma2?) + * 13: DSP (.wiiuadpcm?) [Sonic: Lost World (WiiU)] + * 13: CWAC DSP (.wiiuadpcm?) [Mario & Sonic at the Rio 2016 Olympic Games (WiiU)] + * 14: PS4 HEVAG? + * 18: PS4 ATRAC9 (.at9) [13 Sentinels (PS4)] + * 19: AAC M4A (.m4a) [Imperial SaGa Eclipse (Browser)] + * 24: Switch Opus (.switchopus) [Super Mario RPG (Switch)] + */ +static bool load_meta_type(meta_info_t* meta, STREAMFILE* sf, uint32_t subfile_offset) { + + if (read_u16be(subfile_offset, sf) == 0x8000) { + meta->init_vgmstream_subkey = init_vgmstream_adx_subkey; + meta->extension = "adx"; + return true; + } + + if ((read_u32be(subfile_offset,sf) & 0x7f7f7f7f) == get_id32be("HCA\0")) { + meta->init_vgmstream_subkey = init_vgmstream_hca_subkey; + meta->extension = "hca"; + return true; + } + + if (is_id32be(subfile_offset,sf, "VAGp")) { + meta->init_vgmstream = init_vgmstream_vag; + meta->extension = "vag"; + return true; + } + + if (is_id32be(subfile_offset,sf, "RIFF")) { + meta->init_vgmstream = init_vgmstream_riff; + meta->extension = "wav"; + meta->use_riff_size = true; // padded size, use RIFF's + return true; + } + + if (is_id32be(subfile_offset,sf, "CWAV")) { + meta->init_vgmstream = init_vgmstream_bcwav; + meta->extension = "bcwav"; + return true; + } + + // TODO: call some check function? + if (read_u32be(subfile_offset + 0x08,sf) >= 8000 + && read_u32be(subfile_offset + 0x08,sf) <= 48000 + && read_u16be(subfile_offset + 0x0e,sf) == 0 + && read_u32be(subfile_offset + 0x18,sf) == 2 + && read_u32be(subfile_offset + 0x50,sf) == 0) { + meta->init_vgmstream = init_vgmstream_ngc_dsp_std; + meta->extension = "dsp"; + return true; + } + + if (is_id32be(subfile_offset,sf, "CWAC")) { + meta->init_vgmstream = init_vgmstream_dsp_cwac; + meta->extension = "dsp"; + return true; + } + +#ifdef VGM_USE_FFMPEG + if (read_u32be(subfile_offset + 0x00,sf) == 0x00000018 + && is_id32be(subfile_offset + 0x04,sf, "ftyp")) { + meta->init_vgmstream = init_vgmstream_mp4_aac_ffmpeg; + meta->extension = "m4a"; + return true; + } +#endif + + if (read_u32be(subfile_offset + 0x00,sf) == 0x01000080) { + meta->init_vgmstream = init_vgmstream_opus_std; + meta->extension = "opus"; + meta->load_loops = true; // loops not in Opus but in .acb (rare) + return true; + } + + return false; +} + +// TODO unify, from HCA +static uint64_t load_keycode(STREAMFILE* sf) { + // fully encrypted data, try to read keyfile (rare) + uint8_t keybuf[20+1] = {0}; /* max keystring 20, +1 extra null */ + uint32_t key_size = read_key_file(keybuf, sizeof(keybuf) - 1, sf); + + uint64_t keycode = 0; + bool is_keystring = cri_key9_valid_keystring(keybuf, key_size); + if (is_keystring) { /* number */ + const char* keystring = (const char*)keybuf; + keycode = strtoull(keystring, NULL, 10); + } + else if (key_size == 0x08) { /* hex */ + keycode = get_u64be(keybuf+0x00); + } + + return keycode; +} + +static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid, bool load_loops) { + bool is_memory = (sf_acb != NULL); int port = 0; /* .acb is passed when loading memory .awb inside .acb */ @@ -176,13 +269,18 @@ static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre /* try parsing TXTM if present */ sf_acb = read_filemap_file_pos(sf, 0, &port); - /* try (name).awb + (name).acb */ + /* try (name).awb + (name).acb (most common) */ if (!sf_acb) { sf_acb = open_streamfile_by_ext(sf, "acb"); } - /* try (name)_streamfiles.awb + (name).acb */ - if (!sf_acb) { + /* try (name).awx + (name).acx, exclusive to Dariusburst console games. */ + if (!sf_acb && check_extensions(sf, "awx")) { + sf_acb = open_streamfile_by_ext(sf, "acx"); + } + + /* try (name)_streamfiles.awb + (name).acb (sometimes) */ + if (!sf_acb && check_extensions(sf, "awb")) { char *cmp = "_streamfiles"; get_streamfile_basename(sf, filename, sizeof(filename)); len_name = strlen(filename); @@ -196,7 +294,7 @@ static void load_acb_info(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstre } /* try (name)_STR.awb + (name).acb */ - if (!sf_acb) { + if (!sf_acb && check_extensions(sf, "awb")) { char *cmp = "_STR"; get_streamfile_basename(sf, filename, sizeof(filename)); len_name = strlen(filename); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awb_aac_encryption_streamfile.h b/Frameworks/vgmstream/vgmstream/src/meta/awb_aac_encryption_streamfile.h new file mode 100644 index 000000000..8b92ff1d9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/awb_aac_encryption_streamfile.h @@ -0,0 +1,132 @@ +#ifndef _AWB_AAC_ENCRYPTION_STREAMFILE_H_ +#define _AWB_AAC_ENCRYPTION_STREAMFILE_H_ +#include "../streamfile.h" + + +typedef struct { + uint16_t key[4]; + + uint16_t xor; + uint16_t add; + uint16_t mul; + + uint32_t curr_offset; +} cri_aac_io_data; + + +// see criAacCodec_SetDecryptionKey +static void setup_key(uint64_t keycode, cri_aac_io_data* cridata) { + if (!keycode) + return; + uint16_t k0 = 4 * ((keycode >> 0) & 0x0FFF) | 1; + uint16_t k1 = 2 * ((keycode >> 12) & 0x1FFF) | 1; + uint16_t k2 = 4 * ((keycode >> 25) & 0x1FFF) | 1; + uint16_t k3 = 2 * ((keycode >> 38) & 0x3FFF) | 1; + + cridata->key[0] = k0 ^ k1; + cridata->key[1] = k1 ^ k2; + cridata->key[2] = k2 ^ k3; + cridata->key[3] = ~k3; + + // criatomexacb_generate_aac_decryption_key is slightly different, unsure if used: + //keydata->key[0] = k0 ^ k3; + //keydata->key[1] = k2 ^ k3; + //keydata->key[2] = k2 ^ k3; + //keydata->key[3] = ~k3; +} + +// see criAacCodec_DecryptData +static void decrypt_chunk(cri_aac_io_data* data, uint8_t* dst, uint32_t dst_size) { + uint16_t seed0 = ~data->key[3]; + uint16_t seed1 = seed0 ^ data->key[2]; + uint16_t seed2 = seed1 ^ data->key[1]; + uint16_t seed3 = seed2 ^ data->key[0]; + + uint16_t xor = data->xor; + uint16_t add = data->add; + uint16_t mul = data->mul; + + // use as special flag (original code decrypts whole files so values are always reset) + if (dst == NULL && dst_size == 0) { + xor = 2 * seed0 | 1; + add = 2 * seed0 | 1; // not seed1 + mul = 4 * seed2 | 1; + } + + for (int i = 0; i < dst_size; i++) { + + int curr_i = data->curr_offset + i; + if (!(uint16_t)curr_i) { // every 0x10000, without modulo + mul = ((4 * seed2 + seed3 * (mul & 0xFFFC)) & 0xFFFD) | 1; + add = (2 * seed0 + seed1 * (add & 0xFFFE)) | 1; + } + xor = xor * mul + add; + + if (dst != NULL) { + dst[i] ^= (xor >> 8) & 0xFF; + } + } + + data->xor = xor; + data->add = add; + data->mul = mul; + + data->curr_offset += dst_size; +} + +static void reset_keydata(cri_aac_io_data* data) { + decrypt_chunk(data, NULL, 0); +} + +static void update_key(cri_aac_io_data* data, STREAMFILE* sf, off_t offset) { + size_t to_skip; + + if (offset < data->curr_offset || offset == 0x00) { + reset_keydata(data); + data->curr_offset = 0x00; + to_skip = offset; + } + else { + to_skip = offset - data->curr_offset; + } + + if (to_skip == 0) + return; + + // update key by reading and decrypt all data between current offset + last known key to requested offset + decrypt_chunk(data, NULL, to_skip); +} + +/* XOR depends on decrypted data, meanings having to decrypt linearly to reach some offset. */ +static size_t cri_aac_io_read(STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length, cri_aac_io_data* data) { + size_t bytes; + + // fix key to current offset + update_key(data, sf, offset); + + // read and decrypt current data + bytes = read_streamfile(dest, offset, length, sf); + decrypt_chunk(data, dest, bytes); + + return bytes; +} + +/* decrypts CRI's AAC encryption, from decompilation [Final Fantasy Digital Card Game (Browser)] */ +static STREAMFILE* setup_awb_aac_encryption_streamfile(STREAMFILE* sf, uint32_t subfile_offset, uint32_t subfile_size, const char* extension, uint64_t keycode) { + STREAMFILE* new_sf = NULL; + cri_aac_io_data io_data = {0}; + + setup_key(keycode, &io_data); + reset_keydata(&io_data); + io_data.curr_offset = 0x00; + + new_sf = open_wrap_streamfile(sf); + new_sf = open_clamp_streamfile_f(new_sf, subfile_offset, subfile_size); + new_sf = open_io_streamfile_f(new_sf, &io_data, sizeof(cri_aac_io_data), cri_aac_io_read, NULL); + if (extension) { + new_sf = open_fakename_streamfile_f(new_sf, NULL, extension); + } + return new_sf; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/csb.c b/Frameworks/vgmstream/vgmstream/src/meta/csb.c index 75f79408c..02c9cbede 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/csb.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/csb.c @@ -18,7 +18,9 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "@UTF")) goto fail; - if (!check_extensions(sf, "csb")) + /* .csb: standard + * .cxb: Dariusburst - Another Chronicle (AC) */ + if (!check_extensions(sf, "csb,cxb")) goto fail; /* .csb is an early, simpler version of .acb+awk (see acb.c) used until ~2013? diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c index d3714f9c2..0002cdf18 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_1snh.c @@ -53,7 +53,7 @@ VGMSTREAM* init_vgmstream_ea_1snh(STREAMFILE* sf) { if (!is_id32be(offset + 0x00, sf, "1SNh") && !is_id32be(offset + 0x00, sf, "SEAD")) - goto fail; + return NULL; /* .asf/as4: common, * .lasf: fake for plugins @@ -63,7 +63,7 @@ VGMSTREAM* init_vgmstream_ea_1snh(STREAMFILE* sf) { * .tgv: videos * (extensionless): Need for Speed (SAT) videos */ if (!check_extensions(sf, "asf,lasf,sng,as4,cnk,uv,tgq,tgv,")) - goto fail; + return NULL; /* stream is divided into blocks/chunks: 1SNh=audio header, 1SNd=data xN, 1SNl=loop end, 1SNe=end. * Video uses various blocks (TGVk/TGVf/MUVf/etc) and sometimes alt audio blocks (SEAD/SNDC/SEND). */ @@ -105,13 +105,15 @@ VGMSTREAM* init_vgmstream_ea_eacs(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "EACS") && read_u32be(0x00,sf) != 0 && !is_id32be(0x228,sf, "EACS")) - goto fail; + return NULL; /* .eas: single bank [Need for Speed (PC)] * .bnk: multi bank [Need for Speed (PC)] - * .as4: single [NBA Live 96 (PC)] */ - if (!check_extensions(sf,"eas,bnk,as4")) - goto fail; + * .as4/sph: single [NBA Live 96 (PC)] + * .dty/mon: single [NBA Live 95 (PC)] + * .spc: single [FIFA Soccer 96 (PC)] */ + if (!check_extensions(sf,"eas,bnk,as4,sph,dty,mon,spc")) + return NULL; /* plain data without blocks, can contain N*(EACS header) + N*(data), or N (EACS header + data) */ ea.is_bank = 1; @@ -128,7 +130,7 @@ VGMSTREAM* init_vgmstream_ea_eacs(STREAMFILE* sf) { if (target_subsong == 0) target_subsong = 1; if (target_subsong < 0) goto fail; - /* offsets to EACSs are scattered in the first 0x200, then 0x28 info + EACS per subsong. + /* offsets to EACSs are scattered in the first 0x200, then 0x28 info + EACS per subsong. * This looks dumb but seems like the only way. */ eacs_offset = 0; for (i = 0x00; i < 0x200; i += 0x04) { @@ -163,6 +165,72 @@ fail: return NULL; } +/* EA CRDF - crowd banks (later games use CRDl without audio) */ +VGMSTREAM* init_vgmstream_ea_crdf(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + eacs_header ea = {0}; + off_t eacs_offset; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00, sf, "CRDF")) + return NULL; + + /* .crd: NBA Live 95/96 (PC), FIFA Soccer 96 (PC) */ + if (!check_extensions(sf, "crd")) + return NULL; + + + /* filter out some weird variation [NBA Live 96 (PS1)] */ + if (read_u32le(0x04, sf) != 0x02) goto fail; + + ea.is_bank = 1; + + if (target_subsong == 0) target_subsong = 1; + + // TODO: possibly unreliable variant checks + if (read_u32be(0x10, sf) == 0x02 && read_u32be(0x14, sf) == 0x04) { + /* Early variant, header size 0x344 [NBA 95 (PC)] */ + + total_subsongs = read_u32le(0x18, sf); + /* game does (0xC4 + 0x28) + i * (0x1C * 4) */ + eacs_offset = 0xEC + (target_subsong - 1) * 0x70; + } + else if (read_u32le(0x10, sf) + read_u32le(0x14, sf) == 0x10000) { + /* Later variant, header size 0x38C [NBA 96 (PC), FIFA 96 (PC)] */ + + total_subsongs = read_u32le(0x24, sf); + /* game does (0x7C + 0x28) + i * (0x1D * 4) */ + eacs_offset = 0xA4 + (target_subsong - 1) * 0x74; + } + else { + VGM_LOG("EA EACS: unknown CRDF variant\n"); + goto fail; + } + + /* actual check done by the games, seemingly always 4 + * entries with the latter ones dummy if less tracks */ + //if (total_subsongs > 4) total_subsongs = 4; + + if (total_subsongs < 1 || target_subsong > total_subsongs) + goto fail; + + + if (!parse_header(sf, &ea, eacs_offset)) + goto fail; + + vgmstream = init_vgmstream_main(sf, &ea); + if (!vgmstream) goto fail; + vgmstream->num_streams = total_subsongs; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + static VGMSTREAM* init_vgmstream_main(STREAMFILE* sf, eacs_header* ea) { VGMSTREAM* vgmstream = NULL; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c index f1ff960ec..e0e267e15 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl.c @@ -39,7 +39,7 @@ /* CODEC1 values were used early, then they migrated to CODEC2 values */ #define EA_CODEC1_NONE -1 #define EA_CODEC1_PCM 0x00 -//#define EA_CODEC1_IMA 0x02 /* not used (sx.exe internal defs) */ +#define EA_CODEC1_IMA 0x02 /* very rare [NBA Live 97 (PC)] */ #define EA_CODEC1_N64 0x05 #define EA_CODEC1_VAG 0x06 #define EA_CODEC1_EAXA 0x07 @@ -59,7 +59,7 @@ #define EA_CODEC2_EAXA 0x0A //#define EA_CODEC2_U8_INT 0x0B /* not used (sx.exe internal defs) */ //#define EA_CODEC2_CDXA 0x0C /* not used (sx.exe internal defs) */ -//#define EA_CODEC2_IMA_INT 0x0D /* not used (sx.exe internal defs) */ +#define EA_CODEC2_IMA_INT 0x0D //#define EA_CODEC2_LAYER1 0x0E /* not used (sx.exe internal defs) */ #define EA_CODEC2_LAYER2 0x0F #define EA_CODEC2_LAYER3 0x10 /* not seen so far but may be used somewhere */ @@ -142,6 +142,7 @@ static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* sf, off_t start_offset, static VGMSTREAM* init_vgmstream_ea_variable_header(STREAMFILE* sf, ea_header* ea, off_t start_offset, int is_bnk); static void update_ea_stream_size(STREAMFILE* sf, off_t start_offset, VGMSTREAM* vgmstream); + VGMSTREAM* load_vgmstream_ea_schl(STREAMFILE* sf, off_t offset) { return parse_schl_block(sf, offset); } @@ -150,6 +151,14 @@ VGMSTREAM* load_vgmstream_ea_bnk(STREAMFILE* sf, off_t offset, int target_stream return parse_bnk_header(sf, offset, target_stream, is_embedded); } +/* load standalone variable header */ +VGMSTREAM* load_vgmstream_ea_pt(STREAMFILE* sf_head, STREAMFILE* sf_body, off_t head_offset, size_t head_size, off_t body_offset) { + ea_header ea = {0}; + if (!parse_variable_header(sf_head, &ea, head_offset, head_size, 1)) + return NULL; + return init_vgmstream_ea_variable_header(sf_body, &ea, body_offset, 1); +} + /* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */ static VGMSTREAM* parse_schl_block(STREAMFILE* sf, off_t offset) { off_t start_offset, header_offset; @@ -325,6 +334,10 @@ static VGMSTREAM* init_vgmstream_ea_variable_header(STREAMFILE* sf, ea_header* e } break; + case EA_CODEC2_IMA_INT: /* DVI IMA */ + vgmstream->coding_type = coding_DVI_IMA; + break; + case EA_CODEC2_S8_INT: /* PCM8 (interleaved) */ vgmstream->coding_type = coding_PCM8_int; break; @@ -518,6 +531,15 @@ static VGMSTREAM* init_vgmstream_ea_variable_header(STREAMFILE* sf, ea_header* e } break; } + case coding_DVI_IMA: + /* 0x00 default all? very rarely used, only found in standalone PTH/PTD + * during the transition period from fixed to variable header format */ + //if (start_offset != ea->offsets[0]) goto fail; + for (i = 0; i < vgmstream->channels; i++) { + vgmstream->ch[i].offset = ea->offsets[0]; + } + break; + default: VGM_LOG("EA SCHl: Unknown channel offsets for codec 0x%02x in version %d\n", ea->codec1, ea->version); goto fail; @@ -867,6 +889,7 @@ static int parse_variable_header(STREAMFILE* sf, ea_header* ea, off_t begin_offs else ea->codec2 = ea->bps == 8 ? EA_CODEC2_S8 : (ea->big_endian ? EA_CODEC2_S16BE : EA_CODEC2_S16LE); break; + case EA_CODEC1_IMA: ea->codec2 = EA_CODEC2_IMA_INT; break; case EA_CODEC1_N64: ea->codec2 = EA_CODEC2_N64; break; case EA_CODEC1_VAG: ea->codec2 = EA_CODEC2_VAG; break; case EA_CODEC1_EAXA: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c index e75ae9aa6..76809a19b 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_fixed.c @@ -2,7 +2,7 @@ #include "../layout/layout.h" #include "../coding/coding.h" -/* Possibly the same as EA_CODEC_x in variable SCHl */ +/* Possibly the same as EA_CODEC1_x in variable SCHl */ #define EA_CODEC_PCM 0x00 #define EA_CODEC_IMA 0x02 #define EA_CODEC_PSX 0x06 @@ -17,57 +17,188 @@ typedef struct { int big_endian; int loop_flag; + int is_bank; + + off_t start_offset; + //size_t stream_size; + off_t loop_start; + off_t loop_end; } ea_fixed_header; -static int parse_fixed_header(STREAMFILE* sf, ea_fixed_header* ea); +static VGMSTREAM* init_vgmstream_ea_fixed_header(STREAMFILE* sf, ea_fixed_header* ea); +static int parse_fixed_header(STREAMFILE* sf, ea_fixed_header* ea, off_t offset); /* EA SCHl with fixed header - from EA games (~1997?) */ VGMSTREAM* init_vgmstream_ea_schl_fixed(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - off_t start_offset; - size_t header_size; ea_fixed_header ea = {0}; + size_t header_size; + off_t offset; /* checks */ - if (!is_id32be(0x00,sf, "SCHl")) + if (!is_id32be(0x00, sf, "SCHl")) return NULL; /* .asf: original [NHK 97 (PC)] * .lasf: fake for plugins - * .cnk: ps1 [NBA Live 97 (PS1)] */ - if (!check_extensions(sf,"asf,lasf,cnk")) + * .cnk/dct: ps1 [NBA Live 97 (PS1)] */ + if (!check_extensions(sf, "asf,lasf,cnk,dct")) return NULL; /* see ea_schl.c for more info about blocks */ //TODO: handle SCCl? [NBA Live 97 (PS1)] - header_size = read_u32le(0x04,sf); + header_size = read_u32le(0x04, sf); - if (!parse_fixed_header(sf, &ea)) + offset = is_id32be(0x0c, sf, "PATl") ? 0x0c : 0x08; /* extra field in PS1 */ + + if (!parse_fixed_header(sf, &ea, offset)) + return NULL; + + ea.start_offset = header_size; /* has garbage data in PATl */ + return init_vgmstream_ea_fixed_header(sf, &ea); +} + + +/* EA BNKl with fixed header - from EA games (~1997?) */ +VGMSTREAM* init_vgmstream_ea_bnk_fixed(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sf_body = NULL; + ea_fixed_header ea = {0}; + int bnk_version, num_sounds; + int total_subsongs = 0, target_subsong = sf->stream_index; + off_t offset; + + + /* checks */ + if (!is_id32be(0x00, sf, "BNKl")) + return NULL; + + /* .bkh: FIFA 97 (PC) + * .vh: NBA Live 97 (PS1) */ + if (check_extensions(sf, "bkh")) { + sf_body = open_streamfile_by_ext(sf, "bkd"); + if (!sf_body) goto fail; + } + else if (check_extensions(sf, "vh")) { + sf_body = open_streamfile_by_ext(sf, "vb"); + if (!sf_body) goto fail; + } + else + return NULL; + + + ea.is_bank = 1; + + bnk_version = read_u16le(0x04, sf); + num_sounds = read_u16le(0x06, sf); + + /* (intentionally?) blanked fields [Triple Play 97 (PC)] */ + if (!bnk_version && !num_sounds) { + bnk_version = 0x01; + num_sounds = 0x80; + } + + /* bnk v2+ is only in standard (variable header) ea_schl */ + if (bnk_version != 0x01) goto fail; + /* always a 0x200 sized buffer w/ dummy nullptr entries */ + if (num_sounds != 0x80) goto fail; + + if (target_subsong == 0) target_subsong = 1; + + for (int i = 0; i < num_sounds; i++) { + offset = read_u32le(0x08 + (i * 0x04), sf); + if (!offset) continue; + total_subsongs++; + + if (total_subsongs == target_subsong) { + offset += 0x08 + (i * 0x04); /* pointer base is ptr pos */ + if (!parse_fixed_header(sf, &ea, offset)) + goto fail; + } + } + + if (total_subsongs < 1 || target_subsong > total_subsongs) goto fail; - start_offset = header_size; + vgmstream = init_vgmstream_ea_fixed_header(sf_body, &ea); + if (!vgmstream) goto fail; + vgmstream->num_streams = total_subsongs; + + + close_streamfile(sf_body); + return vgmstream; + +fail: + close_streamfile(sf_body); + close_vgmstream(vgmstream); + return NULL; +} + + +/* EA standalone PATl fixed header - from EA games (~1997?) */ +VGMSTREAM* init_vgmstream_ea_patl(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sf_body = NULL; + ea_fixed_header ea = {0}; + + + /* checks */ + if (!parse_fixed_header(sf, &ea, 0x00)) + return NULL; + + /* .pth: Triple Play 97 (PC) */ + /* often also found as nameless file pairs in bigfiles [FIFA 97 (PC)] */ + if (check_extensions(sf, "pth")) { + sf_body = open_streamfile_by_ext(sf, "ptd"); + if (!sf_body) goto fail; + } + else + return NULL; + + + ea.is_bank = 1; + if (ea.start_offset != 0x00) goto fail; + + vgmstream = init_vgmstream_ea_fixed_header(sf_body, &ea); + if (!vgmstream) goto fail; + + + close_streamfile(sf_body); + return vgmstream; + +fail: + close_streamfile(sf_body); + close_vgmstream(vgmstream); + return NULL; +} + + +static VGMSTREAM* init_vgmstream_ea_fixed_header(STREAMFILE* sf, ea_fixed_header* ea) { + VGMSTREAM* vgmstream = NULL; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(ea.channels, ea.loop_flag); + vgmstream = allocate_vgmstream(ea->channels, ea->loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = ea.sample_rate; - vgmstream->num_samples = ea.num_samples; - //vgmstream->loop_start_sample = ea.loop_start; - //vgmstream->loop_end_sample = ea.loop_end; + //vgmstream->stream_size = ea->stream_size; /* only on PS1, and sometimes uninitialised garbage? */ + vgmstream->sample_rate = ea->sample_rate; + vgmstream->num_samples = ea->num_samples; + /* loops are rare, loop_end might also need +1 just like variable_header? + * NBA Live 97 (PS1, JPN) ZAUDIOFX.BKH #15-#18 loop_end == num_samples-1 */ + vgmstream->loop_start_sample = ea->loop_start; + vgmstream->loop_end_sample = ea->loop_end; - vgmstream->codec_endian = ea.big_endian; + vgmstream->codec_endian = ea->big_endian; - vgmstream->meta_type = meta_EA_SCHL_fixed; - vgmstream->layout_type = layout_blocked_ea_schl; + vgmstream->meta_type = ea->is_bank ? meta_EA_BNK_fixed : meta_EA_SCHL_fixed; + vgmstream->layout_type = ea->is_bank ? layout_none : layout_blocked_ea_schl; - switch (ea.codec) { + switch (ea->codec) { case EA_CODEC_PCM: - vgmstream->coding_type = ea.bps==8 ? coding_PCM8 : (ea.big_endian ? coding_PCM16BE : coding_PCM16LE); + vgmstream->coding_type = ea->bps == 8 ? coding_PCM8 : (ea->big_endian ? coding_PCM16BE : coding_PCM16LE); break; case EA_CODEC_IMA: @@ -79,12 +210,12 @@ VGMSTREAM* init_vgmstream_ea_schl_fixed(STREAMFILE* sf) { break; default: - VGM_LOG("EA: unknown codec 0x%02x\n", ea.codec); + VGM_LOG("EA SCHl: unknown fixed header codec 0x%02x\n", ea->codec); goto fail; } - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + if (!vgmstream_open_stream(vgmstream, sf, ea->start_offset)) goto fail; return vgmstream; @@ -94,60 +225,59 @@ fail: } -static int parse_fixed_header(STREAMFILE* sf, ea_fixed_header* ea) { - uint32_t offset = 0x00, size = 0; +static int parse_fixed_header(STREAMFILE* sf, ea_fixed_header* ea, off_t offset) { - if (is_id32be(offset+0x08, sf, "PATl")) - offset = 0x08; - else if (is_id32be(offset+0x0c, sf, "PATl")) - offset = 0x0c; /* extra field in PS1 */ - else + if (!is_id32be(offset + 0x00, sf, "PATl")) goto fail; - size = read_u32le(offset+0x34, sf); - if (size == 0x20 && is_id32be(offset+0x38, sf, "TMpl")) { /* PC LE? */ - offset += 0x3c; + /* PATl header is 0x10 bytes, and can be separate from the rest of the body (BNKl) */ + offset += read_u32le(offset + 0x0c, sf) + 0x0c; /* body pointer base from ptr pos */ - ea->version = read_u8 (offset+0x00, sf); - ea->bps = read_u8 (offset+0x01, sf); - ea->channels = read_u8 (offset+0x02, sf); - ea->codec = read_u8 (offset+0x03, sf); + //size = read_u32le(offset + 0x34, sf); /* pointer to end of all header bodies, not size */ + if (/*size == 0x20 &&*/ is_id32be(offset + 0x28, sf, "TMpl")) { /* PC LE? */ + offset += 0x2c; + + ea->version = read_u8 (offset + 0x00, sf); + ea->bps = read_u8 (offset + 0x01, sf); + ea->channels = read_u8 (offset + 0x02, sf); + ea->codec = read_u8 (offset + 0x03, sf); /* 0x04: 0? */ - ea->sample_rate = read_u16le(offset+0x06, sf); - ea->num_samples = read_s32le(offset+0x08, sf); - /* 0x0c: -1? loop_start? */ - /* 0x10: -1? loop_end? */ - /* 0x14: 0? data start? */ - /* 0x18: -1? */ - /* 0x1c: volume? (always 128) */ + ea->sample_rate = read_u16le(offset + 0x06, sf); + ea->num_samples = read_s32le(offset + 0x08, sf); + ea->loop_start = read_s32le(offset + 0x0c, sf); + ea->loop_end = read_s32le(offset + 0x10, sf); + ea->start_offset = read_u32le(offset + 0x14, sf); /* BNKl only */ + /* 0x18: -1? */ /* SCHl only */ } - else if (size == 0x38 && is_id32be(offset+0x38, sf, "TMxl")) { /* PSX LE? */ - offset += 0x3c; + else if (/*size == 0x38 &&*/ is_id32be(offset + 0x28, sf, "TMxl")) { /* PSX LE? */ + offset += 0x2c; - ea->version = read_u8 (offset+0x00, sf); - ea->bps = read_u8 (offset+0x01, sf); - ea->channels = read_u8 (offset+0x02, sf); - ea->codec = read_u8 (offset+0x03, sf); + ea->version = read_u8 (offset + 0x00, sf); + ea->bps = read_u8 (offset + 0x01, sf); + ea->channels = read_u8 (offset + 0x02, sf); + ea->codec = read_u8 (offset + 0x03, sf); /* 0x04: 0? */ - ea->sample_rate = read_u16le(offset+0x06, sf); - /* 0x08: 0x20C? */ - ea->num_samples = read_s32le(offset+0x0c, sf); - /* 0x10: -1? loop_start? */ - /* 0x14: -1? loop_end? */ - /* 0x18: 0x20C? */ + ea->sample_rate = read_u16le(offset + 0x06, sf); + /* 0x08: 0x20C in SCHl, 0x800 in BNKl? */ + ea->num_samples = read_s32le(offset + 0x0c, sf); + ea->loop_start = read_s32le(offset + 0x10, sf); + ea->loop_end = read_s32le(offset + 0x14, sf); + ea->start_offset = read_u32le(offset + 0x18, sf); /* BNKl only */ /* 0x1c: 0? */ - /* 0x20: 0? */ + //ea->stream_size = read_u32le(offset + 0x20, sf); /* BNKl only */ /* 0x24: 0? */ /* 0x28: -1? */ /* 0x2c: -1? */ - /* 0x30: -1? */ - /* 0x34: volume? (always 128) */ + /* 0x30: -1? */ /* SCHl only */ } else { + VGM_LOG("EA SCHl: unknown fixed header subtype\n"); goto fail; } + /* after header bodies */ + /* 0x00: volume? (127 or 128) */ - //ea->loop_flag = (ea->loop_end_sample); + ea->loop_flag = (ea->loop_end != -1); return 1; fail: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_standard.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_standard.c index 2eb70f745..94d2c19bb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_standard.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_schl_standard.c @@ -46,20 +46,21 @@ VGMSTREAM* init_vgmstream_ea_schl(STREAMFILE* sf) { return NULL; /* check header */ - if (read_u32be(0x00, sf) != EA_BLOCKID_HEADER && /* "SCHl" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_EN) && /* "SHEN" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_FR) && /* "SHFR" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_GE) && /* "SHGE" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_DE) && /* "SHDE" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_IT) && /* "SHIT" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_SP) && /* "SHSP" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_ES) && /* "SHES" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_MX) && /* "SHMX" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_RU) && /* "SHRU" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JA) && /* "SHJA" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JP) && /* "SHJP" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_PL) && /* "SHPL" */ - read_u32be(0x00, sf) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_BR)) /* "SHBR" */ + uint32_t header = read_u32be(0x00, sf); + if (header != EA_BLOCKID_HEADER && /* "SCHl" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_EN) && /* "SHEN" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_FR) && /* "SHFR" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_GE) && /* "SHGE" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_DE) && /* "SHDE" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_IT) && /* "SHIT" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_SP) && /* "SHSP" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_ES) && /* "SHES" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_MX) && /* "SHMX" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_RU) && /* "SHRU" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JA) && /* "SHJA" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JP) && /* "SHJP" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_PL) && /* "SHPL" */ + header != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_BR)) /* "SHBR" */ return NULL; /* Stream is divided into blocks/chunks: SCHl=audio header, SCCl=count of SCDl, SCDl=data xN, SCLl=loop end, SCEl=end. @@ -183,3 +184,55 @@ fail: close_vgmstream(vgmstream); return NULL; } + + +/* EA standalone PT variable header - rare, found during the transition from fixed header */ +VGMSTREAM* init_vgmstream_ea_pt(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sf_body = NULL; + off_t head_offset, body_offset; + size_t head_size; + int is_split = 0; + + + /* .pth: split [NBA Live 97 (PC)] + * .dat: joined [NBA Live 97/98 (PC)] */ + /* often also found as nameless file pairs in bigfiles [FIFA 97 (PC)] */ + if (check_extensions(sf, "pth")) { + sf_body = open_streamfile_by_ext(sf, "ptd"); + if (!sf_body) goto fail; + is_split = 1; + } + else //if (!check_extensions(sf, "dat,ldat")) + return NULL; + + + if (is_split) { + head_size = get_streamfile_size(sf); + head_offset = 0x00; + body_offset = 0x00; + } + /* these contain multiple subsongs, but with no clear way + * to get each of their offsets, unimplemented for now */ + //else { /* NBA 97 variant, NBA 98 has an even weirder variant */ + // head_size = read_u32le(0x00, sf); + // head_offset = 0x04; + // body_offset = head_offset + head_size; + // sf_body = sf; + //} + + if (!is_id32be(head_offset, sf, "PT\0\0")) /* does standalone GSTR also exist? */ + goto fail; + + vgmstream = load_vgmstream_ea_pt(sf, sf_body, head_offset, head_size, body_offset); + if (!vgmstream) goto fail; + + + if (is_split) close_streamfile(sf_body); + return vgmstream; + +fail: + if (is_split) close_streamfile(sf_body); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_wve_au00.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_wve_au00.c index 72d328496..78244fd1d 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ea_wve_au00.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_wve_au00.c @@ -1,59 +1,60 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "../layout/layout.h" - -/* EA WVE (VLC0/au00) - from Electronic Arts PS movies [Future Cop - L.A.P.D. (PS), Supercross 2000 (PS)] */ -VGMSTREAM * init_vgmstream_ea_wve_au00(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - - /* checks */ - /* .wve: common, .fsv: Future Cop LAPD (PS1) */ - if (!check_extensions(streamFile, "wve,fsv")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x564C4330) /* "VLC0" */ - goto fail; - - start_offset = read_32bitBE(0x04,streamFile); - if (read_32bitBE(start_offset, streamFile) != 0x61753030 && /* "au00" */ - read_32bitBE(start_offset, streamFile) != 0x61753031) /* "au01" (last block, but could be first) */ - goto fail; - loop_flag = 0; - channel_count = 2; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_EA_WVE_AU00; - vgmstream->sample_rate = 22050; - - /* You'd think they'd use coding_EA_XA_int but instead it's PS-ADPCM without flags and 0x0f frame size - * (equivalent to configurable PS-ADPCM), surely to shoehorn EA-XA sizes into the PS1 hardware decoder */ - vgmstream->coding_type = coding_PSX_cfg; - vgmstream->interleave_block_size = 0x0f; - vgmstream->layout_type = layout_blocked_ea_wve_au00; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - /* calc num_samples manually */ - { - vgmstream->next_block_offset = start_offset; - do { - block_update(vgmstream->next_block_offset,vgmstream); - vgmstream->num_samples += ps_cfg_bytes_to_samples(vgmstream->current_block_size, vgmstream->interleave_block_size, 1); - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - block_update(start_offset, vgmstream); - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" + +/* EA WVE (VLC0/au00) - from Electronic Arts PS movies [Future Cop - L.A.P.D. (PS), Supercross 2000 (PS)] */ +VGMSTREAM* init_vgmstream_ea_wve_au00(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels; + + + /* checks */ + if (!is_id32be(0x00,sf, "VLC0")) + return NULL; + + /* .wve: common, .fsv: Future Cop LAPD (PS1) */ + if (!check_extensions(sf, "wve,fsv")) + return NULL; + + start_offset = read_32bitBE(0x04,sf); + if (!is_id32be(start_offset, sf, "au00") && + !is_id32be(start_offset, sf, "au01")) // last block, but could be first) + return NULL; + loop_flag = 0; + channels = 2; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_EA_WVE_AU00; + vgmstream->sample_rate = 22050; + + /* You'd think they'd use coding_EA_XA_int but instead it's PS-ADPCM without flags and 0x0f frame size + * (equivalent to configurable PS-ADPCM), surely to shoehorn EA-XA sizes into the PS1 hardware decoder */ + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->interleave_block_size = 0x0f; + vgmstream->layout_type = layout_blocked_ea_wve_au00; + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + + /* calc num_samples manually */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + vgmstream->num_samples += ps_cfg_bytes_to_samples(vgmstream->current_block_size, vgmstream->interleave_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(sf)); + block_update(start_offset, vgmstream); + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/flx.c b/Frameworks/vgmstream/vgmstream/src/meta/flx.c index 832f4cc24..e59e6c0f3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/flx.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/flx.c @@ -1,113 +1,117 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* FLX - from Ultima IX (.FLX is actually an archive format with sometimes sound data, let's support both anyway) */ -VGMSTREAM * init_vgmstream_flx(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, stream_offset = 0; - size_t data_size; - int loop_flag, channel_count, codec; - int total_subsongs = 0, target_subsong = streamFile->stream_index; - size_t stream_size = 0; - - - /* check extensions (.flx: name of archive, files inside don't have extensions) */ - if (!check_extensions(streamFile,"flx")) - goto fail; - - /* all spaces up to 0x50 = archive FLX */ - if (read_32bitBE(0x00,streamFile) == 0x20202020 && read_32bitBE(0x40,streamFile) == 0x20202020) { - int i; - int entries = read_32bitLE(0x50,streamFile); - off_t offset = 0x80; - - if (read_32bitLE(0x54,streamFile) != 0x02 - || read_32bitLE(0x58,streamFile) != get_streamfile_size(streamFile)) - goto fail; - - if (target_subsong == 0) target_subsong = 1; - - for (i = 0; i < entries; i++) { - off_t entry_offset = read_32bitLE(offset + 0x00, streamFile); - size_t entry_size = read_32bitLE(offset + 0x04, streamFile); - offset += 0x08; - - if (entry_offset != 0x00) - total_subsongs++; /* many entries are empty */ - if (total_subsongs == target_subsong && stream_offset == 0) { - stream_offset = entry_offset; /* found but let's keep adding total_streams */ - stream_size = entry_size; - } - } - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - if (stream_offset == 0x00) goto fail; - } - else { - stream_offset = 0x00; - stream_size = get_streamfile_size(streamFile); - } - - if (read_32bitLE(stream_offset + 0x30,streamFile) != 0x10) - goto fail; - data_size = read_32bitLE(stream_offset + 0x28,streamFile); - channel_count = read_32bitLE(stream_offset + 0x34,streamFile); - codec = read_32bitLE(stream_offset + 0x38,streamFile); - loop_flag = (channel_count > 1); /* full seamless repeats in music */ - start_offset = stream_offset + 0x3c; - /* 0x00: id */ - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(stream_offset + 0x2c,streamFile); - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - vgmstream->meta_type = meta_PC_FLX; - - switch(codec) { - case 0x00: /* PCM (sfx) */ - vgmstream->coding_type = coding_PCM16LE; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x02; - - vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 16); - break; - - case 0x01: /* EA-XA (music, sfx) */ - vgmstream->coding_type = channel_count > 1 ? coding_EA_XA : coding_EA_XA_int; - vgmstream->layout_type = layout_none; - - vgmstream->num_samples = read_32bitLE(stream_offset + 0x28,streamFile) / 0x0f*channel_count * 28; /* ea_xa_bytes_to_samples */ - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - break; - - case 0x02: /* EA-MT (voices) */ - vgmstream->coding_type = coding_EA_MT; - vgmstream->layout_type = layout_none; - vgmstream->codec_data = init_ea_mt(vgmstream->channels, 0); - if (!vgmstream->codec_data) goto fail; - - vgmstream->num_samples = read_32bitLE(start_offset,streamFile); - start_offset += 0x04; - break; - - default: - VGM_LOG("FLX: unknown codec 0x%x\n", codec); - goto fail; - } - - read_string(vgmstream->stream_name,0x20+1, stream_offset + 0x04,streamFile); - - - /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .FLX - from Ultima IX (PC) */ +VGMSTREAM* init_vgmstream_flx(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset, stream_offset = 0; + size_t data_size; + int loop_flag, channels, codec; + int total_subsongs = 0, target_subsong = sf->stream_index; + size_t stream_size = 0; + + + /* checks */ + /* .flx: name of archive (filenames inside don't have extensions) */ + if (!check_extensions(sf,"flx,")) + return NULL; + + // .FLX an archive format with sometimes sound data, let's support both anyway + // all spaces up to 0x50 = archive FLX + if (is_id32be(0x00,sf, " ") && is_id32be(0x40,sf, " ")) { + int entries = read_s32le(0x50,sf); + if (read_u32le(0x54,sf) != 0x02) + return NULL; + if (read_u32le(0x58,sf) != get_streamfile_size(sf)) + return NULL; + + if (target_subsong == 0) target_subsong = 1; + + uint32_t offset = 0x80; + for (int i = 0; i < entries; i++) { + off_t entry_offset = read_u32le(offset + 0x00, sf); + size_t entry_size = read_u32le(offset + 0x04, sf); + offset += 0x08; + + if (entry_offset != 0x00) + total_subsongs++; /* many entries are empty */ + if (total_subsongs == target_subsong && stream_offset == 0) { + stream_offset = entry_offset; /* found but let's keep adding total_streams */ + stream_size = entry_size; + } + } + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + if (stream_offset == 0x00) + return NULL; + } + else { + stream_offset = 0x00; + stream_size = get_streamfile_size(sf); + } + + // file ID, can be a bit higher in sfx packs + if (read_u32le(stream_offset + 0x00,sf) >= 0x10000) + return NULL; + // 04: filename + if (read_u32le(stream_offset + 0x30,sf) != 0x10) + return NULL; + data_size = read_u32le(stream_offset + 0x28,sf); + channels = read_s32le(stream_offset + 0x34,sf); + codec = read_u32le(stream_offset + 0x38,sf); + loop_flag = (channels > 1); /* full seamless repeats in music */ + start_offset = stream_offset + 0x3c; + /* 0x00: id */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(stream_offset + 0x2c,sf); + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + vgmstream->meta_type = meta_PC_FLX; + + switch(codec) { + case 0x00: /* PCM (sfx) */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 16); + break; + + case 0x01: /* EA-XA (music, sfx) */ + vgmstream->coding_type = channels > 1 ? coding_EA_XA : coding_EA_XA_int; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = read_32bitLE(stream_offset + 0x28,sf) / 0x0f*channels * 28; /* ea_xa_bytes_to_samples */ + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + break; + + case 0x02: /* EA-MT (voices) */ + vgmstream->coding_type = coding_EA_MT; + vgmstream->layout_type = layout_none; + vgmstream->codec_data = init_ea_mt(vgmstream->channels, 0); + if (!vgmstream->codec_data) goto fail; + + vgmstream->num_samples = read_32bitLE(start_offset,sf); + start_offset += 0x04; + break; + + default: + VGM_LOG("FLX: unknown codec 0x%x\n", codec); + goto fail; + } + + read_string(vgmstream->stream_name,0x20+1, stream_offset + 0x04,sf); + + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h index 24550161a..cf7650103 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb_keys.h @@ -70,9 +70,10 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSB5, FSBKEY_ADD("3cfe772db5b55b806541d3faf894020e") }, // Final Fantasy XV: War for Eos (Android) { MODE_FSB5, FSBKEY_ADD("aj#$kLucf2lh}eqh") }, // Forza Motorsport 2023 (PC) { MODE_FSB4, FSBKEY_ADD("dpdjeoqkr") }, // AirRider CrazyRacing (PC) - { MODE_FSB5, FSBKEY_ADD("weareAbsolutelyUnsure2018") }, // Wanderstop (PC) - { MODE_FSB5, FSBKEY_ADD(".xW3uXQ8q79yunvMjL6nahLXts9esEXX2VgetuPCxdLrAjUUbZAmB7R*A6KjW24NU_8ifMZ8TC4Qk@_oEsjsK2QLpAaG-Fy!wYKP") }, // UNBEATABLE Demo (PC) - { MODE_FSB5, FSBKEY_ADD(",H9}:p?`bRlQG5_yJ\"\"/L,X_{:=Gs1") }, // Rennsport (PC) + { MODE_FSB5, FSBKEY_ADD("weareAbsolutelyUnsure2018") }, // Wanderstop (PC) + { MODE_FSB5, FSBKEY_ADD(".xW3uXQ8q79yunvMjL6nahLXts9esEXX2VgetuPCxdLrAjUUbZAmB7R*A6KjW24NU_8ifMZ8TC4Qk@_oEsjsK2QLpAaG-Fy!wYKP") }, // UNBEATABLE Demo (PC) + { MODE_FSB5, FSBKEY_ADD(",H9}:p?`bRlQG5_yJ\"\"/L,X_{:=Gs1") }, // Rennsport (PC) + { MODE_FSB5, FSBKEY_ADD("K50j8B2H4pVUfzt7yxfTprg9wdr9zIH6") }, // Gunner, HEAT, PC! (PC) /* some games use a key per file, generated from the filename * (could add all of them but there are a lot of songs, so external .fsbkey are probably better) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index f1f48552d..ec90a6640 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h @@ -1575,6 +1575,8 @@ static const hcakey_info hcakey_list[] = { // Patapon 1 & 2 Reloaded (PC) {3316332033470531258}, // 2E05FA69EC4286BA + // Aether Gazer (multi) + {1578660190369042886}, // 15E887143BFF51C6 }; #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index 668a37f2c..02cea08ba 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -194,8 +194,9 @@ VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_1snh(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_eacs(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_ea_1snh(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_eacs(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_crdf(STREAMFILE* sf); VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile); @@ -290,8 +291,8 @@ VGMSTREAM * init_vgmstream_fag(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_mic(STREAMFILE* sf); -VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_pdt(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_pdt_split(STREAMFILE* sf); VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf); @@ -304,8 +305,6 @@ VGMSTREAM* init_vgmstream_spsd(STREAMFILE* sf); VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_ubi_jade(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ubi_jade_container(STREAMFILE * streamFile); @@ -392,8 +391,6 @@ VGMSTREAM * init_vgmstream_gcub(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_apple_caff(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_pc_mxst(STREAMFILE* streamFile); @@ -578,20 +575,24 @@ VGMSTREAM * init_vgmstream_xa_04sw(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_txth(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ea_schl_video(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_abk_schl(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_amb_schl(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_hdr_dat_v2(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_mpf_mus_schl(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ea_msb_mus_schl(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_ea_schl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_bnk(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_abk_schl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_amb_schl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_hdr_dat(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_hdr_dat_v2(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_map_mus(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_mpf_mus_schl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_msb_mus_schl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_pt(STREAMFILE* sf); VGMSTREAM* load_vgmstream_ea_bnk(STREAMFILE* sf, off_t offset, int target_stream, int is_embedded); VGMSTREAM* load_vgmstream_ea_schl(STREAMFILE* sf, off_t offset); +VGMSTREAM* load_vgmstream_ea_pt(STREAMFILE* sf_head, STREAMFILE* sf_body, off_t head_offset, size_t head_size, off_t body_offset); -VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_ea_patl(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_schl_fixed(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ea_bnk_fixed(STREAMFILE* sf); VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile); @@ -692,7 +693,7 @@ VGMSTREAM * init_vgmstream_sthd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_dsp_std_le(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_pcm_sre(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_sre_pcm(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ubi_lyn(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ubi_lyn_container(STREAMFILE * streamFile); diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mhwk.c b/Frameworks/vgmstream/vgmstream/src/meta/mhwk.c index f85f452db..e09e58757 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mhwk.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mhwk.c @@ -29,17 +29,13 @@ VGMSTREAM* init_vgmstream_mhwk(STREAMFILE* sf) { chunk_size = read_u32be(current_offset + 0x04, sf); current_offset += 0x08; - if (chunk_id == get_id32be("Cue#")) { - current_offset += chunk_size; - continue; - } - else if (chunk_id == get_id32be("ADPC")) { - current_offset += chunk_size; - continue; - } - else if (chunk_id == get_id32be("Data")) { + if (chunk_id == get_id32be("Data")) { break; } + else if (chunk_id == get_id32be("Cue#") || chunk_id == get_id32be("ADPC")) { + current_offset += chunk_size; + continue; + } else { goto fail; } @@ -88,6 +84,17 @@ VGMSTREAM* init_vgmstream_mhwk(STREAMFILE* sf) { vgmstream->coding_type = coding_IMA; vgmstream->layout_type = layout_none; break; + //Riven DVD + case 0x0002: /* MPEG Layer II */ +#if defined(VGM_USE_MPEG) + vgmstream->coding_type = coding_MPEG_layer2; +#elif defined(VGM_USE_FFMPEG) + vgmstream->coding_type = coding_FFmpeg; +#else + goto fail; +#endif + vgmstream->layout_type = layout_none; + break; default: /* Unknown format */ goto fail; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c index 7f51871c6..7a8190fea 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c @@ -26,14 +26,14 @@ VGMSTREAM* init_vgmstream_mp4_aac_ffmpeg(STREAMFILE* sf) { /* checks */ if ((read_u32be(0x00,sf) & 0xFFFFFF00) != 0) /* first atom BE size (usually ~0x18) */ - goto fail; + return NULL; if (!is_id32be(0x04,sf, "ftyp")) - goto fail; + return NULL; /* .bin: Final Fantasy Dimensions (iOS), Final Fantasy V (iOS) * .msd: UNO (iOS) */ if (!check_extensions(sf,"mp4,m4a,m4v,lmp4,bin,lbin,msd")) - goto fail; + return NULL; file_size = get_streamfile_size(sf); @@ -180,56 +180,4 @@ static void parse_mp4(STREAMFILE* sf, mp4_header* mp4) { } } -/* CRI's encryption info (for lack of a better place) [Final Fantasy Digital Card Game (Browser)] - * - * Like other CRI stuff their MP4 can be encrypted, from file's beginning (including headers). - * This is more or less how data is decrypted (supposedly, from decompilations), for reference: - */ -#if 0 -void criAacCodec_SetDecryptionKey(uint64_t keycode, uint16_t* key) { - if (!keycode) - return; - uint16_t k0 = 4 * ((keycode >> 0) & 0x0FFF) | 1; - uint16_t k1 = 2 * ((keycode >> 12) & 0x1FFF) | 1; - uint16_t k2 = 4 * ((keycode >> 25) & 0x1FFF) | 1; - uint16_t k3 = 2 * ((keycode >> 38) & 0x3FFF) | 1; - - key[0] = k0 ^ k1; - key[1] = k1 ^ k2; - key[2] = k2 ^ k3; - key[3] = ~k3; - - /* criatomexacb_generate_aac_decryption_key is slightly different, unsure which one is used: */ - //key[0] = k0 ^ k3; - //key[1] = k2 ^ k3; - //key[2] = k2 ^ k3; - //key[3] = ~k3; -} - -void criAacCodec_DecryptData(const uint16_t* key, uint8_t* data, uint32_t size) { - if (data_size) - return; - uint16_t seed0 = ~key[3]; - uint16_t seed1 = seed0 ^ key[2]; - uint16_t seed2 = seed1 ^ key[1]; - uint16_t seed3 = seed2 ^ key[0]; - - uint16_t xor = 2 * seed0 | 1; - uint16_t add = 2 * seed0 | 1; /* not seed1 */ - uint16_t mul = 4 * seed2 | 1; - - for (int i = 0; i < data_size; i++) { - - if (!(uint16_t)i) { /* every 0x10000, without modulo */ - mul = (4 * seed2 + seed3 * (mul & 0xFFFC)) & 0xFFFD | 1; - add = (2 * seed0 + seed1 * (add & 0xFFFE)) | 1; - } - xor = xor * mul + add; - - *data ^= (xor >> 8) & 0xFF; - ++data; - } -} -#endif - #endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c deleted file mode 100644 index 550c295dc..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c +++ /dev/null @@ -1,55 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - - -//todo this was extracted from a .pak bigfile. Inside are headers then data (no extensions), -// but headers are VAGp in the PS2 version, so it would make more sense to extract pasting -// header+data together, or support as-is (.SCK is a fake extension). - -/* SCK+DSP - Scorpion King (GC) */ -VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - int channel_count, loop_flag; - size_t data_size; - - /* check extension, case insensitive */ - if (!check_extensions(streamFile, "dsp")) - goto fail; - - streamHeader = open_streamfile_by_ext(streamFile, "sck"); - if (!streamHeader) goto fail; - - if (read_32bitBE(0x5C,streamHeader) != 0x60A94000) - goto fail; - - channel_count = 2; - loop_flag = 0; - data_size = read_32bitBE(0x14,streamHeader); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x18,streamHeader); - vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitBE(0xC,streamHeader); - if (vgmstream->interleave_block_size > 0) - vgmstream->interleave_last_block_size = (data_size % (vgmstream->interleave_block_size * channel_count)) / channel_count; - - vgmstream->meta_type = meta_NGC_SCK_DSP; - - dsp_read_coefs_be(vgmstream,streamHeader, 0x2c, 0x00); - - if (!vgmstream_open_stream(vgmstream,streamFile,0x00)) - goto fail; - close_streamfile(streamHeader); - return vgmstream; - -fail: - close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pcm_sre.c b/Frameworks/vgmstream/vgmstream/src/meta/pcm_sre.c deleted file mode 100644 index 3a51c1fc3..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/pcm_sre.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .PCM+SRE. - Capcom's header+data container thing [Viewtiful Joe (PS2)] */ -VGMSTREAM * init_vgmstream_pcm_sre(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t table1_entries, table2_entries; - off_t table1_offset, table2_offset, header_offset; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* checks */ - /* .pcm=data, .sre=header */ - if (!check_extensions(streamFile, "pcm")) - goto fail; - - /* first PS-ADPCM frame should be is null */ - if (read_32bitBE(0x00,streamFile) != 0x00020000 || - read_32bitBE(0x04,streamFile) != 0x00000000 || - read_32bitBE(0x08,streamFile) != 0x00000000 || - read_32bitBE(0x0c,streamFile) != 0x00000000) - goto fail; - - streamHeader = open_streamfile_by_ext(streamFile, "sre"); - if (!streamHeader) goto fail; - - table1_entries = read_32bitLE(0x00, streamHeader); - table1_offset = read_32bitLE(0x04, streamHeader); - table2_entries = read_32bitLE(0x08, streamHeader); - table2_offset = read_32bitLE(0x0c, streamHeader); - if (table1_entries*0x60 + table1_offset != table2_offset) - goto fail; /* just in case */ - - total_subsongs = table2_entries; - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - header_offset = table2_offset + (target_subsong-1)*0x20; - - channel_count = read_32bitLE(header_offset+0x00,streamHeader); - loop_flag = read_32bitLE(header_offset+0x18,streamHeader); - start_offset = read_32bitLE(header_offset+0x08,streamHeader); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_16bitLE(header_offset+0x04,streamHeader); - vgmstream->meta_type = meta_PCM_SRE; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1000; - - vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(header_offset+0x0c,streamHeader), channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(header_offset+0x10,streamHeader)*channel_count, channel_count); - vgmstream->loop_end_sample = ps_bytes_to_samples(read_32bitLE(header_offset+0x14,streamHeader)*channel_count, channel_count); - - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = read_32bitLE(header_offset+0x0c,streamHeader); - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - close_streamfile(streamHeader); - return vgmstream; - -fail: - close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c b/Frameworks/vgmstream/vgmstream/src/meta/pdt.c similarity index 51% rename from Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c rename to Frameworks/vgmstream/vgmstream/src/meta/pdt.c index e7f5bd59e..023a82cb3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/pdt.c @@ -1,214 +1,211 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* PDT - Hudson's stream container [Adventure Island (GC), Muscle Champion (GC), Mario Party series (GC)] */ -VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int loop_flag, channel_count, sample_rate; - size_t entries, nibble_size, loop_start; - off_t entries_offset, coefs_offset, header_offset; - off_t channel1_offset = 0, channel2_offset = 0, coef_offset = 0; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* checks */ - if (!check_extensions(streamFile, "pdt")) - goto fail; - - if (read_16bitBE(0x00,streamFile) != 0x01) /* version? */ - goto fail; - if (read_32bitBE(0x04,streamFile) != 0x02 && /* Mario Party 4 (GC) */ - read_32bitBE(0x04,streamFile) != 0x04) /* Cubic Lode Runner (GC) */ - goto fail; - if (read_32bitBE(0x08,streamFile) != 0x7d00) /* not-sample rate? */ - goto fail; - if (read_32bitBE(0x0c,streamFile) != 0x02 && /* not-channels? */ - read_32bitBE(0x0c,streamFile) != 0x04) - goto fail; - - entries = read_16bitBE(0x02,streamFile); - entries_offset = read_32bitBE(0x10,streamFile); - coefs_offset = read_32bitBE(0x14,streamFile); - //headers_offset = read_32bitBE(0x18,streamFile); /* we'll have pointers to those two */ - //streams_offset = read_32bitBE(0x1c,streamFile); - - /* find subsongs and target header, as entries can be empty/repeated */ - { - /* tables to cache reads as it can be kinda slow with so many loops */ - uint32_t data_offsets[0x2000]; - uint32_t entry_offset, data_offset; - int i,j; - - if (entries > 0x2000) - goto fail; - - total_subsongs = 0; - if (target_subsong == 0) target_subsong = 1; - - header_offset = 0; - for (i = 0; i < entries; i++) { - int is_unique = 1; - - entry_offset = read_32bitBE(entries_offset + i*0x04,streamFile); - if (entry_offset == 0x00) - continue; - data_offset = read_32bitBE(entry_offset+0x10,streamFile); - - /* check if current entry header was repeated (same file offset, difference in flags only) */ - for (j = 0; j < total_subsongs; j++) { - if (data_offsets[j] == data_offset) { - is_unique = 0; - break; - } - } - if (!is_unique) - continue; - - data_offsets[total_subsongs] = data_offset; - total_subsongs++; - - /* target GET, but keep going to count subsongs */ - if (!header_offset && target_subsong == total_subsongs) { - header_offset = entry_offset; - } - } - } - - /* parse header */ - { - uint8_t flags; - size_t coef1_entry; - off_t coef1_offset; - - flags = read_8bit(header_offset+0x00,streamFile); - sample_rate = read_32bitBE(header_offset+0x04,streamFile); - /* 0x01: unknown + 0x4000 */ - sample_rate = read_32bitBE(header_offset+0x04,streamFile); - nibble_size = read_32bitBE(header_offset+0x08,streamFile); - loop_start = read_32bitBE(header_offset+0x0c,streamFile); - - channel1_offset = read_32bitBE(header_offset+0x10,streamFile); - coef1_entry = read_16bitBE(header_offset+0x14,streamFile); - coef1_offset = coefs_offset + coef1_entry*0x20; - - if (flags & 0x01) { - //size_t coef2_entry; - //off_t coef2_offset; - - channel2_offset = read_32bitBE(header_offset+0x18,streamFile); - /* always after coef1 in practice */ - //coef2_entry = read_16bitBE(header_offset+0x1c,streamFile); - //coef2_offset = coefs_offset + coef2_entry*0x20; - //if (coef1_offset + 0x20 != coef2_offset) - // goto fail; - } - - coef_offset = coef1_offset; - loop_flag = (flags & 0x02); - channel_count = (flags & 0x01) ? 2 : 1; - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - //vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count);//todo remove - vgmstream->num_samples = dsp_nibbles_to_samples(nibble_size); - //vgmstream->loop_start_sample = dsp_bytes_to_samples(loop_start, channel_count);//todo remove - vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start); - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->meta_type = meta_NGC_PDT; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - dsp_read_coefs_be(vgmstream, streamFile, coef_offset, 0x20); - - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = nibble_size / 2 * channel_count; - - if (!vgmstream_open_stream(vgmstream,streamFile,channel1_offset)) - goto fail; - - /* channels may start at slightly separated offsets */ - if (channel_count == 2) { - vgmstream->ch[1].channel_start_offset = - vgmstream->ch[1].offset = channel2_offset; - } - - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - - -/* PDT - custom fake header for split (PDTExt) .ptd [Mario Party (GC)] */ -VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "pdt")) - goto fail; - - /* 0x10 fake header + chunks of the original header / data pasted together */ - if (read_32bitBE(0x00,streamFile) != 0x50445420 && /* "PDT " */ - read_32bitBE(0x04,streamFile) != 0x44535020 && /* "DSP " */ - read_32bitBE(0x08,streamFile) != 0x48454144 && /* "HEAD " */ - read_16bitBE(0x0C,streamFile) != 0x4552) /* "ER " */ - goto fail; - - start_offset = 0x800; - channel_count = (uint16_t)(read_16bitLE(0x0E,streamFile)); - loop_flag = (read_32bitBE(0x1C,streamFile) != 2); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x14,streamFile); - - if (channel_count == 1) { - vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count/2; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x1C,streamFile)*14/8/channel_count/2; - vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*14/8/channel_count/2; - } - } - else if (channel_count == 2) { - vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x1C,streamFile)*14/8/channel_count; - vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*14/8/channel_count; - } - } - else { - goto fail; - } - - vgmstream->meta_type = meta_NGC_PDT; - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_none; - dsp_read_coefs_be(vgmstream, streamFile, 0x50, 0x20); - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - if (channel_count == 2) { - vgmstream->ch[1].channel_start_offset = - vgmstream->ch[1].offset = ((get_streamfile_size(streamFile)+start_offset) / channel_count); - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .PDT - Hudson's stream container [Adventure Island (GC), Muscle Champion (GC), Mario Party series (GC)] */ +VGMSTREAM* init_vgmstream_pdt(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int loop_flag, channel_count, sample_rate; + size_t entries, nibble_size, loop_start; + off_t entries_offset, coefs_offset, header_offset; + off_t channel1_offset = 0, channel2_offset = 0, coef_offset = 0; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!check_extensions(sf, "pdt")) + return NULL; + + if (read_16bitBE(0x00,sf) != 0x01) /* version? */ + return NULL; + if (read_32bitBE(0x04,sf) != 0x02 && /* Mario Party 4 (GC) */ + read_32bitBE(0x04,sf) != 0x04) /* Cubic Lode Runner (GC) */ + return NULL; + if (read_32bitBE(0x08,sf) != 0x7d00) /* not-sample rate? */ + return NULL; + if (read_32bitBE(0x0c,sf) != 0x02 && /* not-channels? */ + read_32bitBE(0x0c,sf) != 0x04) + return NULL; + + entries = read_16bitBE(0x02,sf); + entries_offset = read_32bitBE(0x10,sf); + coefs_offset = read_32bitBE(0x14,sf); + //headers_offset = read_32bitBE(0x18,streamFile); /* we'll have pointers to those two */ + //streams_offset = read_32bitBE(0x1c,streamFile); + + /* find subsongs and target header, as entries can be empty/repeated */ + { + /* tables to cache reads as it can be kinda slow with so many loops */ + uint32_t data_offsets[0x2000]; + uint32_t entry_offset, data_offset; + + if (entries > 0x2000) + goto fail; + + total_subsongs = 0; + if (target_subsong == 0) target_subsong = 1; + + header_offset = 0; + for (int i = 0; i < entries; i++) { + int is_unique = 1; + + entry_offset = read_32bitBE(entries_offset + i*0x04,sf); + if (entry_offset == 0x00) + continue; + data_offset = read_32bitBE(entry_offset+0x10,sf); + + /* check if current entry header was repeated (same file offset, difference in flags only) */ + for (int j = 0; j < total_subsongs; j++) { + if (data_offsets[j] == data_offset) { + is_unique = 0; + break; + } + } + if (!is_unique) + continue; + + data_offsets[total_subsongs] = data_offset; + total_subsongs++; + + /* target GET, but keep going to count subsongs */ + if (!header_offset && target_subsong == total_subsongs) { + header_offset = entry_offset; + } + } + } + + /* parse header */ + { + uint8_t flags; + size_t coef1_entry; + off_t coef1_offset; + + flags = read_8bit(header_offset+0x00,sf); + sample_rate = read_32bitBE(header_offset+0x04,sf); + /* 0x01: unknown + 0x4000 */ + sample_rate = read_32bitBE(header_offset+0x04,sf); + nibble_size = read_32bitBE(header_offset+0x08,sf); + loop_start = read_32bitBE(header_offset+0x0c,sf); + + channel1_offset = read_32bitBE(header_offset+0x10,sf); + coef1_entry = read_16bitBE(header_offset+0x14,sf); + coef1_offset = coefs_offset + coef1_entry*0x20; + + if (flags & 0x01) { + //size_t coef2_entry; + //off_t coef2_offset; + + channel2_offset = read_32bitBE(header_offset+0x18,sf); + /* always after coef1 in practice */ + //coef2_entry = read_16bitBE(header_offset+0x1c,streamFile); + //coef2_offset = coefs_offset + coef2_entry*0x20; + //if (coef1_offset + 0x20 != coef2_offset) + // goto fail; + } + + coef_offset = coef1_offset; + loop_flag = (flags & 0x02); + channel_count = (flags & 0x01) ? 2 : 1; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + //vgmstream->num_samples = dsp_bytes_to_samples(data_size, channel_count);//todo remove + vgmstream->num_samples = dsp_nibbles_to_samples(nibble_size); + //vgmstream->loop_start_sample = dsp_bytes_to_samples(loop_start, channel_count);//todo remove + vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->meta_type = meta_PDT; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + dsp_read_coefs_be(vgmstream, sf, coef_offset, 0x20); + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = nibble_size / 2 * channel_count; + + if (!vgmstream_open_stream(vgmstream,sf,channel1_offset)) + goto fail; + + /* channels may start at slightly separated offsets */ + if (channel_count == 2) { + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset = channel2_offset; + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + + +/* PDT - custom fake header for split (PDTExt) .ptd [Mario Party (GC)] */ +VGMSTREAM* init_vgmstream_pdt_split(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag, channels; + + + /* checks */ + if (!check_extensions(sf, "pdt")) + return NULL; + + /* 0x10 fake header + chunks of the original header / data pasted together */ + if (read_32bitBE(0x00,sf) != 0x50445420 && /* "PDT " */ + read_32bitBE(0x04,sf) != 0x44535020 && /* "DSP " */ + read_32bitBE(0x08,sf) != 0x48454144 && /* "HEAD " */ + read_16bitBE(0x0C,sf) != 0x4552) /* "ER " */ + goto fail; + + start_offset = 0x800; + channels = (uint16_t)(read_16bitLE(0x0E,sf)); + loop_flag = (read_32bitBE(0x1C,sf) != 2); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitBE(0x14,sf); + + if (channels == 1) { + vgmstream->num_samples = read_32bitBE(0x18,sf)*14/8/channels/2; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x1C,sf)*14/8/channels/2; + vgmstream->loop_end_sample = read_32bitBE(0x18,sf)*14/8/channels/2; + } + } + else if (channels == 2) { + vgmstream->num_samples = read_32bitBE(0x18,sf)*14/8/channels; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x1C,sf)*14/8/channels; + vgmstream->loop_end_sample = read_32bitBE(0x18,sf)*14/8/channels; + } + } + else { + goto fail; + } + + vgmstream->meta_type = meta_PDT; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + dsp_read_coefs_be(vgmstream, sf, 0x50, 0x20); + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + + if (channels == 2) { + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset = ((get_streamfile_size(sf)+start_offset) / channels); + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c index b0c5b61cf..73c25ca3f 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c @@ -1,106 +1,135 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../coding/coding.h" -#include - -static int get_adm_loop_info(STREAMFILE *streamFile, off_t *loop_start_offset); - -/* .adm - from Dragon Quest V (PS2) */ -VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int channel_count, loop_flag = 0; - off_t start_offset, loop_start_offset = 0; - - /* checks */ - if (!check_extensions(streamFile,"adm")) - goto fail; - - /* raw data, but test some .ADM blocks as they always start with PS-ADPCM flag 0x06 every 0x1000 */ - { - int i; - for (i = 0; i < 10; i++) { - if (read_8bit(0x1000*i + 0x01, streamFile) != 0x06) - goto fail; - } - } - - start_offset = 0x00; - loop_flag = get_adm_loop_info(streamFile, &loop_start_offset); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_PS2_ADM; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_adm; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - /* calc num_samples as playable data size varies between files/blocks */ - { - vgmstream->next_block_offset = start_offset; - do { - block_update(vgmstream->next_block_offset,vgmstream); - if (loop_flag && vgmstream->current_block_offset == loop_start_offset) - vgmstream->loop_start_sample = vgmstream->num_samples; - vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); - } - while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); - block_update(start_offset,vgmstream); - - if (loop_flag) - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* loops are not in the .ADM or .DAT bigfile containing them but in the exe; manually get them (a bit meh but whatevs) */ -static int get_adm_loop_info(STREAMFILE *streamFile, off_t *loop_start_offset) { - char file_name[PATH_LIMIT]; - char index_name[PATH_LIMIT]; - STREAMFILE *streamExe = NULL; - int i, name_index = -1, loop_flag; - off_t offset; - - streamExe = open_streamfile_by_filename(streamFile, "SLPM_655.55"); - if (!streamExe) goto fail; - - get_streamfile_filename(streamFile, file_name, PATH_LIMIT); - - /* get file index from name list (file_name == index_name = index number */ - offset = 0x23B3c0; - for (i = 0; i < 51; i++) { - read_string(index_name,0x20+1, offset,streamExe); - - if (strcmp(index_name, file_name)==0) { - name_index = i; - break; - } - offset += 0x20; - } - if (name_index < 0) - goto fail; - - /* get file info using index */ - offset = 0x23BAEC + 0x1c*name_index; - loop_flag = (read_32bitLE(offset + 0x10, streamExe) == 0); /* 1: don't loop, 0: loop */ - if (loop_flag) { /* loop flag */ - *loop_start_offset = read_32bitLE(offset + 0x04, streamExe); - } - /* 0x08: num_samples/loop_end, 0x0c: sample rate (always 44100), 0x14/18: some size? */ - - close_streamfile(streamExe); - return loop_flag; -fail: - close_streamfile(streamExe); - return 0; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" +#include + +static int get_adm_loop_info(STREAMFILE *streamFile, off_t *loop_start_offset); + + +/* .adm - from Dragon Quest V (PS2) */ +VGMSTREAM* init_vgmstream_ps2_adm(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int channels, loop_flag = 0; + off_t start_offset, loop_start_offset = 0; + + /* checks */ + if (!check_extensions(sf,"adm")) + return NULL; + + //TODO improve/move to .txth (block behavior must be handled in vgmstream though) + // - most blocks end with a 0x03 flag + 0x10 padding, then next blocks restarts with 0x06 flag + // - MTXADPCM.IRX reads a 0x400 L block then R block, doesn't seem to do any block handling + // - padded blocks don't seem consistent or depends on size/loop/etc: + // (but there seems to be 4 parts in looped files and 2 in non-looped) + // - MS_overture_lp.adm (loop offset 0x2B2000) + // - 0x000000~0x020000: padding (all blocks end with 0x03 flag + 0x10 padding) + // - 0x020000~0x2B2800: no padding (only last LR block ends with 0x03 flags) + // - 0x2B2800~0x2FA800: padding (all blocks) + // - 0x2FB000~0x442000: no padding + // - MS_saint.adm (loop offset 0x082000) + // - 0x000000~0x04E000: padding + // - 0x04E000~0x082800: no padding + // - 0x082800~0x0CF000: padding + // - 0x0CF000~0x40B000: no padding + // - MS_item.adm + // - 0x000000~0x016000: padding + // - 0x016000~0x01A000: no padding + // - possibly automatically handled by SPU2 + // - 0x03 flag > ends playback > immediately gets next block = no audio skips + + /* raw data, but test some .ADM blocks as they always start with PS-ADPCM flag 0x06 every 0x1000 */ + for (int i = 0; i < 10; i++) { + if (read_u8(0x1000 * i + 0x01, sf) != 0x06) + return NULL; + } + + start_offset = 0x00; + loop_flag = get_adm_loop_info(sf, &loop_start_offset); + channels = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + // TODO use info from header + vgmstream->meta_type = meta_PS2_ADM; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_adm; + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + + /* calc num_samples as playable data size varies between files/blocks */ + { + vgmstream->next_block_offset = start_offset; + do { + block_update(vgmstream->next_block_offset,vgmstream); + if (loop_flag && vgmstream->current_block_offset == loop_start_offset) + vgmstream->loop_start_sample = vgmstream->num_samples; + vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1); + } + while (vgmstream->next_block_offset < get_streamfile_size(sf)); + block_update(start_offset,vgmstream); + + if (loop_flag) + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* loops are not in the .ADM or .DAT bigfile containing them but in the exe; manually get them (a bit meh but whatevs) */ +static int get_adm_loop_info(STREAMFILE* sf, off_t *loop_start_offset) { + char file_name[PATH_LIMIT]; + char index_name[PATH_LIMIT]; + STREAMFILE *sh = NULL; + int i, name_index = -1, loop_flag; + off_t offset; + + sh = open_streamfile_by_filename(sf, "SLPM_655.55"); + if (!sh) goto fail; + + get_streamfile_filename(sf, file_name, PATH_LIMIT); + + /* get file index from name list (file_name == index_name = index number */ + offset = 0x23B3c0; + for (i = 0; i < 51; i++) { + read_string(index_name,0x20+1, offset,sh); + + if (strcmp(index_name, file_name)==0) { + name_index = i; + break; + } + offset += 0x20; + } + if (name_index < 0) + goto fail; + + /* get file info using index */ + offset = 0x23BAF0 + 0x1c * name_index; + loop_flag = (read_32bitLE(offset + 0x0c, sh) == 0); /* 1: don't loop, 0: loop */ + if (loop_flag) { /* loop flag */ + *loop_start_offset = read_32bitLE(offset + 0x00, sh); + } + + // 23BA20 = adpcm volumes? + // 23BAF0 = adpcm info + // 00: loop start offset + // 04: loop end (size) + // 08: sample rate + // 0c: loop flag (0=inf, 1=no loop) + // 10: loop start block (in 0x800 sizes) + // 14: loop length block (in 0x800 sizes) + // 18: null + + close_streamfile(sh); + return loop_flag; +fail: + close_streamfile(sh); + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c deleted file mode 100644 index 6fe656bb8..000000000 --- a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c +++ /dev/null @@ -1,51 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* .ASS - from Dai Senryaku VII: Exceed (PS2) */ -VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - size_t channel_size, interleave; - int loop_flag, channel_count, sample_rate; - int32_t num_samples, loop_start = 0, loop_end = 0; - - - /* checks */ - if (!check_extensions(streamFile, "ass")) - goto fail; - - start_offset = 0x800; - channel_count = read_32bitLE(0x00,streamFile); /* assumed */ - if (channel_count != 2) goto fail; - sample_rate = read_32bitLE(0x04,streamFile); - channel_size = read_32bitLE(0x08,streamFile); - interleave = read_32bitLE(0x0c,streamFile); - num_samples = ps_bytes_to_samples(channel_size,1); - - loop_flag = ps_find_loop_offsets(streamFile, start_offset, channel_size*channel_count, channel_count, interleave, &loop_start, &loop_end); - loop_flag = loop_flag && (num_samples > 10*sample_rate); /* disable looping for smaller files (in seconds) */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_PS2_ASS; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - - 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/psnd.c b/Frameworks/vgmstream/vgmstream/src/meta/psnd.c index bbf4119a5..cfee5fa67 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/psnd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/psnd.c @@ -12,7 +12,7 @@ VGMSTREAM* init_vgmstream_psnd(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "PSND")) return NULL; - /* .psn: actual extension in exes */ + /* .psn: actual extension in exes/bigfiles */ if (!check_extensions(sf, "psn")) return NULL; @@ -22,21 +22,23 @@ VGMSTREAM* init_vgmstream_psnd(STREAMFILE* sf) { switch (type) { case 0x0030006: /* CBNK */ - channels = read_u8(0xE,sf); - if (read_u8(0x0f, sf) != 16) goto fail; /* bps */ + channels = read_u8(0x0E,sf); + if (read_u8(0x0f, sf) != 16) // bps + goto fail; start_offset = 0x10; - break; + case 0x0000004: /* RR */ channels = 1; start_offset = 0x0e; break; + default: goto fail; } data_size = data_size + 0x08 - start_offset; - loop_flag = 0; /* generally 22050hz music loops */ + loop_flag = 0; // generally 22050hz music fully loops /* build the VGMSTREAM */ @@ -51,11 +53,16 @@ VGMSTREAM* init_vgmstream_psnd(STREAMFILE* sf) { vgmstream->interleave_block_size = 0x02; vgmstream->num_samples = pcm16_bytes_to_samples(data_size, channels); break; + case 0x0000004: - vgmstream->coding_type = coding_DVI_IMA; + vgmstream->coding_type = coding_DVI_IMA_mono; vgmstream->layout_type = layout_none; vgmstream->num_samples = ima_bytes_to_samples(data_size, channels); + + // Reckless Getaway 2 (Android), Xenowerk (Android) + vgmstream->allow_dual_stereo = true; break; + default: goto fail; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c index 0ddabbd6f..e4665fd23 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/riff.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -484,8 +484,9 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { * .se: Rockman X4 (PC) * .v: Rozen Maiden: Duellwalzer (PS2) * .xst: Animaniacs: The Great Edgar Hunt (Xbox) + * .wxv: Dariusburst (PSP) */ - if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus,dat,ldat,wma,lwma,caf,wax,voi,se,v,xst")) { + if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus,dat,ldat,wma,lwma,caf,wax,voi,se,v,xst,wxv")) { return NULL; } diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sk_aud.c b/Frameworks/vgmstream/vgmstream/src/meta/sk_aud.c index c39633c2f..f1fe1a6c3 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/sk_aud.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/sk_aud.c @@ -1,74 +1,73 @@ -#include "meta.h" -#include "../util.h" -#include "../coding/coding.h" - -static int get_sk_num_samples(STREAMFILE *streamFile, off_t start_offset); - -/* AUD/SK - Silicon Knights obfuscated Ogg (cutscene/voices) [Eternal Darkness (GC)] */ -VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count, sample_rate; - - /* check extension, case insensitive */ - if (!check_extensions(streamFile,"aud")) - goto fail; - - if (read_32bitBE(0x00,streamFile) != 0x11534B10) /* \11"SK"\10 */ - goto fail; - - /* the format is just mutant Ogg so actually peeking into the Vorbis id packet here */ - channel_count = read_8bit (0x23,streamFile); - sample_rate = read_32bitLE(0x24,streamFile); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = get_sk_num_samples(streamFile, 0); - vgmstream->meta_type = meta_SK_AUD; - -#ifdef VGM_USE_VORBIS - { - vorbis_custom_config cfg = {0}; - - vgmstream->layout_type = layout_none; - vgmstream->coding_type = coding_VORBIS_custom; - vgmstream->codec_data = init_vorbis_custom(streamFile, 0x00, VORBIS_SK, &cfg); - if (!vgmstream->codec_data) goto fail; - - start_offset = cfg.data_start_offset; - } -#else - goto fail; -#endif - - /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} - -/* SK/Ogg doesn't have num_samples info, manually read total samples */ -static int get_sk_num_samples(STREAMFILE *streamFile, off_t start_offset) { - uint32_t expected_id = 0x11534B10; /* \11"SK"\10 (would read "OggS" by changing the ID) */ - off_t off = get_streamfile_size(streamFile) - 4-1-1-8-4-4-4; - - /* simplest way is to find last OggS/SK page from stream end */ - while (off >= start_offset) { - uint32_t current_id = read_32bitBE(off, streamFile); - if (current_id == expected_id) { /* last packet starts with 0x0004, if more checks are needed */ - return read_32bitLE(off+4+1+1, streamFile); /* get last granule = total samples (64b but whatevs) */ - } - - off--; - } - - return 0; -} +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +static int32_t get_sk_num_samples(STREAMFILE* sf, off_t start_offset); + +/* SK (.AUD) - Silicon Knights obfuscated Ogg (cutscene/voices) [Eternal Darkness (GC)] */ +VGMSTREAM* init_vgmstream_sk_aud(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channels, sample_rate; + + /* checks */ + if (read_u32be(0x00,sf) != 0x11534B10) /* \11"SK"\10 */ + return NULL; + + if (!check_extensions(sf,"aud")) + return NULL; + + /* the format is just mutant Ogg so actually peeking into the Vorbis id packet here */ + channels = read_u8 (0x23,sf); + sample_rate = read_s32le(0x24,sf); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = get_sk_num_samples(sf, 0); + vgmstream->meta_type = meta_SK_AUD; + +#ifdef VGM_USE_VORBIS + { + vorbis_custom_config cfg = {0}; + + vgmstream->layout_type = layout_none; + vgmstream->coding_type = coding_VORBIS_custom; + vgmstream->codec_data = init_vorbis_custom(sf, 0x00, VORBIS_SK, &cfg); + if (!vgmstream->codec_data) goto fail; + + start_offset = cfg.data_start_offset; + } +#else + goto fail; +#endif + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; +fail: + close_vgmstream(vgmstream); + return NULL; +} + +// TODO: improve reads in blocks +/* SK/Ogg doesn't have num_samples info, manually read total samples */ +static int32_t get_sk_num_samples(STREAMFILE* sf, off_t start_offset) { + uint32_t expected_id = 0x11534B10; /* \11"SK"\10 (would read "OggS" by changing the ID) */ + off_t off = get_streamfile_size(sf) - 4-1-1-8-4-4-4; + + /* simplest way is to find last OggS/SK page from stream end */ + while (off >= start_offset) { + uint32_t current_id = read_u32be(off, sf); + if (current_id == expected_id) { /* last packet starts with 0x0004, if more checks are needed */ + return read_s32le(off+4+1+1, sf); /* get last granule = total samples (64b but whatevs) */ + } + + off--; + } + + return 0; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c b/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c index f21322a08..39bfb3783 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c @@ -1,110 +1,112 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* SPD+SPT - Nintendo bank (bgm or sfx) format [Bloodrayne (GC), 4x4 EVO 2 (GC), Table Tennis (Wii)] */ -VGMSTREAM * init_vgmstream_spt_spd(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *sf_h = NULL; - int channel_count, loop_flag, sample_rate; - off_t header_offset, extra_offset, start_offset; - int32_t loop_start, loop_end, stream_start, stream_end; - size_t stream_size; - uint32_t flags; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* checks */ - if (!check_extensions(streamFile, "spd")) - goto fail; - sf_h = open_streamfile_by_ext(streamFile, "spt"); - if (!sf_h) goto fail; - - /* ignore alt .spt+spd [Spyro: Enter the Dragonfly (GC)] */ - if (read_u16be(0x00, sf_h) != 0) /* always 0xA20C? */ - goto fail; - - total_subsongs = read_s32be(0x00, sf_h); - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - header_offset = 0x04 + 0x1c * (target_subsong-1); - extra_offset = 0x04 + 0x1c * total_subsongs + 0x2e * (target_subsong-1); - - flags = read_u32be(header_offset + 0x00, sf_h); - sample_rate = read_s32be(header_offset + 0x04, sf_h); - loop_start = read_s32be(header_offset + 0x08, sf_h); - loop_end = read_s32be(header_offset + 0x0c, sf_h); - stream_end = read_s32be(header_offset + 0x10, sf_h); - stream_start = read_s32be(header_offset + 0x14, sf_h); - /* 0x18: null */ - - channel_count = 1; - loop_flag = (flags & 1); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_SPT_SPD; - vgmstream->allow_dual_stereo = 1; - vgmstream->sample_rate = sample_rate; - vgmstream->layout_type = layout_none; - - vgmstream->num_streams = total_subsongs; - - switch(flags & (~1)) { /* bitflags */ - case 0: /* common */ - /* values in file nibbles? */ - start_offset = (stream_start / 2 - 1); - stream_size = (stream_end / 2 + 1) - (stream_start / 2 - 1); - if (loop_flag) { - loop_start = (loop_start / 2 - 1) - start_offset; - loop_end = (loop_end / 2 + 1) - start_offset; - } - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channel_count); - if (loop_flag) { - vgmstream->loop_start_sample = dsp_bytes_to_samples(loop_start, channel_count); - vgmstream->loop_end_sample = dsp_bytes_to_samples(loop_end, channel_count); - } - dsp_read_coefs_be(vgmstream, sf_h, extra_offset + 0x00, 0x00); - dsp_read_hist_be (vgmstream, sf_h, extra_offset + 0x24, 0x00); - break; - - case 2: /* rare [Monster Jam: Maximum Destruction (GC)] */ - /* values in samples? */ - start_offset = (stream_start * 2); - stream_size = (stream_end * 2) - (stream_start * 2); - if (loop_flag) { - loop_start = (loop_start * 2) - start_offset; - loop_end = (loop_end * 2) - start_offset; - } - - vgmstream->coding_type = coding_PCM16BE; - vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); - if (loop_flag) { - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; - } - break; - - case 4: /* supposedly PCM8 */ - default: - goto fail; - } - - vgmstream->stream_size = stream_size; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - close_streamfile(sf_h); - return vgmstream; - -fail: - close_streamfile(sf_h); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* .SPT+SPD - Nintendo bank (bgm or sfx) [Bloodrayne (GC), 4x4 EVO 2 (GC), Table Tennis (Wii)] */ +VGMSTREAM* init_vgmstream_spt_spd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + int channels, loop_flag, sample_rate; + off_t header_offset, extra_offset, start_offset; + int32_t loop_start, loop_end, stream_start, stream_end; + size_t stream_size; + uint32_t flags; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + total_subsongs = read_s32be(0x00, sf); + // ignores alt .spt+spd that start with 0xA20C [Spyro: Enter the Dragonfly (GC)] + if (total_subsongs < 0 || total_subsongs > 0xFFFF) + return NULL; + + if (!check_extensions(sf, "spt")) + return NULL; + + sb = open_streamfile_by_ext(sf, "spd"); + if (!sb) return NULL; + + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + header_offset = 0x04 + 0x1c * (target_subsong-1); + extra_offset = 0x04 + 0x1c * total_subsongs + 0x2e * (target_subsong - 1); + + flags = read_u32be(header_offset + 0x00, sf); + sample_rate = read_s32be(header_offset + 0x04, sf); + loop_start = read_s32be(header_offset + 0x08, sf); + loop_end = read_s32be(header_offset + 0x0c, sf); + stream_end = read_s32be(header_offset + 0x10, sf); + stream_start = read_s32be(header_offset + 0x14, sf); + // 0x18: null + + channels = 1; + loop_flag = (flags & 1); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SPT_SPD; + vgmstream->allow_dual_stereo = 1; + vgmstream->sample_rate = sample_rate; + vgmstream->layout_type = layout_none; + + vgmstream->num_streams = total_subsongs; + + switch(flags & (~1)) { /* bitflags */ + case 0: /* common */ + /* values in file nibbles? */ + start_offset = (stream_start / 2 - 1); + stream_size = (stream_end / 2 + 1) - (stream_start / 2 - 1); + if (loop_flag) { + loop_start = (loop_start / 2 - 1) - start_offset; + loop_end = (loop_end / 2 + 1) - start_offset; + } + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channels); + if (loop_flag) { + vgmstream->loop_start_sample = dsp_bytes_to_samples(loop_start, channels); + vgmstream->loop_end_sample = dsp_bytes_to_samples(loop_end, channels); + } + + dsp_read_coefs_be(vgmstream, sf, extra_offset + 0x00, 0x00); + dsp_read_hist_be (vgmstream, sf, extra_offset + 0x24, 0x00); + break; + + case 2: /* rare [Monster Jam: Maximum Destruction (GC)] */ + /* values in samples? */ + start_offset = (stream_start * 2); + stream_size = (stream_end * 2) - (stream_start * 2); + if (loop_flag) { + loop_start = (loop_start * 2) - start_offset; + loop_end = (loop_end * 2) - start_offset; + } + + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channels, 16); + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + } + break; + + case 4: /* supposedly PCM8 */ + default: + goto fail; + } + + vgmstream->stream_size = stream_size; + + if (!vgmstream_open_stream(vgmstream, sb, start_offset)) + goto fail; + close_streamfile(sb); + return vgmstream; + +fail: + close_streamfile(sb); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sre_pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/sre_pcm.c new file mode 100644 index 000000000..a13d975e0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sre_pcm.c @@ -0,0 +1,68 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* .SRE+PCM. - Capcom's header+data container thing [Viewtiful Joe (PS2)] */ +VGMSTREAM* init_vgmstream_sre_pcm(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + off_t start_offset; + int loop_flag, channels; + int table1_entries, table2_entries; + uint32_t table1_offset, table2_offset; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + table1_entries = read_s32le(0x00, sf); + if (table1_entries <= 0 || table1_entries >= 0x100) //arbitrary max + return NULL; + table1_offset = read_u32le(0x04, sf); + table2_entries = read_s32le(0x08, sf); + table2_offset = read_u32le(0x0c, sf); + if (table1_entries * 0x60 + table1_offset != table2_offset) + return NULL; + + if (!check_extensions(sf, "sre")) + return NULL; + + total_subsongs = table2_entries; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) + return NULL; + + uint32_t header_offset = table2_offset + (target_subsong - 1) * 0x20; + + channels = read_s32le(header_offset+0x00,sf); + loop_flag = read_s32le(header_offset+0x18,sf); + start_offset = read_u32le(header_offset+0x08,sf); + + sb = open_streamfile_by_ext(sf, "pcm"); + if (!sb) goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_u16le(header_offset+0x04,sf); + vgmstream->meta_type = meta_SRE_PCM; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1000; + + vgmstream->num_samples = ps_bytes_to_samples(read_u32le(header_offset+0x0c,sf), channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(read_u32le(header_offset+0x10,sf), 1); + vgmstream->loop_end_sample = ps_bytes_to_samples(read_u32le(header_offset+0x14,sf), 1); + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = read_u32le(header_offset+0x0c,sf); + + if (!vgmstream_open_stream(vgmstream,sb,start_offset)) + goto fail; + close_streamfile(sb); + return vgmstream; +fail: + close_streamfile(sb); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vab.c b/Frameworks/vgmstream/vgmstream/src/meta/vab.c index 5839747ee..1b85d7f57 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vab.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vab.c @@ -159,6 +159,7 @@ VGMSTREAM* init_vgmstream_vab(STREAMFILE* sf) { } pitch = SsPitchFromNote(note, fine, center, shift); + if (pitch > 0x4000) pitch = 0x4000; /* SPU clamp */ data_offset = is_vh ? 0x00 : (waves_off + 256 * 0x02); for (i = 0; i < wave_num; i++) { diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vgs_ps.c b/Frameworks/vgmstream/vgmstream/src/meta/vgs_ps.c index 221213bc5..39eea4a68 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/vgs_ps.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/vgs_ps.c @@ -11,10 +11,10 @@ VGMSTREAM* init_vgmstream_vgs_ps(STREAMFILE* sf) { /* check */ - if (!check_extensions(sf,"vgs")) - goto fail; if (!is_id32be(0x00,sf, "VGS\0")) /* 'VAG stereo', presumably (simple VAG clone) */ - goto fail; + return NULL; + if (!check_extensions(sf,"vgs")) + return NULL; start_offset = 0x30; data_size = get_streamfile_size(sf) - start_offset; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wsi.c b/Frameworks/vgmstream/vgmstream/src/meta/wsi.c index 3f02260de..d5e4bf4a8 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/wsi.c +++ b/Frameworks/vgmstream/vgmstream/src/meta/wsi.c @@ -1,83 +1,83 @@ -#include "meta.h" -#include "../coding/coding.h" - - -/* .wsi - blocked dsp [Alone in the Dark (Wii)] */ -VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, header_offset; - size_t header_spacing; - int loop_flag, channel_count; - - - /* checks */ - if (!check_extensions(streamFile, "wsi")) - goto fail; - - channel_count = read_32bitBE(0x04,streamFile); - if (channel_count != 2) goto fail; /* assumed */ - - /* check for consistent block headers */ - { - off_t block_offset; - off_t block_size_has_been; - int i; - - block_offset = read_32bitBE(0x00,streamFile); - if (block_offset < 0x08) goto fail; - - block_size_has_been = block_offset; - - /* check 4 blocks, to get an idea */ - for (i = 0; i < 4*channel_count; i++) { - off_t block_size = read_32bitBE(block_offset,streamFile); - - if (block_size < 0x10) - goto fail; /* expect at least the block header */ - if (i%channel_count+1 != read_32bitBE(block_offset+0x08,streamFile)) - goto fail; /* expect the channel numbers to alternate */ - - if (i%channel_count==0) - block_size_has_been = block_size; - else if (block_size != block_size_has_been) - goto fail; /* expect every block in a set of channels to have the same size */ - - block_offset += block_size; - } - } - - start_offset = read_32bitBE(0x00, streamFile); - header_offset = start_offset + 0x10; - header_spacing = read_32bitBE(start_offset,streamFile); - - /* contains standard DSP header, but since it's blocked validations (start/loop ps, etc) - * will fail, so no point to handle as standard DSP */ - loop_flag = read_16bitBE(header_offset+0x0c,streamFile); - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_DSP_WSI; - vgmstream->sample_rate = read_32bitBE(header_offset+0x08,streamFile); - - vgmstream->num_samples = read_32bitBE(header_offset+0x00,streamFile) / 14 * 14; /* remove incomplete last frame */ - vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(header_offset+0x10,streamFile)); - vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bitBE(header_offset+0x14,streamFile))+1; - if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_blocked_wsi; - dsp_read_coefs_be(vgmstream, streamFile, header_offset+0x1c, header_spacing); - dsp_read_hist_be(vgmstream, streamFile, header_offset+0x40, header_spacing); - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* .wsi - blocked dsp [Alone in the Dark (Wii)] */ +VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset, header_offset; + size_t header_spacing; + int loop_flag, channel_count; + + + /* checks */ + if (!check_extensions(streamFile, "wsi")) + goto fail; + + channel_count = read_32bitBE(0x04,streamFile); + if (channel_count != 2) goto fail; /* assumed */ + + /* check for consistent block headers */ + { + off_t block_offset; + off_t block_size_has_been; + int i; + + block_offset = read_32bitBE(0x00,streamFile); + if (block_offset < 0x08) goto fail; + + block_size_has_been = block_offset; + + /* check 4 blocks, to get an idea */ + for (i = 0; i < 4*channel_count; i++) { + off_t block_size = read_32bitBE(block_offset,streamFile); + + if (block_size < 0x10) + goto fail; /* expect at least the block header */ + if (i%channel_count+1 != read_32bitBE(block_offset+0x08,streamFile)) + goto fail; /* expect the channel numbers to alternate */ + + if (i%channel_count==0) + block_size_has_been = block_size; + else if (block_size != block_size_has_been) + goto fail; /* expect every block in a set of channels to have the same size */ + + block_offset += block_size; + } + } + + start_offset = read_32bitBE(0x00, streamFile); + header_offset = start_offset + 0x10; + header_spacing = read_32bitBE(start_offset,streamFile); + + /* contains standard DSP header, but since it's blocked validations (start/loop ps, etc) + * will fail, so no point to handle as standard DSP */ + loop_flag = read_16bitBE(header_offset+0x0c,streamFile); + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_DSP_WSI; + vgmstream->sample_rate = read_32bitBE(header_offset+0x08,streamFile); + + vgmstream->num_samples = read_32bitBE(header_offset+0x00,streamFile) / 14 * 14; /* remove incomplete last frame */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(header_offset+0x10,streamFile)); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bitBE(header_offset+0x14,streamFile))+1; + if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_blocked_wsi; + dsp_read_coefs_be(vgmstream, streamFile, header_offset+0x1c, header_spacing); + dsp_read_hist_be(vgmstream, streamFile, header_offset+0x40, header_spacing); + + 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/vgmstream_init.c b/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c index b98fc8b94..2c36a2fd8 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream_init.c @@ -45,7 +45,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_sfl_ogg, init_vgmstream_sadb, init_vgmstream_ps2_bmdx, - init_vgmstream_wsi, init_vgmstream_aifc, init_vgmstream_str_snds, init_vgmstream_ws_aud, @@ -57,6 +56,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_nwa, init_vgmstream_ea_1snh, init_vgmstream_ea_eacs, + init_vgmstream_ea_crdf, init_vgmstream_xss, init_vgmstream_sl3, init_vgmstream_hgc1, @@ -102,21 +102,17 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_sadl, init_vgmstream_fag, init_vgmstream_mic, - init_vgmstream_ngc_pdt_split, - init_vgmstream_ngc_pdt, init_vgmstream_mus_krome, init_vgmstream_spsd, init_vgmstream_rsd, init_vgmstream_bgw, init_vgmstream_spw, - init_vgmstream_ps2_ass, init_vgmstream_ubi_jade, init_vgmstream_ubi_jade_container, init_vgmstream_seg, init_vgmstream_riff_ima, init_vgmstream_knon, init_vgmstream_gca, - init_vgmstream_spt_spd, init_vgmstream_ish_isd, init_vgmstream_gsnd, init_vgmstream_ydsp, @@ -154,7 +150,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_dsp_kceje, init_vgmstream_gcub, init_vgmstream_maxis_xa, - init_vgmstream_ngc_sck_dsp, init_vgmstream_apple_caff, init_vgmstream_pc_mxst, init_vgmstream_sab, @@ -255,6 +250,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_xa_xa30, init_vgmstream_xa_04sw, init_vgmstream_ea_bnk, + init_vgmstream_ea_bnk_fixed, init_vgmstream_ea_abk_schl, init_vgmstream_ea_amb_schl, init_vgmstream_ea_hdr_dat, @@ -263,6 +259,8 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ea_mpf_mus_schl, init_vgmstream_ea_msb_mus_schl, init_vgmstream_ea_schl_fixed, + init_vgmstream_ea_patl, + init_vgmstream_ea_pt, init_vgmstream_sk_aud, init_vgmstream_stma, init_vgmstream_ea_snu, @@ -295,7 +293,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ea_sbr, init_vgmstream_ea_sbr_harmony, init_vgmstream_vid1, - init_vgmstream_flx, init_vgmstream_mogg, init_vgmstream_kma9, init_vgmstream_xwc, @@ -311,7 +308,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ea_wve_au00, init_vgmstream_ea_wve_ad10, init_vgmstream_sthd, - init_vgmstream_pcm_sre, init_vgmstream_dsp_mcadpcm, init_vgmstream_ubi_lyn, init_vgmstream_ubi_lyn_container, @@ -541,6 +537,11 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_imc_container, init_vgmstream_wv6, init_vgmstream_smh_smc, + init_vgmstream_flx, + init_vgmstream_pdt, + init_vgmstream_spt_spd, + init_vgmstream_wsi, + init_vgmstream_sre_pcm, /* need companion files */ init_vgmstream_pos, init_vgmstream_sli_loops, @@ -562,6 +563,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_exakt_sc, /* .sc raw PCM */ init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */ init_vgmstream_rwsd, /* crap, to be removed */ + init_vgmstream_pdt_split, /* fake format */ #ifdef VGM_USE_FFMPEG init_vgmstream_ffmpeg, /* may play anything incorrectly, since FFmpeg doesn't check extensions */ #endif diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h b/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h index 0b23bb92d..a1cccb23a 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream_types.h @@ -376,11 +376,10 @@ typedef enum { meta_SADL, meta_FAG, /* Jackie Chan - Stuntmaster */ meta_MIC, - meta_NGC_PDT, /* Mario Party 6 */ + meta_PDT, meta_ASD_NAXAT, meta_SPSD, meta_RSD, - meta_PS2_ASS, meta_SEG, meta_RIFF_IMA, meta_KNON, @@ -400,7 +399,8 @@ typedef enum { meta_XMU, meta_EA_SCHL, /* Electronic Arts SCHl with variable header */ meta_EA_SCHL_fixed, /* Electronic Arts SCHl with fixed header */ - meta_EA_BNK, /* Electronic Arts BNK */ + meta_EA_BNK, /* Electronic Arts BNK with variable header */ + meta_EA_BNK_fixed, /* Electronic Arts BNK with fixed header */ meta_EA_1SNH, /* Electronic Arts 1SNh/EACS */ meta_EA_EACS, meta_RAW_PCM, @@ -446,9 +446,8 @@ typedef enum { meta_2DX9, meta_VGV, meta_GCUB, - meta_MAXIS_XA, /* Sim City 3000 (PC) */ - meta_NGC_SCK_DSP, /* Scorpion King (NGC) */ - meta_CAFF, /* iPhone .caf */ + meta_MAXIS_XA, + meta_CAFF, meta_EXAKT_SC, /* Activision EXAKT .SC (PS2) */ meta_WII_WAS, /* DiRT 2 (WII) */ meta_PONA_3DO, /* Policenauts (3DO) */ @@ -576,7 +575,7 @@ typedef enum { meta_EA_WVE_AD10, /* Electronic Arts PS movies [Wing Commander 3/4 (PS)] */ meta_STHD, /* STHD .stx [Kakuto Chojin (Xbox)] */ meta_MP4, /* MP4/AAC */ - meta_PCM_SRE, /* .PCM+SRE [Viewtiful Joe (PS2)] */ + meta_SRE_PCM, meta_DSP_MCADPCM, /* Skyrim (Switch) */ meta_UBI_LYN, /* Ubisoft LyN engine [The Adventures of Tintin (multi)] */ meta_MSB_MSH, /* sfx companion of MIH+MIB */ diff --git a/Info.plist.template b/Info.plist.template index 4a0904033..ecea558f4 100644 --- a/Info.plist.template +++ b/Info.plist.template @@ -401,7 +401,6 @@ asd asf asr - ass ast at3 at9 @@ -419,6 +418,7 @@ awb awc awd + awx b1s baf baka @@ -438,6 +438,7 @@ bik2 binka bk2 + bkh bkr blk bmdx @@ -470,11 +471,14 @@ cnk cpk cps + crd csa csb csmp cvs cwav + cxb + cxk cxs d2 da @@ -489,12 +493,14 @@ dic diva dmsg + drm ds2 dsb dsf dsp dspw dtk + dty dvi dyx e4x @@ -656,13 +662,14 @@ mds mdsp med - mhwk + mhk mjb mi4 mib mic mio mogg + mon move mpdsp mpds @@ -745,6 +752,7 @@ psf psh psn + pth pwb qwv r @@ -846,19 +854,22 @@ snz sod son - spd + spc + sph + spt spm sps spsd spw - srsa srcd + sre + srsa ss2 ssd ssf ssm - sspr ssp + sspr sss ster sth @@ -973,6 +984,7 @@ wvs wvx wxd + wxv x x360audio xa