diff --git a/Cog.xcodeproj/project.pbxproj b/Cog.xcodeproj/project.pbxproj index bc8d72d6f..0ef20636d 100644 --- a/Cog.xcodeproj/project.pbxproj +++ b/Cog.xcodeproj/project.pbxproj @@ -141,6 +141,7 @@ 8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; }; 8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; }; 836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; }; + 836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836F6B2E18BDB80E0095E648 /* vgmstream.bundle */; }; 836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB5471820538800B3AD2D /* Hively.bundle */; }; 8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; }; 83790D501809F4980073CF51 /* NSObject+SPInvocationGrabbing.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */; }; @@ -434,6 +435,13 @@ remoteGlobalIDString = 8360EEE417F92AC8005208A4; remoteInfo = HighlyComplete; }; + 836F6B2D18BDB80E0095E648 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 836F6B1018BDB80D0095E648; + remoteInfo = vgmstream; + }; 836FB5461820538800B3AD2D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 836FB5421820538700B3AD2D /* Hively.xcodeproj */; @@ -620,6 +628,7 @@ dstPath = ""; dstSubfolderSpec = 13; files = ( + 836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */, 836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */, 83A0F4E31816DBF900119DB4 /* playptmod.bundle in CopyFiles */, 83B06704180D579E008E3612 /* MIDI.bundle in CopyFiles */, @@ -866,6 +875,7 @@ 8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = ""; }; 836D28A618086386005B7299 /* MiniModeMenuTitleTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MiniModeMenuTitleTransformer.h; path = Window/MiniModeMenuTitleTransformer.h; sourceTree = ""; }; 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MiniModeMenuTitleTransformer.m; path = Window/MiniModeMenuTitleTransformer.m; sourceTree = ""; }; + 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vgmstream.xcodeproj; path = Plugins/vgmstream/vgmstream.xcodeproj; sourceTree = ""; }; 836FB5421820538700B3AD2D /* Hively.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Hively.xcodeproj; path = Plugins/Hively/Hively.xcodeproj; sourceTree = ""; }; 8375B05117FFEA400092A79F /* Opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Opus.xcodeproj; path = Plugins/Opus/Opus.xcodeproj; sourceTree = ""; }; 83790D4C1809F4980073CF51 /* NSObject+SPInvocationGrabbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SPInvocationGrabbing.h"; sourceTree = ""; }; @@ -1221,6 +1231,7 @@ 83B0669C180D5668008E3612 /* MIDI.xcodeproj */, 83A0F4841816CE5E00119DB4 /* playptmod.xcodeproj */, 836FB5421820538700B3AD2D /* Hively.xcodeproj */, + 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */, ); name = PlugIns; sourceTree = ""; @@ -1551,6 +1562,14 @@ name = Products; sourceTree = ""; }; + 836F6B2618BDB80D0095E648 /* Products */ = { + isa = PBXGroup; + children = ( + 836F6B2E18BDB80E0095E648 /* vgmstream.bundle */, + ); + name = Products; + sourceTree = ""; + }; 836FB5431820538700B3AD2D /* Products */ = { isa = PBXGroup; children = ( @@ -1908,6 +1927,10 @@ ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */; ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */; }, + { + ProductGroup = 836F6B2618BDB80D0095E648 /* Products */; + ProjectRef = 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */; + }, { ProductGroup = 17C808B80C3BD1D2005707C4 /* Products */; ProjectRef = 17C808B70C3BD1D2005707C4 /* Vorbis.xcodeproj */; @@ -2044,6 +2067,13 @@ remoteRef = 8360EF0417F92B24005208A4 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 836F6B2E18BDB80E0095E648 /* vgmstream.bundle */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = vgmstream.bundle; + remoteRef = 836F6B2D18BDB80E0095E648 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 836FB5471820538800B3AD2D /* Hively.bundle */ = { isa = PBXReferenceProxy; fileType = wrapper.cfbundle; diff --git a/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj new file mode 100644 index 000000000..6147efc5b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -0,0 +1,1564 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B4518BDB8880095E648 /* InfoPlist.strings */; }; + 836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE018BDC2180095E648 /* acm_decoder.c */; }; + 836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6DE118BDC2180095E648 /* acm_decoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE218BDC2180095E648 /* adx_decoder.c */; }; + 836F6F2118BDC2190095E648 /* aica_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE318BDC2180095E648 /* aica_decoder.c */; }; + 836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE418BDC2180095E648 /* at3_decoder.c */; }; + 836F6F2318BDC2190095E648 /* coding.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6DE518BDC2180095E648 /* coding.h */; }; + 836F6F2418BDC2190095E648 /* eaxa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE618BDC2180095E648 /* eaxa_decoder.c */; }; + 836F6F2518BDC2190095E648 /* g721_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE718BDC2180095E648 /* g721_decoder.c */; }; + 836F6F2618BDC2190095E648 /* g7221_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DE818BDC2180095E648 /* g7221_decoder.c */; }; + 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6DE918BDC2180095E648 /* g72x_state.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DEA18BDC2180095E648 /* ima_decoder.c */; }; + 836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DEB18BDC2180095E648 /* l5_555_decoder.c */; }; + 836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DEC18BDC2180095E648 /* lsf_decoder.c */; }; + 836F6F2B18BDC2190095E648 /* Makefile.unix.am in Resources */ = {isa = PBXBuildFile; fileRef = 836F6DED18BDC2180095E648 /* Makefile.unix.am */; }; + 836F6F2C18BDC2190095E648 /* mp4_aac_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DEE18BDC2180095E648 /* mp4_aac_decoder.c */; }; + 836F6F2D18BDC2190095E648 /* mpeg_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DEF18BDC2180095E648 /* mpeg_decoder.c */; }; + 836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF018BDC2180095E648 /* msadpcm_decoder.c */; }; + 836F6F2F18BDC2190095E648 /* mtaf_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF118BDC2180095E648 /* mtaf_decoder.c */; }; + 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF218BDC2180095E648 /* nds_procyon_decoder.c */; }; + 836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF318BDC2180095E648 /* ngc_afc_decoder.c */; }; + 836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF418BDC2180095E648 /* ngc_dsp_decoder.c */; }; + 836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF518BDC2180095E648 /* ngc_dtk_decoder.c */; }; + 836F6F3418BDC2190095E648 /* nwa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF618BDC2180095E648 /* nwa_decoder.c */; }; + 836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6DF718BDC2180095E648 /* nwa_decoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF818BDC2180095E648 /* ogg_vorbis_decoder.c */; }; + 836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DF918BDC2180095E648 /* pcm_decoder.c */; }; + 836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DFA18BDC2180095E648 /* psx_decoder.c */; }; + 836F6F3918BDC2190095E648 /* SASSC_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DFB18BDC2180095E648 /* SASSC_decoder.c */; }; + 836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DFC18BDC2180095E648 /* sdx2_decoder.c */; }; + 836F6F3B18BDC2190095E648 /* ws_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DFD18BDC2180095E648 /* ws_decoder.c */; }; + 836F6F3C18BDC2190095E648 /* xa_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6DFE18BDC2180095E648 /* xa_decoder.c */; }; + 836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0018BDC2180095E648 /* aax_layout.c */; }; + 836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0118BDC2180095E648 /* aix_layout.c */; }; + 836F6F3F18BDC2190095E648 /* ast_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0218BDC2180095E648 /* ast_blocked.c */; }; + 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0318BDC2180095E648 /* bdsp_blocked.c */; }; + 836F6F4118BDC2190095E648 /* blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0418BDC2180095E648 /* blocked.c */; }; + 836F6F4218BDC2190095E648 /* caf_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0518BDC2180095E648 /* caf_blocked.c */; }; + 836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0618BDC2180095E648 /* de2_blocked.c */; }; + 836F6F4418BDC2190095E648 /* ea_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0718BDC2180095E648 /* ea_block.c */; }; + 836F6F4518BDC2190095E648 /* emff_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0818BDC2180095E648 /* emff_blocked.c */; }; + 836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0918BDC2180095E648 /* filp_blocked.c */; }; + 836F6F4718BDC2190095E648 /* gsb_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0A18BDC2180095E648 /* gsb_blocked.c */; }; + 836F6F4818BDC2190095E648 /* halpst_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0B18BDC2180095E648 /* halpst_blocked.c */; }; + 836F6F4918BDC2190095E648 /* ims_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0C18BDC2180095E648 /* ims_block.c */; }; + 836F6F4A18BDC2190095E648 /* interleave.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0D18BDC2180095E648 /* interleave.c */; }; + 836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0E18BDC2180095E648 /* interleave_byte.c */; }; + 836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E0F18BDC2180095E648 /* ivaud_layout.c */; }; + 836F6F4D18BDC2190095E648 /* layout.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6E1018BDC2180095E648 /* layout.h */; }; + 836F6F4E18BDC2190095E648 /* Makefile.unix.am in Resources */ = {isa = PBXBuildFile; fileRef = 836F6E1118BDC2180095E648 /* Makefile.unix.am */; }; + 836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1218BDC2180095E648 /* mus_acm_layout.c */; }; + 836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1318BDC2180095E648 /* mxch_blocked.c */; }; + 836F6F5118BDC2190095E648 /* nolayout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1418BDC2180095E648 /* nolayout.c */; }; + 836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */; }; + 836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */; }; + 836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */; }; + 836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */; }; + 836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1918BDC2180095E648 /* scd_int_layout.c */; }; + 836F6F5718BDC2190095E648 /* str_snds_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */; }; + 836F6F5818BDC2190095E648 /* thp_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1B18BDC2180095E648 /* thp_blocked.c */; }; + 836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1C18BDC2180095E648 /* tra_blocked.c */; }; + 836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1D18BDC2180095E648 /* vs_blocked.c */; }; + 836F6F5B18BDC2190095E648 /* ws_aud_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1E18BDC2180095E648 /* ws_aud_blocked.c */; }; + 836F6F5C18BDC2190095E648 /* wsi_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E1F18BDC2180095E648 /* wsi_blocked.c */; }; + 836F6F5D18BDC2190095E648 /* xa_blocked.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2018BDC2180095E648 /* xa_blocked.c */; }; + 836F6F5E18BDC2190095E648 /* xvas_block.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2118BDC2180095E648 /* xvas_block.c */; }; + 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2918BDC2180095E648 /* 2dx9.c */; }; + 836F6F6618BDC2190095E648 /* aax.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2A18BDC2180095E648 /* aax.c */; }; + 836F6F6718BDC2190095E648 /* acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2B18BDC2180095E648 /* acm.c */; }; + 836F6F6818BDC2190095E648 /* ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2C18BDC2180095E648 /* ads.c */; }; + 836F6F6918BDC2190095E648 /* adx_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2D18BDC2180095E648 /* adx_header.c */; }; + 836F6F6A18BDC2190095E648 /* afc_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2E18BDC2180095E648 /* afc_header.c */; }; + 836F6F6B18BDC2190095E648 /* agsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E2F18BDC2180095E648 /* agsc.c */; }; + 836F6F6C18BDC2190095E648 /* ahx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3018BDC2180095E648 /* ahx.c */; }; + 836F6F6D18BDC2190095E648 /* aifc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3118BDC2180095E648 /* aifc.c */; }; + 836F6F6E18BDC2190095E648 /* aix.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3218BDC2180095E648 /* aix.c */; }; + 836F6F6F18BDC2190095E648 /* akb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3318BDC2180095E648 /* akb.c */; }; + 836F6F7018BDC2190095E648 /* apple_caff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3418BDC2180095E648 /* apple_caff.c */; }; + 836F6F7118BDC2190095E648 /* ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3518BDC2180095E648 /* ast.c */; }; + 836F6F7218BDC2190095E648 /* baf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3618BDC2180095E648 /* baf.c */; }; + 836F6F7318BDC2190095E648 /* bcstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3718BDC2180095E648 /* bcstm.c */; }; + 836F6F7418BDC2190095E648 /* bgw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3818BDC2180095E648 /* bgw.c */; }; + 836F6F7518BDC2190095E648 /* bnsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3918BDC2180095E648 /* bnsf.c */; }; + 836F6F7618BDC2190095E648 /* brstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3A18BDC2180095E648 /* brstm.c */; }; + 836F6F7718BDC2190095E648 /* capdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3B18BDC2180095E648 /* capdsp.c */; }; + 836F6F7818BDC2190095E648 /* Cstr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3C18BDC2180095E648 /* Cstr.c */; }; + 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3D18BDC2180095E648 /* dc_asd.c */; }; + 836F6F7A18BDC2190095E648 /* dc_dcsw_dcs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3E18BDC2180095E648 /* dc_dcsw_dcs.c */; }; + 836F6F7B18BDC2190095E648 /* dc_idvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E3F18BDC2180095E648 /* dc_idvi.c */; }; + 836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4018BDC2180095E648 /* dc_kcey.c */; }; + 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4118BDC2180095E648 /* dc_str.c */; }; + 836F6F7E18BDC2190095E648 /* de2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4218BDC2180095E648 /* de2.c */; }; + 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4318BDC2180095E648 /* dmsg_segh.c */; }; + 836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4418BDC2180095E648 /* dsp_bdsp.c */; }; + 836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4518BDC2180095E648 /* dsp_sth_str.c */; }; + 836F6F8218BDC2190095E648 /* ea_header.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4618BDC2180095E648 /* ea_header.c */; }; + 836F6F8318BDC2190095E648 /* ea_old.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4718BDC2180095E648 /* ea_old.c */; }; + 836F6F8418BDC2190095E648 /* emff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4818BDC2180095E648 /* emff.c */; }; + 836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4918BDC2180095E648 /* exakt_sc.c */; }; + 836F6F8618BDC2190095E648 /* excitebots.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4A18BDC2180095E648 /* excitebots.c */; }; + 836F6F8718BDC2190095E648 /* ffw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4B18BDC2180095E648 /* ffw.c */; }; + 836F6F8818BDC2190095E648 /* fsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4C18BDC2180095E648 /* fsb.c */; }; + 836F6F8918BDC2190095E648 /* gca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4D18BDC2180095E648 /* gca.c */; }; + 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4E18BDC2180095E648 /* gcsw.c */; }; + 836F6F8B18BDC2190095E648 /* genh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E4F18BDC2180095E648 /* genh.c */; }; + 836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5018BDC2180095E648 /* gh3_bar.c */; }; + 836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5118BDC2180095E648 /* gsp_gsb.c */; }; + 836F6F8E18BDC2190095E648 /* halpst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5218BDC2180095E648 /* halpst.c */; }; + 836F6F8F18BDC2190095E648 /* his.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5318BDC2180095E648 /* his.c */; }; + 836F6F9018BDC2190095E648 /* idsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5418BDC2180095E648 /* idsp.c */; }; + 836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5518BDC2180095E648 /* ios_psnd.c */; }; + 836F6F9218BDC2190095E648 /* ish_isd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5618BDC2180095E648 /* ish_isd.c */; }; + 836F6F9318BDC2190095E648 /* ivaud.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5718BDC2180095E648 /* ivaud.c */; }; + 836F6F9418BDC2190095E648 /* ivb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5818BDC2180095E648 /* ivb.c */; }; + 836F6F9518BDC2190095E648 /* kraw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5918BDC2180095E648 /* kraw.c */; }; + 836F6F9618BDC2190095E648 /* lsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5A18BDC2180095E648 /* lsf.c */; }; + 836F6F9718BDC2190095E648 /* Makefile.unix.am in Resources */ = {isa = PBXBuildFile; fileRef = 836F6E5B18BDC2180095E648 /* Makefile.unix.am */; }; + 836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */; }; + 836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5D18BDC2180095E648 /* maxis_xa.c */; }; + 836F6F9A18BDC2190095E648 /* meta.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6E5E18BDC2180095E648 /* meta.h */; }; + 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E5F18BDC2180095E648 /* mn_str.c */; }; + 836F6F9C18BDC2190095E648 /* mp4.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6018BDC2180095E648 /* mp4.c */; }; + 836F6F9D18BDC2190095E648 /* msvp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6118BDC2180095E648 /* msvp.c */; }; + 836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6218BDC2180095E648 /* mus_acm.c */; }; + 836F6F9F18BDC2190095E648 /* musc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6318BDC2180095E648 /* musc.c */; }; + 836F6FA018BDC2190095E648 /* musx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6418BDC2180095E648 /* musx.c */; }; + 836F6FA118BDC2190095E648 /* myspd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6518BDC2180095E648 /* myspd.c */; }; + 836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6618BDC2180095E648 /* naomi_adpcm.c */; }; + 836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6718BDC2180095E648 /* naomi_spsd.c */; }; + 836F6FA418BDC2190095E648 /* nds_hwas.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6818BDC2180095E648 /* nds_hwas.c */; }; + 836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6918BDC2180095E648 /* nds_rrds.c */; }; + 836F6FA618BDC2190095E648 /* nds_sad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6A18BDC2180095E648 /* nds_sad.c */; }; + 836F6FA718BDC2190095E648 /* nds_strm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6B18BDC2180095E648 /* nds_strm.c */; }; + 836F6FA818BDC2190095E648 /* nds_swav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6C18BDC2180095E648 /* nds_swav.c */; }; + 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6D18BDC2180095E648 /* ngc_adpdtk.c */; }; + 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6E18BDC2180095E648 /* ngc_bh2pcm.c */; }; + 836F6FAB18BDC2190095E648 /* ngc_bo2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E6F18BDC2180095E648 /* ngc_bo2.c */; }; + 836F6FAC18BDC2190095E648 /* ngc_caf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7018BDC2180095E648 /* ngc_caf.c */; }; + 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7118BDC2180095E648 /* ngc_dsp_konami.c */; }; + 836F6FAE18BDC2190095E648 /* ngc_dsp_mpds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7218BDC2180095E648 /* ngc_dsp_mpds.c */; }; + 836F6FAF18BDC2190095E648 /* ngc_dsp_std.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7318BDC2180095E648 /* ngc_dsp_std.c */; }; + 836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7418BDC2180095E648 /* ngc_dsp_ygo.c */; }; + 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7518BDC2180095E648 /* ngc_ffcc_str.c */; }; + 836F6FB218BDC2190095E648 /* ngc_gcub.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7618BDC2180095E648 /* ngc_gcub.c */; }; + 836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7718BDC2180095E648 /* ngc_lps.c */; }; + 836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7818BDC2180095E648 /* ngc_nst_dsp.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 */; }; + 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7B18BDC2180095E648 /* ngc_ssm.c */; }; + 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */; }; + 836F6FB918BDC2190095E648 /* ngc_waa_wac_wad_wam.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7D18BDC2180095E648 /* ngc_waa_wac_wad_wam.c */; }; + 836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7E18BDC2180095E648 /* ngc_ymf.c */; }; + 836F6FBB18BDC2190095E648 /* ngca.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E7F18BDC2180095E648 /* ngca.c */; }; + 836F6FBC18BDC2190095E648 /* nub.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8018BDC2180095E648 /* nub.c */; }; + 836F6FBD18BDC2190095E648 /* nwa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8118BDC2180095E648 /* nwa.c */; }; + 836F6FBE18BDC2190095E648 /* ogg_vorbis_file.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8218BDC2180095E648 /* ogg_vorbis_file.c */; }; + 836F6FBF18BDC2190095E648 /* otm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8318BDC2180095E648 /* otm.c */; }; + 836F6FC018BDC2190095E648 /* p3d.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8418BDC2180095E648 /* p3d.c */; }; + 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8518BDC2180095E648 /* pc_adp.c */; }; + 836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8618BDC2180095E648 /* pc_mxst.c */; }; + 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8718BDC2180095E648 /* pc_smp.c */; }; + 836F6FC418BDC2190095E648 /* pc_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8818BDC2180095E648 /* pc_snds.c */; }; + 836F6FC518BDC2190095E648 /* pc_sob.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8918BDC2180095E648 /* pc_sob.c */; }; + 836F6FC618BDC2190095E648 /* pcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8A18BDC2180095E648 /* pcm.c */; }; + 836F6FC718BDC2190095E648 /* pona.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8B18BDC2180095E648 /* pona.c */; }; + 836F6FC818BDC2190095E648 /* pos.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8C18BDC2180095E648 /* pos.c */; }; + 836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */; }; + 836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8E18BDC2180095E648 /* ps2_adm.c */; }; + 836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E8F18BDC2180095E648 /* ps2_ads.c */; }; + 836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9018BDC2180095E648 /* ps2_adsc.c */; }; + 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9118BDC2180095E648 /* ps2_ass.c */; }; + 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9218BDC2180095E648 /* ps2_ast.c */; }; + 836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9318BDC2180095E648 /* ps2_aus.c */; }; + 836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9418BDC2180095E648 /* ps2_b1s.c */; }; + 836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9518BDC2180095E648 /* ps2_bg00.c */; }; + 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9618BDC2180095E648 /* ps2_bmdx.c */; }; + 836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9718BDC2180095E648 /* ps2_ccc.c */; }; + 836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9818BDC2180095E648 /* ps2_dxh.c */; }; + 836F6FD518BDC2190095E648 /* ps2_enth.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9918BDC2180095E648 /* ps2_enth.c */; }; + 836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9A18BDC2180095E648 /* ps2_exst.c */; }; + 836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9B18BDC2180095E648 /* ps2_filp.c */; }; + 836F6FD818BDC2190095E648 /* ps2_gbts.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9C18BDC2180095E648 /* ps2_gbts.c */; }; + 836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9D18BDC2180095E648 /* ps2_gcm.c */; }; + 836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9E18BDC2180095E648 /* ps2_hgc1.c */; }; + 836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6E9F18BDC2180095E648 /* ps2_hsf.c */; }; + 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA018BDC2180095E648 /* ps2_iab.c */; }; + 836F6FDD18BDC2190095E648 /* ps2_ikm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA118BDC2180095E648 /* ps2_ikm.c */; }; + 836F6FDE18BDC2190095E648 /* ps2_ild.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA218BDC2180095E648 /* ps2_ild.c */; }; + 836F6FDF18BDC2190095E648 /* ps2_int.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA318BDC2180095E648 /* ps2_int.c */; }; + 836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA418BDC2180095E648 /* ps2_joe.c */; }; + 836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA518BDC2180095E648 /* ps2_jstm.c */; }; + 836F6FE218BDC2190095E648 /* ps2_kces.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA618BDC2180095E648 /* ps2_kces.c */; }; + 836F6FE318BDC2190095E648 /* ps2_khv.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA718BDC2180095E648 /* ps2_khv.c */; }; + 836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA818BDC2180095E648 /* ps2_leg.c */; }; + 836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EA918BDC2180095E648 /* ps2_lpcm.c */; }; + 836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAA18BDC2180095E648 /* ps2_mcg.c */; }; + 836F6FE718BDC2190095E648 /* ps2_mib.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAB18BDC2180095E648 /* ps2_mib.c */; }; + 836F6FE818BDC2190095E648 /* ps2_mic.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAC18BDC2180095E648 /* ps2_mic.c */; }; + 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAD18BDC2180095E648 /* ps2_mihb.c */; }; + 836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAE18BDC2180095E648 /* ps2_msa.c */; }; + 836F6FEB18BDC2190095E648 /* ps2_mss.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EAF18BDC2180095E648 /* ps2_mss.c */; }; + 836F6FEC18BDC2190095E648 /* ps2_mtaf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB018BDC2180095E648 /* ps2_mtaf.c */; }; + 836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB118BDC2180095E648 /* ps2_npsf.c */; }; + 836F6FEE18BDC2190095E648 /* ps2_p2bt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB218BDC2180095E648 /* ps2_p2bt.c */; }; + 836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB318BDC2180095E648 /* ps2_pnb.c */; }; + 836F6FF018BDC2190095E648 /* ps2_psh.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB418BDC2180095E648 /* ps2_psh.c */; }; + 836F6FF118BDC2190095E648 /* ps2_psw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB518BDC2180095E648 /* ps2_psw.c */; }; + 836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB618BDC2180095E648 /* ps2_rnd.c */; }; + 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB718BDC2180095E648 /* ps2_rstm.c */; }; + 836F6FF418BDC2190095E648 /* ps2_rws.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB818BDC2180095E648 /* ps2_rws.c */; }; + 836F6FF518BDC2190095E648 /* ps2_rxw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EB918BDC2180095E648 /* ps2_rxw.c */; }; + 836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBA18BDC2180095E648 /* ps2_sfs.c */; }; + 836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBB18BDC2180095E648 /* ps2_sl3.c */; }; + 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBC18BDC2180095E648 /* ps2_smpl.c */; }; + 836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBD18BDC2180095E648 /* ps2_snd.c */; }; + 836F6FFA18BDC2190095E648 /* ps2_spm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBE18BDC2190095E648 /* ps2_spm.c */; }; + 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EBF18BDC2190095E648 /* ps2_sps.c */; }; + 836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC018BDC2190095E648 /* ps2_ster.c */; }; + 836F6FFD18BDC2190095E648 /* ps2_stm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC118BDC2190095E648 /* ps2_stm.c */; }; + 836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC218BDC2190095E648 /* ps2_str.c */; }; + 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC318BDC2190095E648 /* ps2_strlr.c */; }; + 836F700018BDC2190095E648 /* ps2_svag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC418BDC2190095E648 /* ps2_svag.c */; }; + 836F700118BDC2190095E648 /* ps2_tec.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC518BDC2190095E648 /* ps2_tec.c */; }; + 836F700218BDC2190095E648 /* ps2_tk5.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC618BDC2190095E648 /* ps2_tk5.c */; }; + 836F700318BDC2190095E648 /* ps2_vag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC718BDC2190095E648 /* ps2_vag.c */; }; + 836F700418BDC2190095E648 /* ps2_vas.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC818BDC2190095E648 /* ps2_vas.c */; }; + 836F700518BDC2190095E648 /* ps2_vbk.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EC918BDC2190095E648 /* ps2_vbk.c */; }; + 836F700618BDC2190095E648 /* ps2_vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECA18BDC2190095E648 /* ps2_vgs.c */; }; + 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECB18BDC2190095E648 /* ps2_vgv.c */; }; + 836F700818BDC2190095E648 /* ps2_vms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECC18BDC2190095E648 /* ps2_vms.c */; }; + 836F700918BDC2190095E648 /* ps2_voi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECD18BDC2190095E648 /* ps2_voi.c */; }; + 836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECE18BDC2190095E648 /* ps2_vpk.c */; }; + 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ECF18BDC2190095E648 /* ps2_wad.c */; }; + 836F700C18BDC2190095E648 /* ps2_wb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED018BDC2190095E648 /* ps2_wb.c */; }; + 836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED118BDC2190095E648 /* ps2_wmus.c */; }; + 836F700E18BDC2190095E648 /* ps2_xa2.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED218BDC2190095E648 /* ps2_xa2.c */; }; + 836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED318BDC2190095E648 /* ps2_xa30.c */; }; + 836F701018BDC2190095E648 /* ps2_xau.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED418BDC2190095E648 /* ps2_xau.c */; }; + 836F701118BDC2190095E648 /* ps3_cps.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED518BDC2190095E648 /* ps3_cps.c */; }; + 836F701218BDC2190095E648 /* ps3_ivag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED618BDC2190095E648 /* ps3_ivag.c */; }; + 836F701318BDC2190095E648 /* ps3_klbs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED718BDC2190095E648 /* ps3_klbs.c */; }; + 836F701418BDC2190095E648 /* ps3_msf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED818BDC2190095E648 /* ps3_msf.c */; }; + 836F701518BDC2190095E648 /* ps3_past.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6ED918BDC2190095E648 /* ps3_past.c */; }; + 836F701618BDC2190095E648 /* ps3_sgh_sgb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */; }; + 836F701718BDC2190095E648 /* ps3_vawx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDB18BDC2190095E648 /* ps3_vawx.c */; }; + 836F701818BDC2190095E648 /* ps3_xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDC18BDC2190095E648 /* ps3_xvag.c */; }; + 836F701918BDC2190095E648 /* psx_cdxa.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDD18BDC2190095E648 /* psx_cdxa.c */; }; + 836F701A18BDC2190095E648 /* psx_fag.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDE18BDC2190095E648 /* psx_fag.c */; }; + 836F701B18BDC2190095E648 /* psx_gms.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EDF18BDC2190095E648 /* psx_gms.c */; }; + 836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE018BDC2190095E648 /* psx_str_mgav.c */; }; + 836F701D18BDC2190095E648 /* raw.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE118BDC2190095E648 /* raw.c */; }; + 836F701E18BDC2190095E648 /* redspark.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE218BDC2190095E648 /* redspark.c */; }; + 836F701F18BDC2190095E648 /* riff.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE318BDC2190095E648 /* riff.c */; }; + 836F702018BDC2190095E648 /* rkv.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE418BDC2190095E648 /* rkv.c */; }; + 836F702118BDC2190095E648 /* rs03.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE518BDC2190095E648 /* rs03.c */; }; + 836F702218BDC2190095E648 /* rsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE618BDC2190095E648 /* rsd.c */; }; + 836F702318BDC2190095E648 /* rsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE718BDC2190095E648 /* rsf.c */; }; + 836F702418BDC2190095E648 /* rwsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE818BDC2190095E648 /* rwsd.c */; }; + 836F702518BDC2190095E648 /* rwx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EE918BDC2190095E648 /* rwx.c */; }; + 836F702618BDC2190095E648 /* s14_sss.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EEA18BDC2190095E648 /* s14_sss.c */; }; + 836F702718BDC2190095E648 /* sat_baka.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EEB18BDC2190095E648 /* sat_baka.c */; }; + 836F702818BDC2190095E648 /* sat_dvi.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EEC18BDC2190095E648 /* sat_dvi.c */; }; + 836F702918BDC2190095E648 /* sat_sap.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EED18BDC2190095E648 /* sat_sap.c */; }; + 836F702A18BDC2190095E648 /* sd9.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EEE18BDC2190095E648 /* sd9.c */; }; + 836F702B18BDC2190095E648 /* sdt.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EEF18BDC2190095E648 /* sdt.c */; }; + 836F702C18BDC2190095E648 /* seg.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF018BDC2190095E648 /* seg.c */; }; + 836F702D18BDC2190095E648 /* sfl.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF118BDC2190095E648 /* sfl.c */; }; + 836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; }; + 836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.c */; }; + 836F703018BDC2190095E648 /* sqex_scd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF418BDC2190095E648 /* sqex_scd.c */; }; + 836F703118BDC2190095E648 /* ss_stream.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF518BDC2190095E648 /* ss_stream.c */; }; + 836F703218BDC2190095E648 /* str_asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* str_asr.c */; }; + 836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; }; + 836F703418BDC2190095E648 /* stx.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF818BDC2190095E648 /* stx.c */; }; + 836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; }; + 836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.c */; }; + 836F703718BDC2190095E648 /* tun.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFB18BDC2190095E648 /* tun.c */; }; + 836F703818BDC2190095E648 /* ubi_ckd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFC18BDC2190095E648 /* ubi_ckd.c */; }; + 836F703918BDC2190095E648 /* vgs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFD18BDC2190095E648 /* vgs.c */; }; + 836F703A18BDC2190095E648 /* vs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFE18BDC2190095E648 /* vs.c */; }; + 836F703B18BDC2190095E648 /* vsf.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFF18BDC2190095E648 /* vsf.c */; }; + 836F703C18BDC2190095E648 /* wii_bns.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0018BDC2190095E648 /* wii_bns.c */; }; + 836F703D18BDC2190095E648 /* wii_mus.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0118BDC2190095E648 /* wii_mus.c */; }; + 836F703E18BDC2190095E648 /* wii_ras.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0218BDC2190095E648 /* wii_ras.c */; }; + 836F703F18BDC2190095E648 /* wii_smp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0318BDC2190095E648 /* wii_smp.c */; }; + 836F704018BDC2190095E648 /* wii_sng.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0418BDC2190095E648 /* wii_sng.c */; }; + 836F704118BDC2190095E648 /* wii_str.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0518BDC2190095E648 /* wii_str.c */; }; + 836F704218BDC2190095E648 /* wii_sts.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0618BDC2190095E648 /* wii_sts.c */; }; + 836F704318BDC2190095E648 /* wpd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0718BDC2190095E648 /* wpd.c */; }; + 836F704418BDC2190095E648 /* ws_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0818BDC2190095E648 /* ws_aud.c */; }; + 836F704518BDC2190095E648 /* wvs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0918BDC2190095E648 /* wvs.c */; }; + 836F704618BDC2190095E648 /* x360_tra.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0A18BDC2190095E648 /* x360_tra.c */; }; + 836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */; }; + 836F704818BDC2190095E648 /* xbox_ims.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0C18BDC2190095E648 /* xbox_ims.c */; }; + 836F704918BDC2190095E648 /* xbox_stma.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0D18BDC2190095E648 /* xbox_stma.c */; }; + 836F704A18BDC2190095E648 /* xbox_wavm.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0E18BDC2190095E648 /* xbox_wavm.c */; }; + 836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F0F18BDC2190095E648 /* xbox_xmu.c */; }; + 836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1018BDC2190095E648 /* xbox_xvas.c */; }; + 836F704D18BDC2190095E648 /* xbox_xwav.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1118BDC2190095E648 /* xbox_xwav.c */; }; + 836F704E18BDC2190095E648 /* xss.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1218BDC2190095E648 /* xss.c */; }; + 836F704F18BDC2190095E648 /* xwb.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1318BDC2190095E648 /* xwb.c */; }; + 836F705018BDC2190095E648 /* ydsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1418BDC2190095E648 /* ydsp.c */; }; + 836F705118BDC2190095E648 /* zsd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1518BDC2190095E648 /* zsd.c */; }; + 836F705218BDC2190095E648 /* zwdsp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1618BDC2190095E648 /* zwdsp.c */; }; + 836F705318BDC2190095E648 /* streamfile.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1718BDC2190095E648 /* streamfile.c */; }; + 836F705418BDC2190095E648 /* streamfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1818BDC2190095E648 /* streamfile.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836F705518BDC2190095E648 /* streamtypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1918BDC2190095E648 /* streamtypes.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 836F705618BDC2190095E648 /* util.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1A18BDC2190095E648 /* util.c */; }; + 836F705718BDC2190095E648 /* util.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1B18BDC2190095E648 /* util.h */; }; + 836F705818BDC2190095E648 /* vgmstream.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6F1C18BDC2190095E648 /* vgmstream.c */; }; + 836F705918BDC2190095E648 /* vgmstream.h in Headers */ = {isa = PBXBuildFile; fileRef = 836F6F1D18BDC2190095E648 /* vgmstream.h */; settings = {ATTRIBUTES = (Public, ); }; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 836F6B3918BDB8880095E648 /* vgmstream.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = vgmstream.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 836F6B4418BDB8880095E648 /* vgmstream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "vgmstream-Info.plist"; sourceTree = ""; }; + 836F6B4618BDB8880095E648 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 836F6DE018BDC2180095E648 /* acm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm_decoder.c; sourceTree = ""; }; + 836F6DE118BDC2180095E648 /* acm_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acm_decoder.h; sourceTree = ""; }; + 836F6DE218BDC2180095E648 /* adx_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adx_decoder.c; sourceTree = ""; }; + 836F6DE318BDC2180095E648 /* aica_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aica_decoder.c; sourceTree = ""; }; + 836F6DE418BDC2180095E648 /* at3_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = at3_decoder.c; sourceTree = ""; }; + 836F6DE518BDC2180095E648 /* coding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coding.h; sourceTree = ""; }; + 836F6DE618BDC2180095E648 /* eaxa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = eaxa_decoder.c; sourceTree = ""; }; + 836F6DE718BDC2180095E648 /* g721_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g721_decoder.c; sourceTree = ""; }; + 836F6DE818BDC2180095E648 /* g7221_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g7221_decoder.c; sourceTree = ""; }; + 836F6DE918BDC2180095E648 /* g72x_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g72x_state.h; sourceTree = ""; }; + 836F6DEA18BDC2180095E648 /* ima_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ima_decoder.c; sourceTree = ""; }; + 836F6DEB18BDC2180095E648 /* l5_555_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = l5_555_decoder.c; sourceTree = ""; }; + 836F6DEC18BDC2180095E648 /* lsf_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lsf_decoder.c; sourceTree = ""; }; + 836F6DED18BDC2180095E648 /* Makefile.unix.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.unix.am; sourceTree = ""; }; + 836F6DEE18BDC2180095E648 /* mp4_aac_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mp4_aac_decoder.c; sourceTree = ""; }; + 836F6DEF18BDC2180095E648 /* mpeg_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mpeg_decoder.c; sourceTree = ""; }; + 836F6DF018BDC2180095E648 /* msadpcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msadpcm_decoder.c; sourceTree = ""; }; + 836F6DF118BDC2180095E648 /* mtaf_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mtaf_decoder.c; sourceTree = ""; }; + 836F6DF218BDC2180095E648 /* nds_procyon_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_procyon_decoder.c; sourceTree = ""; }; + 836F6DF318BDC2180095E648 /* ngc_afc_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_afc_decoder.c; sourceTree = ""; }; + 836F6DF418BDC2180095E648 /* ngc_dsp_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dsp_decoder.c; sourceTree = ""; }; + 836F6DF518BDC2180095E648 /* ngc_dtk_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dtk_decoder.c; sourceTree = ""; }; + 836F6DF618BDC2180095E648 /* nwa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa_decoder.c; sourceTree = ""; }; + 836F6DF718BDC2180095E648 /* nwa_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nwa_decoder.h; sourceTree = ""; }; + 836F6DF818BDC2180095E648 /* ogg_vorbis_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogg_vorbis_decoder.c; sourceTree = ""; }; + 836F6DF918BDC2180095E648 /* pcm_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcm_decoder.c; sourceTree = ""; }; + 836F6DFA18BDC2180095E648 /* psx_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_decoder.c; sourceTree = ""; }; + 836F6DFB18BDC2180095E648 /* SASSC_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SASSC_decoder.c; sourceTree = ""; }; + 836F6DFC18BDC2180095E648 /* sdx2_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sdx2_decoder.c; sourceTree = ""; }; + 836F6DFD18BDC2180095E648 /* ws_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ws_decoder.c; sourceTree = ""; }; + 836F6DFE18BDC2180095E648 /* xa_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa_decoder.c; sourceTree = ""; }; + 836F6E0018BDC2180095E648 /* aax_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax_layout.c; sourceTree = ""; }; + 836F6E0118BDC2180095E648 /* aix_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aix_layout.c; sourceTree = ""; }; + 836F6E0218BDC2180095E648 /* ast_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ast_blocked.c; sourceTree = ""; }; + 836F6E0318BDC2180095E648 /* bdsp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bdsp_blocked.c; sourceTree = ""; }; + 836F6E0418BDC2180095E648 /* blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked.c; sourceTree = ""; }; + 836F6E0518BDC2180095E648 /* caf_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = caf_blocked.c; sourceTree = ""; }; + 836F6E0618BDC2180095E648 /* de2_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2_blocked.c; sourceTree = ""; }; + 836F6E0718BDC2180095E648 /* ea_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_block.c; sourceTree = ""; }; + 836F6E0818BDC2180095E648 /* emff_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff_blocked.c; sourceTree = ""; }; + 836F6E0918BDC2180095E648 /* filp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = filp_blocked.c; sourceTree = ""; }; + 836F6E0A18BDC2180095E648 /* gsb_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsb_blocked.c; sourceTree = ""; }; + 836F6E0B18BDC2180095E648 /* halpst_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst_blocked.c; sourceTree = ""; }; + 836F6E0C18BDC2180095E648 /* ims_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ims_block.c; sourceTree = ""; }; + 836F6E0D18BDC2180095E648 /* interleave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave.c; sourceTree = ""; }; + 836F6E0E18BDC2180095E648 /* interleave_byte.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interleave_byte.c; sourceTree = ""; }; + 836F6E0F18BDC2180095E648 /* ivaud_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivaud_layout.c; sourceTree = ""; }; + 836F6E1018BDC2180095E648 /* layout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = layout.h; sourceTree = ""; }; + 836F6E1118BDC2180095E648 /* Makefile.unix.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.unix.am; sourceTree = ""; }; + 836F6E1218BDC2180095E648 /* mus_acm_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm_layout.c; sourceTree = ""; }; + 836F6E1318BDC2180095E648 /* mxch_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mxch_blocked.c; sourceTree = ""; }; + 836F6E1418BDC2180095E648 /* nolayout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nolayout.c; sourceTree = ""; }; + 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adm_blocked.c; sourceTree = ""; }; + 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_iab_blocked.c; sourceTree = ""; }; + 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_strlr_blocked.c; sourceTree = ""; }; + 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_mgav_blocked.c; sourceTree = ""; }; + 836F6E1918BDC2180095E648 /* scd_int_layout.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = scd_int_layout.c; sourceTree = ""; }; + 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds_blocked.c; sourceTree = ""; }; + 836F6E1B18BDC2180095E648 /* thp_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp_blocked.c; sourceTree = ""; }; + 836F6E1C18BDC2180095E648 /* tra_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tra_blocked.c; sourceTree = ""; }; + 836F6E1D18BDC2180095E648 /* vs_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs_blocked.c; sourceTree = ""; }; + 836F6E1E18BDC2180095E648 /* ws_aud_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ws_aud_blocked.c; sourceTree = ""; }; + 836F6E1F18BDC2180095E648 /* wsi_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wsi_blocked.c; sourceTree = ""; }; + 836F6E2018BDC2180095E648 /* xa_blocked.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xa_blocked.c; sourceTree = ""; }; + 836F6E2118BDC2180095E648 /* xvas_block.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xvas_block.c; sourceTree = ""; }; + 836F6E2918BDC2180095E648 /* 2dx9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = 2dx9.c; sourceTree = ""; }; + 836F6E2A18BDC2180095E648 /* aax.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aax.c; sourceTree = ""; }; + 836F6E2B18BDC2180095E648 /* acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acm.c; sourceTree = ""; }; + 836F6E2C18BDC2180095E648 /* ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ads.c; sourceTree = ""; }; + 836F6E2D18BDC2180095E648 /* adx_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = adx_header.c; sourceTree = ""; }; + 836F6E2E18BDC2180095E648 /* afc_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = afc_header.c; sourceTree = ""; }; + 836F6E2F18BDC2180095E648 /* agsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = agsc.c; sourceTree = ""; }; + 836F6E3018BDC2180095E648 /* ahx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ahx.c; sourceTree = ""; }; + 836F6E3118BDC2180095E648 /* aifc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aifc.c; sourceTree = ""; }; + 836F6E3218BDC2180095E648 /* aix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aix.c; sourceTree = ""; }; + 836F6E3318BDC2180095E648 /* akb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = akb.c; sourceTree = ""; }; + 836F6E3418BDC2180095E648 /* apple_caff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = apple_caff.c; sourceTree = ""; }; + 836F6E3518BDC2180095E648 /* ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ast.c; sourceTree = ""; }; + 836F6E3618BDC2180095E648 /* baf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = baf.c; sourceTree = ""; }; + 836F6E3718BDC2180095E648 /* bcstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bcstm.c; sourceTree = ""; }; + 836F6E3818BDC2180095E648 /* bgw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bgw.c; sourceTree = ""; }; + 836F6E3918BDC2180095E648 /* bnsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bnsf.c; sourceTree = ""; }; + 836F6E3A18BDC2180095E648 /* brstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = brstm.c; sourceTree = ""; }; + 836F6E3B18BDC2180095E648 /* capdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = capdsp.c; sourceTree = ""; }; + 836F6E3C18BDC2180095E648 /* Cstr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Cstr.c; sourceTree = ""; }; + 836F6E3D18BDC2180095E648 /* dc_asd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_asd.c; sourceTree = ""; }; + 836F6E3E18BDC2180095E648 /* dc_dcsw_dcs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_dcsw_dcs.c; sourceTree = ""; }; + 836F6E3F18BDC2180095E648 /* dc_idvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_idvi.c; sourceTree = ""; }; + 836F6E4018BDC2180095E648 /* dc_kcey.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_kcey.c; sourceTree = ""; }; + 836F6E4118BDC2180095E648 /* dc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dc_str.c; sourceTree = ""; }; + 836F6E4218BDC2180095E648 /* de2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = de2.c; sourceTree = ""; }; + 836F6E4318BDC2180095E648 /* dmsg_segh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmsg_segh.c; sourceTree = ""; }; + 836F6E4418BDC2180095E648 /* dsp_bdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_bdsp.c; sourceTree = ""; }; + 836F6E4518BDC2180095E648 /* dsp_sth_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dsp_sth_str.c; sourceTree = ""; }; + 836F6E4618BDC2180095E648 /* ea_header.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_header.c; sourceTree = ""; }; + 836F6E4718BDC2180095E648 /* ea_old.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ea_old.c; sourceTree = ""; }; + 836F6E4818BDC2180095E648 /* emff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = emff.c; sourceTree = ""; }; + 836F6E4918BDC2180095E648 /* exakt_sc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exakt_sc.c; sourceTree = ""; }; + 836F6E4A18BDC2180095E648 /* excitebots.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = excitebots.c; sourceTree = ""; }; + 836F6E4B18BDC2180095E648 /* ffw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ffw.c; sourceTree = ""; }; + 836F6E4C18BDC2180095E648 /* fsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fsb.c; sourceTree = ""; }; + 836F6E4D18BDC2180095E648 /* gca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gca.c; sourceTree = ""; }; + 836F6E4E18BDC2180095E648 /* gcsw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gcsw.c; sourceTree = ""; }; + 836F6E4F18BDC2180095E648 /* genh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = genh.c; sourceTree = ""; }; + 836F6E5018BDC2180095E648 /* gh3_bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gh3_bar.c; sourceTree = ""; }; + 836F6E5118BDC2180095E648 /* gsp_gsb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gsp_gsb.c; sourceTree = ""; }; + 836F6E5218BDC2180095E648 /* halpst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = halpst.c; sourceTree = ""; }; + 836F6E5318BDC2180095E648 /* his.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = his.c; sourceTree = ""; }; + 836F6E5418BDC2180095E648 /* idsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = idsp.c; sourceTree = ""; }; + 836F6E5518BDC2180095E648 /* ios_psnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ios_psnd.c; sourceTree = ""; }; + 836F6E5618BDC2180095E648 /* ish_isd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ish_isd.c; sourceTree = ""; }; + 836F6E5718BDC2180095E648 /* ivaud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivaud.c; sourceTree = ""; }; + 836F6E5818BDC2180095E648 /* ivb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ivb.c; sourceTree = ""; }; + 836F6E5918BDC2180095E648 /* kraw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kraw.c; sourceTree = ""; }; + 836F6E5A18BDC2180095E648 /* lsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lsf.c; sourceTree = ""; }; + 836F6E5B18BDC2180095E648 /* Makefile.unix.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.unix.am; sourceTree = ""; }; + 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mattel_hyperscan.c; sourceTree = ""; }; + 836F6E5D18BDC2180095E648 /* maxis_xa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = maxis_xa.c; sourceTree = ""; }; + 836F6E5E18BDC2180095E648 /* meta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = meta.h; sourceTree = ""; }; + 836F6E5F18BDC2180095E648 /* mn_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mn_str.c; sourceTree = ""; }; + 836F6E6018BDC2180095E648 /* mp4.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mp4.c; sourceTree = ""; }; + 836F6E6118BDC2180095E648 /* msvp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = msvp.c; sourceTree = ""; }; + 836F6E6218BDC2180095E648 /* mus_acm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mus_acm.c; sourceTree = ""; }; + 836F6E6318BDC2180095E648 /* musc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = musc.c; sourceTree = ""; }; + 836F6E6418BDC2180095E648 /* musx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = musx.c; sourceTree = ""; }; + 836F6E6518BDC2180095E648 /* myspd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = myspd.c; sourceTree = ""; }; + 836F6E6618BDC2180095E648 /* naomi_adpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naomi_adpcm.c; sourceTree = ""; }; + 836F6E6718BDC2180095E648 /* naomi_spsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = naomi_spsd.c; sourceTree = ""; }; + 836F6E6818BDC2180095E648 /* nds_hwas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_hwas.c; sourceTree = ""; }; + 836F6E6918BDC2180095E648 /* nds_rrds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_rrds.c; sourceTree = ""; }; + 836F6E6A18BDC2180095E648 /* nds_sad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_sad.c; sourceTree = ""; }; + 836F6E6B18BDC2180095E648 /* nds_strm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_strm.c; sourceTree = ""; }; + 836F6E6C18BDC2180095E648 /* nds_swav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nds_swav.c; sourceTree = ""; }; + 836F6E6D18BDC2180095E648 /* ngc_adpdtk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_adpdtk.c; sourceTree = ""; }; + 836F6E6E18BDC2180095E648 /* ngc_bh2pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_bh2pcm.c; sourceTree = ""; }; + 836F6E6F18BDC2180095E648 /* ngc_bo2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_bo2.c; sourceTree = ""; }; + 836F6E7018BDC2180095E648 /* ngc_caf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_caf.c; sourceTree = ""; }; + 836F6E7118BDC2180095E648 /* ngc_dsp_konami.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dsp_konami.c; sourceTree = ""; }; + 836F6E7218BDC2180095E648 /* ngc_dsp_mpds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dsp_mpds.c; sourceTree = ""; }; + 836F6E7318BDC2180095E648 /* ngc_dsp_std.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dsp_std.c; sourceTree = ""; }; + 836F6E7418BDC2180095E648 /* ngc_dsp_ygo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_dsp_ygo.c; sourceTree = ""; }; + 836F6E7518BDC2180095E648 /* ngc_ffcc_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ffcc_str.c; sourceTree = ""; }; + 836F6E7618BDC2180095E648 /* ngc_gcub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_gcub.c; sourceTree = ""; }; + 836F6E7718BDC2180095E648 /* ngc_lps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_lps.c; sourceTree = ""; }; + 836F6E7818BDC2180095E648 /* ngc_nst_dsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_nst_dsp.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 = ""; }; + 836F6E7B18BDC2180095E648 /* ngc_ssm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ssm.c; sourceTree = ""; }; + 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_tydsp.c; sourceTree = ""; }; + 836F6E7D18BDC2180095E648 /* ngc_waa_wac_wad_wam.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_waa_wac_wad_wam.c; sourceTree = ""; }; + 836F6E7E18BDC2180095E648 /* ngc_ymf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngc_ymf.c; sourceTree = ""; }; + 836F6E7F18BDC2180095E648 /* ngca.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngca.c; sourceTree = ""; }; + 836F6E8018BDC2180095E648 /* nub.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nub.c; sourceTree = ""; }; + 836F6E8118BDC2180095E648 /* nwa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nwa.c; sourceTree = ""; }; + 836F6E8218BDC2180095E648 /* ogg_vorbis_file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ogg_vorbis_file.c; sourceTree = ""; }; + 836F6E8318BDC2180095E648 /* otm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = otm.c; sourceTree = ""; }; + 836F6E8418BDC2180095E648 /* p3d.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p3d.c; sourceTree = ""; }; + 836F6E8518BDC2180095E648 /* pc_adp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_adp.c; sourceTree = ""; }; + 836F6E8618BDC2180095E648 /* pc_mxst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_mxst.c; sourceTree = ""; }; + 836F6E8718BDC2180095E648 /* pc_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_smp.c; sourceTree = ""; }; + 836F6E8818BDC2180095E648 /* pc_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_snds.c; sourceTree = ""; }; + 836F6E8918BDC2180095E648 /* pc_sob.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pc_sob.c; sourceTree = ""; }; + 836F6E8A18BDC2180095E648 /* pcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pcm.c; sourceTree = ""; }; + 836F6E8B18BDC2180095E648 /* pona.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pona.c; sourceTree = ""; }; + 836F6E8C18BDC2180095E648 /* pos.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pos.c; sourceTree = ""; }; + 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_2pfs.c; sourceTree = ""; }; + 836F6E8E18BDC2180095E648 /* ps2_adm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adm.c; sourceTree = ""; }; + 836F6E8F18BDC2180095E648 /* ps2_ads.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ads.c; sourceTree = ""; }; + 836F6E9018BDC2180095E648 /* ps2_adsc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_adsc.c; sourceTree = ""; }; + 836F6E9118BDC2180095E648 /* ps2_ass.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ass.c; sourceTree = ""; }; + 836F6E9218BDC2180095E648 /* ps2_ast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ast.c; sourceTree = ""; }; + 836F6E9318BDC2180095E648 /* ps2_aus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_aus.c; sourceTree = ""; }; + 836F6E9418BDC2180095E648 /* ps2_b1s.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_b1s.c; sourceTree = ""; }; + 836F6E9518BDC2180095E648 /* ps2_bg00.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bg00.c; sourceTree = ""; }; + 836F6E9618BDC2180095E648 /* ps2_bmdx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_bmdx.c; sourceTree = ""; }; + 836F6E9718BDC2180095E648 /* ps2_ccc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ccc.c; sourceTree = ""; }; + 836F6E9818BDC2180095E648 /* ps2_dxh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_dxh.c; sourceTree = ""; }; + 836F6E9918BDC2180095E648 /* ps2_enth.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_enth.c; sourceTree = ""; }; + 836F6E9A18BDC2180095E648 /* ps2_exst.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_exst.c; sourceTree = ""; }; + 836F6E9B18BDC2180095E648 /* ps2_filp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_filp.c; sourceTree = ""; }; + 836F6E9C18BDC2180095E648 /* ps2_gbts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_gbts.c; sourceTree = ""; }; + 836F6E9D18BDC2180095E648 /* ps2_gcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_gcm.c; sourceTree = ""; }; + 836F6E9E18BDC2180095E648 /* ps2_hgc1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_hgc1.c; sourceTree = ""; }; + 836F6E9F18BDC2180095E648 /* ps2_hsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_hsf.c; sourceTree = ""; }; + 836F6EA018BDC2180095E648 /* ps2_iab.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_iab.c; sourceTree = ""; }; + 836F6EA118BDC2180095E648 /* ps2_ikm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ikm.c; sourceTree = ""; }; + 836F6EA218BDC2180095E648 /* ps2_ild.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ild.c; sourceTree = ""; }; + 836F6EA318BDC2180095E648 /* ps2_int.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_int.c; sourceTree = ""; }; + 836F6EA418BDC2180095E648 /* ps2_joe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_joe.c; sourceTree = ""; }; + 836F6EA518BDC2180095E648 /* ps2_jstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_jstm.c; sourceTree = ""; }; + 836F6EA618BDC2180095E648 /* ps2_kces.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_kces.c; sourceTree = ""; }; + 836F6EA718BDC2180095E648 /* ps2_khv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_khv.c; sourceTree = ""; }; + 836F6EA818BDC2180095E648 /* ps2_leg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_leg.c; sourceTree = ""; }; + 836F6EA918BDC2180095E648 /* ps2_lpcm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_lpcm.c; sourceTree = ""; }; + 836F6EAA18BDC2180095E648 /* ps2_mcg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mcg.c; sourceTree = ""; }; + 836F6EAB18BDC2180095E648 /* ps2_mib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mib.c; sourceTree = ""; }; + 836F6EAC18BDC2180095E648 /* ps2_mic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mic.c; sourceTree = ""; }; + 836F6EAD18BDC2180095E648 /* ps2_mihb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mihb.c; sourceTree = ""; }; + 836F6EAE18BDC2180095E648 /* ps2_msa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_msa.c; sourceTree = ""; }; + 836F6EAF18BDC2180095E648 /* ps2_mss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mss.c; sourceTree = ""; }; + 836F6EB018BDC2180095E648 /* ps2_mtaf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_mtaf.c; sourceTree = ""; }; + 836F6EB118BDC2180095E648 /* ps2_npsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_npsf.c; sourceTree = ""; }; + 836F6EB218BDC2180095E648 /* ps2_p2bt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_p2bt.c; sourceTree = ""; }; + 836F6EB318BDC2180095E648 /* ps2_pnb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_pnb.c; sourceTree = ""; }; + 836F6EB418BDC2180095E648 /* ps2_psh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_psh.c; sourceTree = ""; }; + 836F6EB518BDC2180095E648 /* ps2_psw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_psw.c; sourceTree = ""; }; + 836F6EB618BDC2180095E648 /* ps2_rnd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rnd.c; sourceTree = ""; }; + 836F6EB718BDC2180095E648 /* ps2_rstm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rstm.c; sourceTree = ""; }; + 836F6EB818BDC2180095E648 /* ps2_rws.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rws.c; sourceTree = ""; }; + 836F6EB918BDC2180095E648 /* ps2_rxw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_rxw.c; sourceTree = ""; }; + 836F6EBA18BDC2180095E648 /* ps2_sfs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_sfs.c; sourceTree = ""; }; + 836F6EBB18BDC2180095E648 /* ps2_sl3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_sl3.c; sourceTree = ""; }; + 836F6EBC18BDC2180095E648 /* ps2_smpl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_smpl.c; sourceTree = ""; }; + 836F6EBD18BDC2180095E648 /* ps2_snd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_snd.c; sourceTree = ""; }; + 836F6EBE18BDC2190095E648 /* ps2_spm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_spm.c; sourceTree = ""; }; + 836F6EBF18BDC2190095E648 /* ps2_sps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_sps.c; sourceTree = ""; }; + 836F6EC018BDC2190095E648 /* ps2_ster.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_ster.c; sourceTree = ""; }; + 836F6EC118BDC2190095E648 /* ps2_stm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_stm.c; sourceTree = ""; }; + 836F6EC218BDC2190095E648 /* ps2_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_str.c; sourceTree = ""; }; + 836F6EC318BDC2190095E648 /* ps2_strlr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_strlr.c; sourceTree = ""; }; + 836F6EC418BDC2190095E648 /* ps2_svag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_svag.c; sourceTree = ""; }; + 836F6EC518BDC2190095E648 /* ps2_tec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_tec.c; sourceTree = ""; }; + 836F6EC618BDC2190095E648 /* ps2_tk5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_tk5.c; sourceTree = ""; }; + 836F6EC718BDC2190095E648 /* ps2_vag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vag.c; sourceTree = ""; }; + 836F6EC818BDC2190095E648 /* ps2_vas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vas.c; sourceTree = ""; }; + 836F6EC918BDC2190095E648 /* ps2_vbk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vbk.c; sourceTree = ""; }; + 836F6ECA18BDC2190095E648 /* ps2_vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vgs.c; sourceTree = ""; }; + 836F6ECB18BDC2190095E648 /* ps2_vgv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vgv.c; sourceTree = ""; }; + 836F6ECC18BDC2190095E648 /* ps2_vms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vms.c; sourceTree = ""; }; + 836F6ECD18BDC2190095E648 /* ps2_voi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_voi.c; sourceTree = ""; }; + 836F6ECE18BDC2190095E648 /* ps2_vpk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_vpk.c; sourceTree = ""; }; + 836F6ECF18BDC2190095E648 /* ps2_wad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wad.c; sourceTree = ""; }; + 836F6ED018BDC2190095E648 /* ps2_wb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wb.c; sourceTree = ""; }; + 836F6ED118BDC2190095E648 /* ps2_wmus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_wmus.c; sourceTree = ""; }; + 836F6ED218BDC2190095E648 /* ps2_xa2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa2.c; sourceTree = ""; }; + 836F6ED318BDC2190095E648 /* ps2_xa30.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xa30.c; sourceTree = ""; }; + 836F6ED418BDC2190095E648 /* ps2_xau.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps2_xau.c; sourceTree = ""; }; + 836F6ED518BDC2190095E648 /* ps3_cps.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_cps.c; sourceTree = ""; }; + 836F6ED618BDC2190095E648 /* ps3_ivag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_ivag.c; sourceTree = ""; }; + 836F6ED718BDC2190095E648 /* ps3_klbs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_klbs.c; sourceTree = ""; }; + 836F6ED818BDC2190095E648 /* ps3_msf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_msf.c; sourceTree = ""; }; + 836F6ED918BDC2190095E648 /* ps3_past.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_past.c; sourceTree = ""; }; + 836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_sgh_sgb.c; sourceTree = ""; }; + 836F6EDB18BDC2190095E648 /* ps3_vawx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_vawx.c; sourceTree = ""; }; + 836F6EDC18BDC2190095E648 /* ps3_xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ps3_xvag.c; sourceTree = ""; }; + 836F6EDD18BDC2190095E648 /* psx_cdxa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_cdxa.c; sourceTree = ""; }; + 836F6EDE18BDC2190095E648 /* psx_fag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_fag.c; sourceTree = ""; }; + 836F6EDF18BDC2190095E648 /* psx_gms.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_gms.c; sourceTree = ""; }; + 836F6EE018BDC2190095E648 /* psx_str_mgav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = psx_str_mgav.c; sourceTree = ""; }; + 836F6EE118BDC2190095E648 /* raw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = raw.c; sourceTree = ""; }; + 836F6EE218BDC2190095E648 /* redspark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = redspark.c; sourceTree = ""; }; + 836F6EE318BDC2190095E648 /* riff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = riff.c; sourceTree = ""; }; + 836F6EE418BDC2190095E648 /* rkv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rkv.c; sourceTree = ""; }; + 836F6EE518BDC2190095E648 /* rs03.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rs03.c; sourceTree = ""; }; + 836F6EE618BDC2190095E648 /* rsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rsd.c; sourceTree = ""; }; + 836F6EE718BDC2190095E648 /* rsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rsf.c; sourceTree = ""; }; + 836F6EE818BDC2190095E648 /* rwsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwsd.c; sourceTree = ""; }; + 836F6EE918BDC2190095E648 /* rwx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rwx.c; sourceTree = ""; }; + 836F6EEA18BDC2190095E648 /* s14_sss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s14_sss.c; sourceTree = ""; }; + 836F6EEB18BDC2190095E648 /* sat_baka.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sat_baka.c; sourceTree = ""; }; + 836F6EEC18BDC2190095E648 /* sat_dvi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sat_dvi.c; sourceTree = ""; }; + 836F6EED18BDC2190095E648 /* sat_sap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sat_sap.c; sourceTree = ""; }; + 836F6EEE18BDC2190095E648 /* sd9.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sd9.c; sourceTree = ""; }; + 836F6EEF18BDC2190095E648 /* sdt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sdt.c; sourceTree = ""; }; + 836F6EF018BDC2190095E648 /* seg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = seg.c; sourceTree = ""; }; + 836F6EF118BDC2190095E648 /* sfl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sfl.c; sourceTree = ""; }; + 836F6EF218BDC2190095E648 /* sli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sli.c; sourceTree = ""; }; + 836F6EF318BDC2190095E648 /* spt_spd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spt_spd.c; sourceTree = ""; }; + 836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = ""; }; + 836F6EF518BDC2190095E648 /* ss_stream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ss_stream.c; sourceTree = ""; }; + 836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = ""; }; + 836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = ""; }; + 836F6EF818BDC2190095E648 /* stx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = stx.c; sourceTree = ""; }; + 836F6EF918BDC2190095E648 /* svs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svs.c; sourceTree = ""; }; + 836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = ""; }; + 836F6EFB18BDC2190095E648 /* tun.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tun.c; sourceTree = ""; }; + 836F6EFC18BDC2190095E648 /* ubi_ckd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ubi_ckd.c; sourceTree = ""; }; + 836F6EFD18BDC2190095E648 /* vgs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgs.c; sourceTree = ""; }; + 836F6EFE18BDC2190095E648 /* vs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vs.c; sourceTree = ""; }; + 836F6EFF18BDC2190095E648 /* vsf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vsf.c; sourceTree = ""; }; + 836F6F0018BDC2190095E648 /* wii_bns.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_bns.c; sourceTree = ""; }; + 836F6F0118BDC2190095E648 /* wii_mus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_mus.c; sourceTree = ""; }; + 836F6F0218BDC2190095E648 /* wii_ras.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_ras.c; sourceTree = ""; }; + 836F6F0318BDC2190095E648 /* wii_smp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_smp.c; sourceTree = ""; }; + 836F6F0418BDC2190095E648 /* wii_sng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_sng.c; sourceTree = ""; }; + 836F6F0518BDC2190095E648 /* wii_str.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_str.c; sourceTree = ""; }; + 836F6F0618BDC2190095E648 /* wii_sts.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wii_sts.c; sourceTree = ""; }; + 836F6F0718BDC2190095E648 /* wpd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wpd.c; sourceTree = ""; }; + 836F6F0818BDC2190095E648 /* ws_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ws_aud.c; sourceTree = ""; }; + 836F6F0918BDC2190095E648 /* wvs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wvs.c; sourceTree = ""; }; + 836F6F0A18BDC2190095E648 /* x360_tra.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x360_tra.c; sourceTree = ""; }; + 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_hlwav.c; sourceTree = ""; }; + 836F6F0C18BDC2190095E648 /* xbox_ims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_ims.c; sourceTree = ""; }; + 836F6F0D18BDC2190095E648 /* xbox_stma.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_stma.c; sourceTree = ""; }; + 836F6F0E18BDC2190095E648 /* xbox_wavm.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_wavm.c; sourceTree = ""; }; + 836F6F0F18BDC2190095E648 /* xbox_xmu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_xmu.c; sourceTree = ""; }; + 836F6F1018BDC2190095E648 /* xbox_xvas.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_xvas.c; sourceTree = ""; }; + 836F6F1118BDC2190095E648 /* xbox_xwav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xbox_xwav.c; sourceTree = ""; }; + 836F6F1218BDC2190095E648 /* xss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xss.c; sourceTree = ""; }; + 836F6F1318BDC2190095E648 /* xwb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwb.c; sourceTree = ""; }; + 836F6F1418BDC2190095E648 /* ydsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ydsp.c; sourceTree = ""; }; + 836F6F1518BDC2190095E648 /* zsd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zsd.c; sourceTree = ""; }; + 836F6F1618BDC2190095E648 /* zwdsp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = zwdsp.c; sourceTree = ""; }; + 836F6F1718BDC2190095E648 /* streamfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = streamfile.c; sourceTree = ""; }; + 836F6F1818BDC2190095E648 /* streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streamfile.h; sourceTree = ""; }; + 836F6F1918BDC2190095E648 /* streamtypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = streamtypes.h; sourceTree = ""; }; + 836F6F1A18BDC2190095E648 /* util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = util.c; sourceTree = ""; }; + 836F6F1B18BDC2190095E648 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = util.h; sourceTree = ""; }; + 836F6F1C18BDC2190095E648 /* vgmstream.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vgmstream.c; sourceTree = ""; }; + 836F6F1D18BDC2190095E648 /* vgmstream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vgmstream.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 836F6B3518BDB8880095E648 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 836F6B2F18BDB8880095E648 = { + isa = PBXGroup; + children = ( + 836F6B4218BDB8880095E648 /* vgmstream */, + 836F6B3B18BDB8880095E648 /* Frameworks */, + 836F6B3A18BDB8880095E648 /* Products */, + ); + sourceTree = ""; + }; + 836F6B3A18BDB8880095E648 /* Products */ = { + isa = PBXGroup; + children = ( + 836F6B3918BDB8880095E648 /* vgmstream.framework */, + ); + name = Products; + sourceTree = ""; + }; + 836F6B3B18BDB8880095E648 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 836F6B3E18BDB8880095E648 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + 836F6B3E18BDB8880095E648 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 836F6B4218BDB8880095E648 /* vgmstream */ = { + isa = PBXGroup; + children = ( + 836F6DDE18BDC2180095E648 /* src */, + 836F6B4318BDB8880095E648 /* Supporting Files */, + ); + path = vgmstream; + sourceTree = ""; + }; + 836F6B4318BDB8880095E648 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 836F6B4418BDB8880095E648 /* vgmstream-Info.plist */, + 836F6B4518BDB8880095E648 /* InfoPlist.strings */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 836F6DDE18BDC2180095E648 /* src */ = { + isa = PBXGroup; + children = ( + 836F6DDF18BDC2180095E648 /* coding */, + 836F6DFF18BDC2180095E648 /* layout */, + 836F6E2718BDC2180095E648 /* meta */, + 836F6F1718BDC2190095E648 /* streamfile.c */, + 836F6F1818BDC2190095E648 /* streamfile.h */, + 836F6F1918BDC2190095E648 /* streamtypes.h */, + 836F6F1A18BDC2190095E648 /* util.c */, + 836F6F1B18BDC2190095E648 /* util.h */, + 836F6F1C18BDC2190095E648 /* vgmstream.c */, + 836F6F1D18BDC2190095E648 /* vgmstream.h */, + ); + path = src; + sourceTree = ""; + }; + 836F6DDF18BDC2180095E648 /* coding */ = { + isa = PBXGroup; + children = ( + 836F6DE018BDC2180095E648 /* acm_decoder.c */, + 836F6DE118BDC2180095E648 /* acm_decoder.h */, + 836F6DE218BDC2180095E648 /* adx_decoder.c */, + 836F6DE318BDC2180095E648 /* aica_decoder.c */, + 836F6DE418BDC2180095E648 /* at3_decoder.c */, + 836F6DE518BDC2180095E648 /* coding.h */, + 836F6DE618BDC2180095E648 /* eaxa_decoder.c */, + 836F6DE718BDC2180095E648 /* g721_decoder.c */, + 836F6DE818BDC2180095E648 /* g7221_decoder.c */, + 836F6DE918BDC2180095E648 /* g72x_state.h */, + 836F6DEA18BDC2180095E648 /* ima_decoder.c */, + 836F6DEB18BDC2180095E648 /* l5_555_decoder.c */, + 836F6DEC18BDC2180095E648 /* lsf_decoder.c */, + 836F6DED18BDC2180095E648 /* Makefile.unix.am */, + 836F6DEE18BDC2180095E648 /* mp4_aac_decoder.c */, + 836F6DEF18BDC2180095E648 /* mpeg_decoder.c */, + 836F6DF018BDC2180095E648 /* msadpcm_decoder.c */, + 836F6DF118BDC2180095E648 /* mtaf_decoder.c */, + 836F6DF218BDC2180095E648 /* nds_procyon_decoder.c */, + 836F6DF318BDC2180095E648 /* ngc_afc_decoder.c */, + 836F6DF418BDC2180095E648 /* ngc_dsp_decoder.c */, + 836F6DF518BDC2180095E648 /* ngc_dtk_decoder.c */, + 836F6DF618BDC2180095E648 /* nwa_decoder.c */, + 836F6DF718BDC2180095E648 /* nwa_decoder.h */, + 836F6DF818BDC2180095E648 /* ogg_vorbis_decoder.c */, + 836F6DF918BDC2180095E648 /* pcm_decoder.c */, + 836F6DFA18BDC2180095E648 /* psx_decoder.c */, + 836F6DFB18BDC2180095E648 /* SASSC_decoder.c */, + 836F6DFC18BDC2180095E648 /* sdx2_decoder.c */, + 836F6DFD18BDC2180095E648 /* ws_decoder.c */, + 836F6DFE18BDC2180095E648 /* xa_decoder.c */, + ); + path = coding; + sourceTree = ""; + }; + 836F6DFF18BDC2180095E648 /* layout */ = { + isa = PBXGroup; + children = ( + 836F6E0018BDC2180095E648 /* aax_layout.c */, + 836F6E0118BDC2180095E648 /* aix_layout.c */, + 836F6E0218BDC2180095E648 /* ast_blocked.c */, + 836F6E0318BDC2180095E648 /* bdsp_blocked.c */, + 836F6E0418BDC2180095E648 /* blocked.c */, + 836F6E0518BDC2180095E648 /* caf_blocked.c */, + 836F6E0618BDC2180095E648 /* de2_blocked.c */, + 836F6E0718BDC2180095E648 /* ea_block.c */, + 836F6E0818BDC2180095E648 /* emff_blocked.c */, + 836F6E0918BDC2180095E648 /* filp_blocked.c */, + 836F6E0A18BDC2180095E648 /* gsb_blocked.c */, + 836F6E0B18BDC2180095E648 /* halpst_blocked.c */, + 836F6E0C18BDC2180095E648 /* ims_block.c */, + 836F6E0D18BDC2180095E648 /* interleave.c */, + 836F6E0E18BDC2180095E648 /* interleave_byte.c */, + 836F6E0F18BDC2180095E648 /* ivaud_layout.c */, + 836F6E1018BDC2180095E648 /* layout.h */, + 836F6E1118BDC2180095E648 /* Makefile.unix.am */, + 836F6E1218BDC2180095E648 /* mus_acm_layout.c */, + 836F6E1318BDC2180095E648 /* mxch_blocked.c */, + 836F6E1418BDC2180095E648 /* nolayout.c */, + 836F6E1518BDC2180095E648 /* ps2_adm_blocked.c */, + 836F6E1618BDC2180095E648 /* ps2_iab_blocked.c */, + 836F6E1718BDC2180095E648 /* ps2_strlr_blocked.c */, + 836F6E1818BDC2180095E648 /* psx_mgav_blocked.c */, + 836F6E1918BDC2180095E648 /* scd_int_layout.c */, + 836F6E1A18BDC2180095E648 /* str_snds_blocked.c */, + 836F6E1B18BDC2180095E648 /* thp_blocked.c */, + 836F6E1C18BDC2180095E648 /* tra_blocked.c */, + 836F6E1D18BDC2180095E648 /* vs_blocked.c */, + 836F6E1E18BDC2180095E648 /* ws_aud_blocked.c */, + 836F6E1F18BDC2180095E648 /* wsi_blocked.c */, + 836F6E2018BDC2180095E648 /* xa_blocked.c */, + 836F6E2118BDC2180095E648 /* xvas_block.c */, + ); + path = layout; + sourceTree = ""; + }; + 836F6E2718BDC2180095E648 /* meta */ = { + isa = PBXGroup; + children = ( + 836F6E2918BDC2180095E648 /* 2dx9.c */, + 836F6E2A18BDC2180095E648 /* aax.c */, + 836F6E2B18BDC2180095E648 /* acm.c */, + 836F6E2C18BDC2180095E648 /* ads.c */, + 836F6E2D18BDC2180095E648 /* adx_header.c */, + 836F6E2E18BDC2180095E648 /* afc_header.c */, + 836F6E2F18BDC2180095E648 /* agsc.c */, + 836F6E3018BDC2180095E648 /* ahx.c */, + 836F6E3118BDC2180095E648 /* aifc.c */, + 836F6E3218BDC2180095E648 /* aix.c */, + 836F6E3318BDC2180095E648 /* akb.c */, + 836F6E3418BDC2180095E648 /* apple_caff.c */, + 836F6E3518BDC2180095E648 /* ast.c */, + 836F6E3618BDC2180095E648 /* baf.c */, + 836F6E3718BDC2180095E648 /* bcstm.c */, + 836F6E3818BDC2180095E648 /* bgw.c */, + 836F6E3918BDC2180095E648 /* bnsf.c */, + 836F6E3A18BDC2180095E648 /* brstm.c */, + 836F6E3B18BDC2180095E648 /* capdsp.c */, + 836F6E3C18BDC2180095E648 /* Cstr.c */, + 836F6E3D18BDC2180095E648 /* dc_asd.c */, + 836F6E3E18BDC2180095E648 /* dc_dcsw_dcs.c */, + 836F6E3F18BDC2180095E648 /* dc_idvi.c */, + 836F6E4018BDC2180095E648 /* dc_kcey.c */, + 836F6E4118BDC2180095E648 /* dc_str.c */, + 836F6E4218BDC2180095E648 /* de2.c */, + 836F6E4318BDC2180095E648 /* dmsg_segh.c */, + 836F6E4418BDC2180095E648 /* dsp_bdsp.c */, + 836F6E4518BDC2180095E648 /* dsp_sth_str.c */, + 836F6E4618BDC2180095E648 /* ea_header.c */, + 836F6E4718BDC2180095E648 /* ea_old.c */, + 836F6E4818BDC2180095E648 /* emff.c */, + 836F6E4918BDC2180095E648 /* exakt_sc.c */, + 836F6E4A18BDC2180095E648 /* excitebots.c */, + 836F6E4B18BDC2180095E648 /* ffw.c */, + 836F6E4C18BDC2180095E648 /* fsb.c */, + 836F6E4D18BDC2180095E648 /* gca.c */, + 836F6E4E18BDC2180095E648 /* gcsw.c */, + 836F6E4F18BDC2180095E648 /* genh.c */, + 836F6E5018BDC2180095E648 /* gh3_bar.c */, + 836F6E5118BDC2180095E648 /* gsp_gsb.c */, + 836F6E5218BDC2180095E648 /* halpst.c */, + 836F6E5318BDC2180095E648 /* his.c */, + 836F6E5418BDC2180095E648 /* idsp.c */, + 836F6E5518BDC2180095E648 /* ios_psnd.c */, + 836F6E5618BDC2180095E648 /* ish_isd.c */, + 836F6E5718BDC2180095E648 /* ivaud.c */, + 836F6E5818BDC2180095E648 /* ivb.c */, + 836F6E5918BDC2180095E648 /* kraw.c */, + 836F6E5A18BDC2180095E648 /* lsf.c */, + 836F6E5B18BDC2180095E648 /* Makefile.unix.am */, + 836F6E5C18BDC2180095E648 /* mattel_hyperscan.c */, + 836F6E5D18BDC2180095E648 /* maxis_xa.c */, + 836F6E5E18BDC2180095E648 /* meta.h */, + 836F6E5F18BDC2180095E648 /* mn_str.c */, + 836F6E6018BDC2180095E648 /* mp4.c */, + 836F6E6118BDC2180095E648 /* msvp.c */, + 836F6E6218BDC2180095E648 /* mus_acm.c */, + 836F6E6318BDC2180095E648 /* musc.c */, + 836F6E6418BDC2180095E648 /* musx.c */, + 836F6E6518BDC2180095E648 /* myspd.c */, + 836F6E6618BDC2180095E648 /* naomi_adpcm.c */, + 836F6E6718BDC2180095E648 /* naomi_spsd.c */, + 836F6E6818BDC2180095E648 /* nds_hwas.c */, + 836F6E6918BDC2180095E648 /* nds_rrds.c */, + 836F6E6A18BDC2180095E648 /* nds_sad.c */, + 836F6E6B18BDC2180095E648 /* nds_strm.c */, + 836F6E6C18BDC2180095E648 /* nds_swav.c */, + 836F6E6D18BDC2180095E648 /* ngc_adpdtk.c */, + 836F6E6E18BDC2180095E648 /* ngc_bh2pcm.c */, + 836F6E6F18BDC2180095E648 /* ngc_bo2.c */, + 836F6E7018BDC2180095E648 /* ngc_caf.c */, + 836F6E7118BDC2180095E648 /* ngc_dsp_konami.c */, + 836F6E7218BDC2180095E648 /* ngc_dsp_mpds.c */, + 836F6E7318BDC2180095E648 /* ngc_dsp_std.c */, + 836F6E7418BDC2180095E648 /* ngc_dsp_ygo.c */, + 836F6E7518BDC2180095E648 /* ngc_ffcc_str.c */, + 836F6E7618BDC2180095E648 /* ngc_gcub.c */, + 836F6E7718BDC2180095E648 /* ngc_lps.c */, + 836F6E7818BDC2180095E648 /* ngc_nst_dsp.c */, + 836F6E7918BDC2180095E648 /* ngc_pdt.c */, + 836F6E7A18BDC2180095E648 /* ngc_sck_dsp.c */, + 836F6E7B18BDC2180095E648 /* ngc_ssm.c */, + 836F6E7C18BDC2180095E648 /* ngc_tydsp.c */, + 836F6E7D18BDC2180095E648 /* ngc_waa_wac_wad_wam.c */, + 836F6E7E18BDC2180095E648 /* ngc_ymf.c */, + 836F6E7F18BDC2180095E648 /* ngca.c */, + 836F6E8018BDC2180095E648 /* nub.c */, + 836F6E8118BDC2180095E648 /* nwa.c */, + 836F6E8218BDC2180095E648 /* ogg_vorbis_file.c */, + 836F6E8318BDC2180095E648 /* otm.c */, + 836F6E8418BDC2180095E648 /* p3d.c */, + 836F6E8518BDC2180095E648 /* pc_adp.c */, + 836F6E8618BDC2180095E648 /* pc_mxst.c */, + 836F6E8718BDC2180095E648 /* pc_smp.c */, + 836F6E8818BDC2180095E648 /* pc_snds.c */, + 836F6E8918BDC2180095E648 /* pc_sob.c */, + 836F6E8A18BDC2180095E648 /* pcm.c */, + 836F6E8B18BDC2180095E648 /* pona.c */, + 836F6E8C18BDC2180095E648 /* pos.c */, + 836F6E8D18BDC2180095E648 /* ps2_2pfs.c */, + 836F6E8E18BDC2180095E648 /* ps2_adm.c */, + 836F6E8F18BDC2180095E648 /* ps2_ads.c */, + 836F6E9018BDC2180095E648 /* ps2_adsc.c */, + 836F6E9118BDC2180095E648 /* ps2_ass.c */, + 836F6E9218BDC2180095E648 /* ps2_ast.c */, + 836F6E9318BDC2180095E648 /* ps2_aus.c */, + 836F6E9418BDC2180095E648 /* ps2_b1s.c */, + 836F6E9518BDC2180095E648 /* ps2_bg00.c */, + 836F6E9618BDC2180095E648 /* ps2_bmdx.c */, + 836F6E9718BDC2180095E648 /* ps2_ccc.c */, + 836F6E9818BDC2180095E648 /* ps2_dxh.c */, + 836F6E9918BDC2180095E648 /* ps2_enth.c */, + 836F6E9A18BDC2180095E648 /* ps2_exst.c */, + 836F6E9B18BDC2180095E648 /* ps2_filp.c */, + 836F6E9C18BDC2180095E648 /* ps2_gbts.c */, + 836F6E9D18BDC2180095E648 /* ps2_gcm.c */, + 836F6E9E18BDC2180095E648 /* ps2_hgc1.c */, + 836F6E9F18BDC2180095E648 /* ps2_hsf.c */, + 836F6EA018BDC2180095E648 /* ps2_iab.c */, + 836F6EA118BDC2180095E648 /* ps2_ikm.c */, + 836F6EA218BDC2180095E648 /* ps2_ild.c */, + 836F6EA318BDC2180095E648 /* ps2_int.c */, + 836F6EA418BDC2180095E648 /* ps2_joe.c */, + 836F6EA518BDC2180095E648 /* ps2_jstm.c */, + 836F6EA618BDC2180095E648 /* ps2_kces.c */, + 836F6EA718BDC2180095E648 /* ps2_khv.c */, + 836F6EA818BDC2180095E648 /* ps2_leg.c */, + 836F6EA918BDC2180095E648 /* ps2_lpcm.c */, + 836F6EAA18BDC2180095E648 /* ps2_mcg.c */, + 836F6EAB18BDC2180095E648 /* ps2_mib.c */, + 836F6EAC18BDC2180095E648 /* ps2_mic.c */, + 836F6EAD18BDC2180095E648 /* ps2_mihb.c */, + 836F6EAE18BDC2180095E648 /* ps2_msa.c */, + 836F6EAF18BDC2180095E648 /* ps2_mss.c */, + 836F6EB018BDC2180095E648 /* ps2_mtaf.c */, + 836F6EB118BDC2180095E648 /* ps2_npsf.c */, + 836F6EB218BDC2180095E648 /* ps2_p2bt.c */, + 836F6EB318BDC2180095E648 /* ps2_pnb.c */, + 836F6EB418BDC2180095E648 /* ps2_psh.c */, + 836F6EB518BDC2180095E648 /* ps2_psw.c */, + 836F6EB618BDC2180095E648 /* ps2_rnd.c */, + 836F6EB718BDC2180095E648 /* ps2_rstm.c */, + 836F6EB818BDC2180095E648 /* ps2_rws.c */, + 836F6EB918BDC2180095E648 /* ps2_rxw.c */, + 836F6EBA18BDC2180095E648 /* ps2_sfs.c */, + 836F6EBB18BDC2180095E648 /* ps2_sl3.c */, + 836F6EBC18BDC2180095E648 /* ps2_smpl.c */, + 836F6EBD18BDC2180095E648 /* ps2_snd.c */, + 836F6EBE18BDC2190095E648 /* ps2_spm.c */, + 836F6EBF18BDC2190095E648 /* ps2_sps.c */, + 836F6EC018BDC2190095E648 /* ps2_ster.c */, + 836F6EC118BDC2190095E648 /* ps2_stm.c */, + 836F6EC218BDC2190095E648 /* ps2_str.c */, + 836F6EC318BDC2190095E648 /* ps2_strlr.c */, + 836F6EC418BDC2190095E648 /* ps2_svag.c */, + 836F6EC518BDC2190095E648 /* ps2_tec.c */, + 836F6EC618BDC2190095E648 /* ps2_tk5.c */, + 836F6EC718BDC2190095E648 /* ps2_vag.c */, + 836F6EC818BDC2190095E648 /* ps2_vas.c */, + 836F6EC918BDC2190095E648 /* ps2_vbk.c */, + 836F6ECA18BDC2190095E648 /* ps2_vgs.c */, + 836F6ECB18BDC2190095E648 /* ps2_vgv.c */, + 836F6ECC18BDC2190095E648 /* ps2_vms.c */, + 836F6ECD18BDC2190095E648 /* ps2_voi.c */, + 836F6ECE18BDC2190095E648 /* ps2_vpk.c */, + 836F6ECF18BDC2190095E648 /* ps2_wad.c */, + 836F6ED018BDC2190095E648 /* ps2_wb.c */, + 836F6ED118BDC2190095E648 /* ps2_wmus.c */, + 836F6ED218BDC2190095E648 /* ps2_xa2.c */, + 836F6ED318BDC2190095E648 /* ps2_xa30.c */, + 836F6ED418BDC2190095E648 /* ps2_xau.c */, + 836F6ED518BDC2190095E648 /* ps3_cps.c */, + 836F6ED618BDC2190095E648 /* ps3_ivag.c */, + 836F6ED718BDC2190095E648 /* ps3_klbs.c */, + 836F6ED818BDC2190095E648 /* ps3_msf.c */, + 836F6ED918BDC2190095E648 /* ps3_past.c */, + 836F6EDA18BDC2190095E648 /* ps3_sgh_sgb.c */, + 836F6EDB18BDC2190095E648 /* ps3_vawx.c */, + 836F6EDC18BDC2190095E648 /* ps3_xvag.c */, + 836F6EDD18BDC2190095E648 /* psx_cdxa.c */, + 836F6EDE18BDC2190095E648 /* psx_fag.c */, + 836F6EDF18BDC2190095E648 /* psx_gms.c */, + 836F6EE018BDC2190095E648 /* psx_str_mgav.c */, + 836F6EE118BDC2190095E648 /* raw.c */, + 836F6EE218BDC2190095E648 /* redspark.c */, + 836F6EE318BDC2190095E648 /* riff.c */, + 836F6EE418BDC2190095E648 /* rkv.c */, + 836F6EE518BDC2190095E648 /* rs03.c */, + 836F6EE618BDC2190095E648 /* rsd.c */, + 836F6EE718BDC2190095E648 /* rsf.c */, + 836F6EE818BDC2190095E648 /* rwsd.c */, + 836F6EE918BDC2190095E648 /* rwx.c */, + 836F6EEA18BDC2190095E648 /* s14_sss.c */, + 836F6EEB18BDC2190095E648 /* sat_baka.c */, + 836F6EEC18BDC2190095E648 /* sat_dvi.c */, + 836F6EED18BDC2190095E648 /* sat_sap.c */, + 836F6EEE18BDC2190095E648 /* sd9.c */, + 836F6EEF18BDC2190095E648 /* sdt.c */, + 836F6EF018BDC2190095E648 /* seg.c */, + 836F6EF118BDC2190095E648 /* sfl.c */, + 836F6EF218BDC2190095E648 /* sli.c */, + 836F6EF318BDC2190095E648 /* spt_spd.c */, + 836F6EF418BDC2190095E648 /* sqex_scd.c */, + 836F6EF518BDC2190095E648 /* ss_stream.c */, + 836F6EF618BDC2190095E648 /* str_asr.c */, + 836F6EF718BDC2190095E648 /* str_snds.c */, + 836F6EF818BDC2190095E648 /* stx.c */, + 836F6EF918BDC2190095E648 /* svs.c */, + 836F6EFA18BDC2190095E648 /* thp.c */, + 836F6EFB18BDC2190095E648 /* tun.c */, + 836F6EFC18BDC2190095E648 /* ubi_ckd.c */, + 836F6EFD18BDC2190095E648 /* vgs.c */, + 836F6EFE18BDC2190095E648 /* vs.c */, + 836F6EFF18BDC2190095E648 /* vsf.c */, + 836F6F0018BDC2190095E648 /* wii_bns.c */, + 836F6F0118BDC2190095E648 /* wii_mus.c */, + 836F6F0218BDC2190095E648 /* wii_ras.c */, + 836F6F0318BDC2190095E648 /* wii_smp.c */, + 836F6F0418BDC2190095E648 /* wii_sng.c */, + 836F6F0518BDC2190095E648 /* wii_str.c */, + 836F6F0618BDC2190095E648 /* wii_sts.c */, + 836F6F0718BDC2190095E648 /* wpd.c */, + 836F6F0818BDC2190095E648 /* ws_aud.c */, + 836F6F0918BDC2190095E648 /* wvs.c */, + 836F6F0A18BDC2190095E648 /* x360_tra.c */, + 836F6F0B18BDC2190095E648 /* xbox_hlwav.c */, + 836F6F0C18BDC2190095E648 /* xbox_ims.c */, + 836F6F0D18BDC2190095E648 /* xbox_stma.c */, + 836F6F0E18BDC2190095E648 /* xbox_wavm.c */, + 836F6F0F18BDC2190095E648 /* xbox_xmu.c */, + 836F6F1018BDC2190095E648 /* xbox_xvas.c */, + 836F6F1118BDC2190095E648 /* xbox_xwav.c */, + 836F6F1218BDC2190095E648 /* xss.c */, + 836F6F1318BDC2190095E648 /* xwb.c */, + 836F6F1418BDC2190095E648 /* ydsp.c */, + 836F6F1518BDC2190095E648 /* zsd.c */, + 836F6F1618BDC2190095E648 /* zwdsp.c */, + ); + path = meta; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 836F6B3618BDB8880095E648 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F705518BDC2190095E648 /* streamtypes.h in Headers */, + 836F6F1F18BDC2190095E648 /* acm_decoder.h in Headers */, + 836F6F3518BDC2190095E648 /* nwa_decoder.h in Headers */, + 836F6F2718BDC2190095E648 /* g72x_state.h in Headers */, + 836F705418BDC2190095E648 /* streamfile.h in Headers */, + 836F705918BDC2190095E648 /* vgmstream.h in Headers */, + 836F705718BDC2190095E648 /* util.h in Headers */, + 836F6F9A18BDC2190095E648 /* meta.h in Headers */, + 836F6F4D18BDC2190095E648 /* layout.h in Headers */, + 836F6F2318BDC2190095E648 /* coding.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 836F6B3818BDB8880095E648 /* vgmstream */ = { + isa = PBXNativeTarget; + buildConfigurationList = 836F6B6118BDB8880095E648 /* Build configuration list for PBXNativeTarget "vgmstream" */; + buildPhases = ( + 836F6B3418BDB8880095E648 /* Sources */, + 836F6B3518BDB8880095E648 /* Frameworks */, + 836F6B3618BDB8880095E648 /* Headers */, + 836F6B3718BDB8880095E648 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = vgmstream; + productName = vgmstream; + productReference = 836F6B3918BDB8880095E648 /* vgmstream.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 836F6B3018BDB8880095E648 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Christopher Snowhill"; + }; + buildConfigurationList = 836F6B3318BDB8880095E648 /* Build configuration list for PBXProject "vgmstream" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 836F6B2F18BDB8880095E648; + productRefGroup = 836F6B3A18BDB8880095E648 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 836F6B3818BDB8880095E648 /* vgmstream */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 836F6B3718BDB8880095E648 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F6F9718BDC2190095E648 /* Makefile.unix.am in Resources */, + 836F6B4718BDB8880095E648 /* InfoPlist.strings in Resources */, + 836F6F4E18BDC2190095E648 /* Makefile.unix.am in Resources */, + 836F6F2B18BDC2190095E648 /* Makefile.unix.am in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 836F6B3418BDB8880095E648 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F6FAD18BDC2190095E648 /* ngc_dsp_konami.c in Sources */, + 836F6FF818BDC2190095E648 /* ps2_smpl.c in Sources */, + 836F6F8118BDC2190095E648 /* dsp_sth_str.c in Sources */, + 836F6F5E18BDC2190095E648 /* xvas_block.c in Sources */, + 836F703818BDC2190095E648 /* ubi_ckd.c in Sources */, + 836F705318BDC2190095E648 /* streamfile.c in Sources */, + 836F6F5C18BDC2190095E648 /* wsi_blocked.c in Sources */, + 836F6F7418BDC2190095E648 /* bgw.c in Sources */, + 836F6F7218BDC2190095E648 /* baf.c in Sources */, + 836F6F4B18BDC2190095E648 /* interleave_byte.c in Sources */, + 836F6FD418BDC2190095E648 /* ps2_dxh.c in Sources */, + 836F700C18BDC2190095E648 /* ps2_wb.c in Sources */, + 836F6F7D18BDC2190095E648 /* dc_str.c in Sources */, + 836F701718BDC2190095E648 /* ps3_vawx.c in Sources */, + 836F702018BDC2190095E648 /* rkv.c in Sources */, + 836F703218BDC2190095E648 /* str_asr.c in Sources */, + 836F6FB218BDC2190095E648 /* ngc_gcub.c in Sources */, + 836F702818BDC2190095E648 /* sat_dvi.c in Sources */, + 836F6F2F18BDC2190095E648 /* mtaf_decoder.c in Sources */, + 836F6F9B18BDC2190095E648 /* mn_str.c in Sources */, + 836F6F5918BDC2190095E648 /* tra_blocked.c in Sources */, + 836F6F9F18BDC2190095E648 /* musc.c in Sources */, + 836F701818BDC2190095E648 /* ps3_xvag.c in Sources */, + 836F6FCA18BDC2190095E648 /* ps2_adm.c in Sources */, + 836F6FA118BDC2190095E648 /* myspd.c in Sources */, + 836F6FD718BDC2190095E648 /* ps2_filp.c in Sources */, + 836F703418BDC2190095E648 /* stx.c in Sources */, + 836F6F7018BDC2190095E648 /* apple_caff.c in Sources */, + 836F700018BDC2190095E648 /* ps2_svag.c in Sources */, + 836F6FB618BDC2190095E648 /* ngc_sck_dsp.c in Sources */, + 836F6F2818BDC2190095E648 /* ima_decoder.c in Sources */, + 836F702318BDC2190095E648 /* rsf.c in Sources */, + 836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */, + 836F6FBB18BDC2190095E648 /* ngca.c in Sources */, + 836F6F5218BDC2190095E648 /* ps2_adm_blocked.c in Sources */, + 836F6F9418BDC2190095E648 /* ivb.c in Sources */, + 836F6FF118BDC2190095E648 /* ps2_psw.c in Sources */, + 836F6F8D18BDC2190095E648 /* gsp_gsb.c in Sources */, + 836F704518BDC2190095E648 /* wvs.c in Sources */, + 836F6F2218BDC2190095E648 /* at3_decoder.c in Sources */, + 836F6FFC18BDC2190095E648 /* ps2_ster.c in Sources */, + 836F701E18BDC2190095E648 /* redspark.c in Sources */, + 836F6FA018BDC2190095E648 /* musx.c in Sources */, + 836F705818BDC2190095E648 /* vgmstream.c in Sources */, + 836F6F6818BDC2190095E648 /* ads.c in Sources */, + 836F6F8B18BDC2190095E648 /* genh.c in Sources */, + 836F705118BDC2190095E648 /* zsd.c in Sources */, + 836F6FD218BDC2190095E648 /* ps2_bmdx.c in Sources */, + 836F703C18BDC2190095E648 /* wii_bns.c in Sources */, + 836F6FA718BDC2190095E648 /* nds_strm.c in Sources */, + 836F6F6E18BDC2190095E648 /* aix.c in Sources */, + 836F703118BDC2190095E648 /* ss_stream.c in Sources */, + 836F701018BDC2190095E648 /* ps2_xau.c in Sources */, + 836F6F8718BDC2190095E648 /* ffw.c in Sources */, + 836F6FE418BDC2190095E648 /* ps2_leg.c in Sources */, + 836F705618BDC2190095E648 /* util.c in Sources */, + 836F703618BDC2190095E648 /* thp.c in Sources */, + 836F6F7818BDC2190095E648 /* Cstr.c in Sources */, + 836F6F1E18BDC2190095E648 /* acm_decoder.c in Sources */, + 836F6FD818BDC2190095E648 /* ps2_gbts.c in Sources */, + 836F6F2418BDC2190095E648 /* eaxa_decoder.c in Sources */, + 836F6F7A18BDC2190095E648 /* dc_dcsw_dcs.c in Sources */, + 836F6F5318BDC2190095E648 /* ps2_iab_blocked.c in Sources */, + 836F6FF218BDC2190095E648 /* ps2_rnd.c in Sources */, + 836F6FA818BDC2190095E648 /* nds_swav.c in Sources */, + 836F6F3F18BDC2190095E648 /* ast_blocked.c in Sources */, + 836F6F5018BDC2190095E648 /* mxch_blocked.c in Sources */, + 836F6FB518BDC2190095E648 /* ngc_pdt.c in Sources */, + 836F6F4F18BDC2190095E648 /* mus_acm_layout.c in Sources */, + 836F6F4218BDC2190095E648 /* caf_blocked.c in Sources */, + 836F6F6C18BDC2190095E648 /* ahx.c in Sources */, + 836F702D18BDC2190095E648 /* sfl.c in Sources */, + 836F6FEC18BDC2190095E648 /* ps2_mtaf.c in Sources */, + 836F701118BDC2190095E648 /* ps3_cps.c in Sources */, + 836F701418BDC2190095E648 /* ps3_msf.c in Sources */, + 836F6F6518BDC2190095E648 /* 2dx9.c in Sources */, + 836F700818BDC2190095E648 /* ps2_vms.c in Sources */, + 836F702418BDC2190095E648 /* rwsd.c in Sources */, + 836F6F7E18BDC2190095E648 /* de2.c in Sources */, + 836F6F5618BDC2190095E648 /* scd_int_layout.c in Sources */, + 836F6F6618BDC2190095E648 /* aax.c in Sources */, + 836F6F4C18BDC2190095E648 /* ivaud_layout.c in Sources */, + 836F6FD618BDC2190095E648 /* ps2_exst.c in Sources */, + 836F6F6718BDC2190095E648 /* acm.c in Sources */, + 836F6F8A18BDC2190095E648 /* gcsw.c in Sources */, + 836F6F9C18BDC2190095E648 /* mp4.c in Sources */, + 836F704918BDC2190095E648 /* xbox_stma.c in Sources */, + 836F700F18BDC2190095E648 /* ps2_xa30.c in Sources */, + 836F6F6F18BDC2190095E648 /* akb.c in Sources */, + 836F6F7F18BDC2190095E648 /* dmsg_segh.c in Sources */, + 836F6F8F18BDC2190095E648 /* his.c in Sources */, + 836F6FE218BDC2190095E648 /* ps2_kces.c in Sources */, + 836F6FEF18BDC2190095E648 /* ps2_pnb.c in Sources */, + 836F6FCB18BDC2190095E648 /* ps2_ads.c in Sources */, + 836F6FD318BDC2190095E648 /* ps2_ccc.c in Sources */, + 836F704C18BDC2190095E648 /* xbox_xvas.c in Sources */, + 836F6F3918BDC2190095E648 /* SASSC_decoder.c in Sources */, + 836F703A18BDC2190095E648 /* vs.c in Sources */, + 836F6FF918BDC2190095E648 /* ps2_snd.c in Sources */, + 836F6F9018BDC2190095E648 /* idsp.c in Sources */, + 836F6F2918BDC2190095E648 /* l5_555_decoder.c in Sources */, + 836F6FF318BDC2190095E648 /* ps2_rstm.c in Sources */, + 836F6FCC18BDC2190095E648 /* ps2_adsc.c in Sources */, + 836F6F7918BDC2190095E648 /* dc_asd.c in Sources */, + 836F6FC118BDC2190095E648 /* pc_adp.c in Sources */, + 836F6F8318BDC2190095E648 /* ea_old.c in Sources */, + 836F701A18BDC2190095E648 /* psx_fag.c in Sources */, + 836F703B18BDC2190095E648 /* vsf.c in Sources */, + 836F6F3D18BDC2190095E648 /* aax_layout.c in Sources */, + 836F6F8218BDC2190095E648 /* ea_header.c in Sources */, + 836F700A18BDC2190095E648 /* ps2_vpk.c in Sources */, + 836F6F7318BDC2190095E648 /* bcstm.c in Sources */, + 836F704018BDC2190095E648 /* wii_sng.c in Sources */, + 836F6F3218BDC2190095E648 /* ngc_dsp_decoder.c in Sources */, + 836F704218BDC2190095E648 /* wii_sts.c in Sources */, + 836F703918BDC2190095E648 /* vgs.c in Sources */, + 836F6F2C18BDC2190095E648 /* mp4_aac_decoder.c in Sources */, + 836F701F18BDC2190095E648 /* riff.c in Sources */, + 836F6F9318BDC2190095E648 /* ivaud.c in Sources */, + 836F6F8518BDC2190095E648 /* exakt_sc.c in Sources */, + 836F6FA618BDC2190095E648 /* nds_sad.c in Sources */, + 836F702B18BDC2190095E648 /* sdt.c in Sources */, + 836F6FDA18BDC2190095E648 /* ps2_hgc1.c in Sources */, + 836F702C18BDC2190095E648 /* seg.c in Sources */, + 836F6F6A18BDC2190095E648 /* afc_header.c in Sources */, + 836F700918BDC2190095E648 /* ps2_voi.c in Sources */, + 836F6F3E18BDC2190095E648 /* aix_layout.c in Sources */, + 836F6FE018BDC2190095E648 /* ps2_joe.c in Sources */, + 836F700118BDC2190095E648 /* ps2_tec.c in Sources */, + 836F6F4718BDC2190095E648 /* gsb_blocked.c in Sources */, + 836F703018BDC2190095E648 /* sqex_scd.c in Sources */, + 836F6FD518BDC2190095E648 /* ps2_enth.c in Sources */, + 836F6FAE18BDC2190095E648 /* ngc_dsp_mpds.c in Sources */, + 836F705218BDC2190095E648 /* zwdsp.c in Sources */, + 836F6FFB18BDC2190095E648 /* ps2_sps.c in Sources */, + 836F6FFF18BDC2190095E648 /* ps2_strlr.c in Sources */, + 836F6F5518BDC2190095E648 /* psx_mgav_blocked.c in Sources */, + 836F6F2018BDC2190095E648 /* adx_decoder.c in Sources */, + 836F6FCF18BDC2190095E648 /* ps2_aus.c in Sources */, + 836F6F4018BDC2190095E648 /* bdsp_blocked.c in Sources */, + 836F700418BDC2190095E648 /* ps2_vas.c in Sources */, + 836F6F9818BDC2190095E648 /* mattel_hyperscan.c in Sources */, + 836F704418BDC2190095E648 /* ws_aud.c in Sources */, + 836F6FBC18BDC2190095E648 /* nub.c in Sources */, + 836F6F6D18BDC2190095E648 /* aifc.c in Sources */, + 836F702218BDC2190095E648 /* rsd.c in Sources */, + 836F6FC618BDC2190095E648 /* pcm.c in Sources */, + 836F702518BDC2190095E648 /* rwx.c in Sources */, + 836F6F3A18BDC2190095E648 /* sdx2_decoder.c in Sources */, + 836F6FAF18BDC2190095E648 /* ngc_dsp_std.c in Sources */, + 836F6F7118BDC2190095E648 /* ast.c in Sources */, + 836F6FE318BDC2190095E648 /* ps2_khv.c in Sources */, + 836F701318BDC2190095E648 /* ps3_klbs.c in Sources */, + 836F6F5818BDC2190095E648 /* thp_blocked.c in Sources */, + 836F6F6B18BDC2190095E648 /* agsc.c in Sources */, + 836F6FF018BDC2190095E648 /* ps2_psh.c in Sources */, + 836F700E18BDC2190095E648 /* ps2_xa2.c in Sources */, + 836F6FF718BDC2190095E648 /* ps2_sl3.c in Sources */, + 836F6F3118BDC2190095E648 /* ngc_afc_decoder.c in Sources */, + 836F6FE718BDC2190095E648 /* ps2_mib.c in Sources */, + 836F6FAB18BDC2190095E648 /* ngc_bo2.c in Sources */, + 836F6F9918BDC2190095E648 /* maxis_xa.c in Sources */, + 836F702118BDC2190095E648 /* rs03.c in Sources */, + 836F6F8418BDC2190095E648 /* emff.c in Sources */, + 836F704118BDC2190095E648 /* wii_str.c in Sources */, + 836F6F8818BDC2190095E648 /* fsb.c in Sources */, + 836F6F4618BDC2190095E648 /* filp_blocked.c in Sources */, + 836F6FE518BDC2190095E648 /* ps2_lpcm.c in Sources */, + 836F6FB318BDC2190095E648 /* ngc_lps.c in Sources */, + 836F6FC018BDC2190095E648 /* p3d.c in Sources */, + 836F6FC718BDC2190095E648 /* pona.c in Sources */, + 836F6FE618BDC2190095E648 /* ps2_mcg.c in Sources */, + 836F6FB918BDC2190095E648 /* ngc_waa_wac_wad_wam.c in Sources */, + 836F6F5118BDC2190095E648 /* nolayout.c in Sources */, + 836F702918BDC2190095E648 /* sat_sap.c in Sources */, + 836F6F3718BDC2190095E648 /* pcm_decoder.c in Sources */, + 836F6F5B18BDC2190095E648 /* ws_aud_blocked.c in Sources */, + 836F700218BDC2190095E648 /* ps2_tk5.c in Sources */, + 836F703F18BDC2190095E648 /* wii_smp.c in Sources */, + 836F6FB818BDC2190095E648 /* ngc_tydsp.c in Sources */, + 836F701518BDC2190095E648 /* ps3_past.c in Sources */, + 836F6F7C18BDC2190095E648 /* dc_kcey.c in Sources */, + 836F6FED18BDC2190095E648 /* ps2_npsf.c in Sources */, + 836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */, + 836F6FCD18BDC2190095E648 /* ps2_ass.c in Sources */, + 836F6FFE18BDC2190095E648 /* ps2_str.c in Sources */, + 836F6F4A18BDC2190095E648 /* interleave.c in Sources */, + 836F6FFD18BDC2190095E648 /* ps2_stm.c in Sources */, + 836F6FA518BDC2190095E648 /* nds_rrds.c in Sources */, + 836F702F18BDC2190095E648 /* spt_spd.c in Sources */, + 836F704618BDC2190095E648 /* x360_tra.c in Sources */, + 836F6FFA18BDC2190095E648 /* ps2_spm.c in Sources */, + 836F701918BDC2190095E648 /* psx_cdxa.c in Sources */, + 836F6FC318BDC2190095E648 /* pc_smp.c in Sources */, + 836F6FCE18BDC2190095E648 /* ps2_ast.c in Sources */, + 836F6FEB18BDC2190095E648 /* ps2_mss.c in Sources */, + 836F6F5418BDC2190095E648 /* ps2_strlr_blocked.c in Sources */, + 836F703D18BDC2190095E648 /* wii_mus.c in Sources */, + 836F700D18BDC2190095E648 /* ps2_wmus.c in Sources */, + 836F6F8018BDC2190095E648 /* dsp_bdsp.c in Sources */, + 836F6F9618BDC2190095E648 /* lsf.c in Sources */, + 836F6FC818BDC2190095E648 /* pos.c in Sources */, + 836F6F8918BDC2190095E648 /* gca.c in Sources */, + 836F6F5718BDC2190095E648 /* str_snds_blocked.c in Sources */, + 836F6FA418BDC2190095E648 /* nds_hwas.c in Sources */, + 836F6FD018BDC2190095E648 /* ps2_b1s.c in Sources */, + 836F701218BDC2190095E648 /* ps3_ivag.c in Sources */, + 836F6F7718BDC2190095E648 /* capdsp.c in Sources */, + 836F6FB018BDC2190095E648 /* ngc_dsp_ygo.c in Sources */, + 836F703318BDC2190095E648 /* str_snds.c in Sources */, + 836F703718BDC2190095E648 /* tun.c in Sources */, + 836F700B18BDC2190095E648 /* ps2_wad.c in Sources */, + 836F702A18BDC2190095E648 /* sd9.c in Sources */, + 836F6FB418BDC2190095E648 /* ngc_nst_dsp.c in Sources */, + 836F6F4418BDC2190095E648 /* ea_block.c in Sources */, + 836F6FDB18BDC2190095E648 /* ps2_hsf.c in Sources */, + 836F6FF618BDC2190095E648 /* ps2_sfs.c in Sources */, + 836F6F9518BDC2190095E648 /* kraw.c in Sources */, + 836F6FB718BDC2190095E648 /* ngc_ssm.c in Sources */, + 836F704A18BDC2190095E648 /* xbox_wavm.c in Sources */, + 836F6F8618BDC2190095E648 /* excitebots.c in Sources */, + 836F6FF418BDC2190095E648 /* ps2_rws.c in Sources */, + 836F6F2518BDC2190095E648 /* g721_decoder.c in Sources */, + 836F6FE818BDC2190095E648 /* ps2_mic.c in Sources */, + 836F6F3C18BDC2190095E648 /* xa_decoder.c in Sources */, + 836F6F9118BDC2190095E648 /* ios_psnd.c in Sources */, + 836F700618BDC2190095E648 /* ps2_vgs.c in Sources */, + 836F6F2118BDC2190095E648 /* aica_decoder.c in Sources */, + 836F700318BDC2190095E648 /* ps2_vag.c in Sources */, + 836F6FAA18BDC2190095E648 /* ngc_bh2pcm.c in Sources */, + 836F6F4318BDC2190095E648 /* de2_blocked.c in Sources */, + 836F6F3018BDC2190095E648 /* nds_procyon_decoder.c in Sources */, + 836F6F5A18BDC2190095E648 /* vs_blocked.c in Sources */, + 836F6FB118BDC2190095E648 /* ngc_ffcc_str.c in Sources */, + 836F6FC218BDC2190095E648 /* pc_mxst.c in Sources */, + 836F6FC918BDC2190095E648 /* ps2_2pfs.c in Sources */, + 836F704818BDC2190095E648 /* xbox_ims.c in Sources */, + 836F6F4918BDC2190095E648 /* ims_block.c in Sources */, + 836F6F7518BDC2190095E648 /* bnsf.c in Sources */, + 836F704318BDC2190095E648 /* wpd.c in Sources */, + 836F6FE118BDC2190095E648 /* ps2_jstm.c in Sources */, + 836F6FD918BDC2190095E648 /* ps2_gcm.c in Sources */, + 836F6F8E18BDC2190095E648 /* halpst.c in Sources */, + 836F6FEE18BDC2190095E648 /* ps2_p2bt.c in Sources */, + 836F6FBE18BDC2190095E648 /* ogg_vorbis_file.c in Sources */, + 836F702618BDC2190095E648 /* s14_sss.c in Sources */, + 836F6F4818BDC2190095E648 /* halpst_blocked.c in Sources */, + 836F702E18BDC2190095E648 /* sli.c in Sources */, + 836F701D18BDC2190095E648 /* raw.c in Sources */, + 836F6FDE18BDC2190095E648 /* ps2_ild.c in Sources */, + 836F703E18BDC2190095E648 /* wii_ras.c in Sources */, + 836F6FF518BDC2190095E648 /* ps2_rxw.c in Sources */, + 836F6FEA18BDC2190095E648 /* ps2_msa.c in Sources */, + 836F701618BDC2190095E648 /* ps3_sgh_sgb.c in Sources */, + 836F6F3618BDC2190095E648 /* ogg_vorbis_decoder.c in Sources */, + 836F704718BDC2190095E648 /* xbox_hlwav.c in Sources */, + 836F701C18BDC2190095E648 /* psx_str_mgav.c in Sources */, + 836F6F7618BDC2190095E648 /* brstm.c in Sources */, + 836F700718BDC2190095E648 /* ps2_vgv.c in Sources */, + 836F704F18BDC2190095E648 /* xwb.c in Sources */, + 836F6FC518BDC2190095E648 /* pc_sob.c in Sources */, + 836F6FE918BDC2190095E648 /* ps2_mihb.c in Sources */, + 836F6FA918BDC2190095E648 /* ngc_adpdtk.c in Sources */, + 836F6FDC18BDC2190095E648 /* ps2_iab.c in Sources */, + 836F6FAC18BDC2190095E648 /* ngc_caf.c in Sources */, + 836F6F3818BDC2190095E648 /* psx_decoder.c in Sources */, + 836F6F2D18BDC2190095E648 /* mpeg_decoder.c in Sources */, + 836F6F2618BDC2190095E648 /* g7221_decoder.c in Sources */, + 836F6FA218BDC2190095E648 /* naomi_adpcm.c in Sources */, + 836F6FBF18BDC2190095E648 /* otm.c in Sources */, + 836F6FDD18BDC2190095E648 /* ps2_ikm.c in Sources */, + 836F6FBD18BDC2190095E648 /* nwa.c in Sources */, + 836F6FC418BDC2190095E648 /* pc_snds.c in Sources */, + 836F704E18BDC2190095E648 /* xss.c in Sources */, + 836F6FD118BDC2190095E648 /* ps2_bg00.c in Sources */, + 836F6F4118BDC2190095E648 /* blocked.c in Sources */, + 836F6F3B18BDC2190095E648 /* ws_decoder.c in Sources */, + 836F6F4518BDC2190095E648 /* emff_blocked.c in Sources */, + 836F6F5D18BDC2190095E648 /* xa_blocked.c in Sources */, + 836F6F3418BDC2190095E648 /* nwa_decoder.c in Sources */, + 836F6F6918BDC2190095E648 /* adx_header.c in Sources */, + 836F6F2E18BDC2190095E648 /* msadpcm_decoder.c in Sources */, + 836F6F9218BDC2190095E648 /* ish_isd.c in Sources */, + 836F6F2A18BDC2190095E648 /* lsf_decoder.c in Sources */, + 836F703518BDC2190095E648 /* svs.c in Sources */, + 836F6FA318BDC2190095E648 /* naomi_spsd.c in Sources */, + 836F6F9D18BDC2190095E648 /* msvp.c in Sources */, + 836F6FBA18BDC2190095E648 /* ngc_ymf.c in Sources */, + 836F705018BDC2190095E648 /* ydsp.c in Sources */, + 836F702718BDC2190095E648 /* sat_baka.c in Sources */, + 836F6F8C18BDC2190095E648 /* gh3_bar.c in Sources */, + 836F704B18BDC2190095E648 /* xbox_xmu.c in Sources */, + 836F701B18BDC2190095E648 /* psx_gms.c in Sources */, + 836F700518BDC2190095E648 /* ps2_vbk.c in Sources */, + 836F6FDF18BDC2190095E648 /* ps2_int.c in Sources */, + 836F704D18BDC2190095E648 /* xbox_xwav.c in Sources */, + 836F6F7B18BDC2190095E648 /* dc_idvi.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 836F6B4518BDB8880095E648 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 836F6B4618BDB8880095E648 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 836F6B5F18BDB8880095E648 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + BUILD_VGMSTREAM, + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "@loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 836F6B6018BDB8880095E648 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_PREPROCESSOR_DEFINITIONS = BUILD_VGMSTREAM; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = "@loader_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 836F6B6218BDB8880095E648 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "vgmstream/vgmstream-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = framework; + }; + name = Debug; + }; + 836F6B6318BDB8880095E648 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + FRAMEWORK_VERSION = A; + INFOPLIST_FILE = "vgmstream/vgmstream-Info.plist"; + PRODUCT_NAME = "$(TARGET_NAME)"; + WRAPPER_EXTENSION = framework; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 836F6B3318BDB8880095E648 /* Build configuration list for PBXProject "vgmstream" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836F6B5F18BDB8880095E648 /* Debug */, + 836F6B6018BDB8880095E648 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 836F6B6118BDB8880095E648 /* Build configuration list for PBXNativeTarget "vgmstream" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836F6B6218BDB8880095E648 /* Debug */, + 836F6B6318BDB8880095E648 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 836F6B3018BDB8880095E648 /* Project object */; +} diff --git a/Frameworks/vgmstream/vgmstream/en.lproj/InfoPlist.strings b/Frameworks/vgmstream/vgmstream/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Frameworks/vgmstream/vgmstream/src/coding/Makefile.unix.am b/Frameworks/vgmstream/vgmstream/src/coding/Makefile.unix.am new file mode 100644 index 000000000..12380feb0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/Makefile.unix.am @@ -0,0 +1,33 @@ +noinst_LTLIBRARIES = libcoding.la + +AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir) +AM_MAKEFLAGS=-f Makefile.unix + +libcoding_la_LDFLAGS = +libcoding_la_SOURCES = +libcoding_la_SOURCES += adx_decoder.c +libcoding_la_SOURCES += eaxa_decoder.c +libcoding_la_SOURCES += g721_decoder.c +libcoding_la_SOURCES += ima_decoder.c +libcoding_la_SOURCES += ngc_afc_decoder.c +libcoding_la_SOURCES += ngc_dsp_decoder.c +libcoding_la_SOURCES += ngc_dtk_decoder.c +libcoding_la_SOURCES += pcm_decoder.c +libcoding_la_SOURCES += psx_decoder.c +libcoding_la_SOURCES += xa_decoder.c +libcoding_la_SOURCES += ogg_vorbis_decoder.c +libcoding_la_SOURCES += sdx2_decoder.c +libcoding_la_SOURCES += ws_decoder.c +libcoding_la_SOURCES += mpeg_decoder.c +libcoding_la_SOURCES += acm_decoder.c +libcoding_la_SOURCES += nwa_decoder.c +libcoding_la_SOURCES += aica_decoder.c +libcoding_la_SOURCES += msadpcm_decoder.c +libcoding_la_SOURCES += nds_procyon_decoder.c +libcoding_la_SOURCES += l5_555_decoder.c +libcoding_la_SOURCES += SASSC_decoder.c +libcoding_la_SOURCES += g7221_decoder.c +libcoding_la_SOURCES += lsf_decoder.c +libcoding_la_SOURCES += mtaf_decoder.c + +EXTRA_DIST = coding.h g72x_state.h diff --git a/Frameworks/vgmstream/vgmstream/src/coding/SASSC_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/SASSC_decoder.c new file mode 100644 index 000000000..f3912286e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/SASSC_decoder.c @@ -0,0 +1,77 @@ +#include "coding.h" +#include "../util.h" + +/* Activision / EXAKT Entertainment's DPCM for Supercar Street Challenge */ + +#if 0 + +To build table: + +int32_t bring_round(int32_t v) +{ + return v | (v >> 12); +} + +for (i=0x00;i<0x20;i++) + SASSC_steps[i] = bring_round(i<<4); +for (i=0x20;i<0x40;i++) + SASSC_steps[i] = bring_round(((i-0x20)*7+0x20)<<4); +for (i=0x40;i<0x60;i++) + SASSC_steps[i] = bring_round(((i-0x40)*24+0x100)<<4); +for (i=0x60;i<0x80;i++) + SASSC_steps[i] = bring_round(((i-0x60)*96+0x400)<<4); + +for (i=0x80;i<0xFF;i++) + SASSC_steps[i] = -SASSC_steps[i-0x80]; + +SASSC_steps[0xFF] = SASSC_steps[0x7F]; +#endif +int32_t SASSC_steps[256] = +{ + 0, 16, 32, 48, 64, 80, 96, 112, + 128, 144, 160, 176, 192, 208, 224, 240, + 256, 272, 288, 304, 320, 336, 352, 368, + 384, 400, 416, 432, 448, 464, 480, 496, + 512, 624, 736, 848, 960, 1072, 1184, 1296, + 1408, 1520, 1632, 1744, 1856, 1968, 2080, 2192, + 2304, 2416, 2528, 2640, 2752, 2864, 2976, 3088, + 3200, 3312, 3424, 3536, 3648, 3760, 3872, 3984, + 4097, 4481, 4865, 5249, 5633, 6017, 6401, 6785, + 7169, 7553, 7937, 8322, 8706, 9090, 9474, 9858, + 10242, 10626, 11010, 11394, 11778, 12162, 12547, 12931, + 13315, 13699, 14083, 14467, 14851, 15235, 15619, 16003, + 16388, 17924, 19460, 20997, 22533, 24069, 25606, 27142, + 28679, 30215, 31751, 33288, 34824, 36360, 37897, 39433, + 40970, 42506, 44042, 45579, 47115, 48651, 50188, 51724, + 53261, 54797, 56333, 57870, 59406, 60942, 62479, 64015, + + 0, -16, -32, -48, -64, -80, -96, -112, + -128, -144, -160, -176, -192, -208, -224, -240, + -256, -272, -288, -304, -320, -336, -352, -368, + -384, -400, -416, -432, -448, -464, -480, -496, + -512, -624, -736, -848, -960, -1072, -1184, -1296, + -1408, -1520, -1632, -1744, -1856, -1968, -2080, -2192, + -2304, -2416, -2528, -2640, -2752, -2864, -2976, -3088, + -3200, -3312, -3424, -3536, -3648, -3760, -3872, -3984, + -4097, -4481, -4865, -5249, -5633, -6017, -6401, -6785, + -7169, -7553, -7937, -8322, -8706, -9090, -9474, -9858, + -10242, -10626, -11010, -11394, -11778, -12162, -12547, -12931, + -13315, -13699, -14083, -14467, -14851, -15235, -15619, -16003, + -16388, -17924, -19460, -20997, -22533, -24069, -25606, -27142, + -28679, -30215, -31751, -33288, -34824, -36360, -37897, -39433, + -40970, -42506, -44042, -45579, -47115, -48651, -50188, -51724, + -53261, -54797, -56333, -57870, -59406, -60942, -62479, 64015, +}; + +void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + int32_t hist = stream->adpcm_history1_32; + + for(i=first_sample,sample_count=0; ioffset+i,stream->streamfile)]; + outbuf[sample_count] = clamp16(hist); + } + + stream->adpcm_history1_32 = hist; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.c new file mode 100644 index 000000000..edc53d742 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.c @@ -0,0 +1,839 @@ +/* + * ACM decoder. + * + * Copyright (c) 2004-2008, Marko Kreen + * Copyright (c) 2008, Adam Gashlin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "coding.h" +#include "../vgmstream.h" +#include "../streamtypes.h" +#include "acm_decoder.h" + +#define ACM_EXPECTED_EOF -99 + +typedef int (*filler_t)(ACMStream *acm, unsigned ind, unsigned col); + +/************************************** + * Stream processing + **************************************/ + +/* NB: bits <= 31! Thus less checks in code. */ + +static int get_bits_reload(ACMStream *acm, unsigned bits) +{ + int got; + unsigned data, b_data, b_avail; + + data = acm->bit_data; + got = acm->bit_avail; + bits -= got; + + switch (acm->data_len - acm->buf_start_ofs) { + case 0: + b_data = 0; + b_avail = 8; + break; + case 1: + b_data = (uint8_t)read_8bit(acm->buf_start_ofs,acm->streamfile); + b_avail = 8; + acm->buf_start_ofs += 1; + break; + case 2: + b_data = (uint16_t)read_16bitLE(acm->buf_start_ofs,acm->streamfile); + b_avail = 16; + acm->buf_start_ofs += 2; + break; + case 3: + b_data = (uint8_t)read_8bit(acm->buf_start_ofs,acm->streamfile); + b_data |= (int32_t)(uint16_t)read_16bitLE(acm->buf_start_ofs+1,acm->streamfile)<<8; + b_avail = 24; + acm->buf_start_ofs += 3; + break; + case 4: + default: + if (acm->data_len - acm->buf_start_ofs <= 0) { + b_data = 0; + b_avail = 8; + break; + } + + b_data = read_32bitLE(acm->buf_start_ofs,acm->streamfile); + b_avail = 32; + acm->buf_start_ofs += 4; + break; + } + + data |= (b_data & ((1 << bits) - 1)) << got; + acm->bit_data = b_data >> bits; + acm->bit_avail = b_avail - bits; + return data; +} + +#define GET_BITS_NOERR(tmpval, acm, bits) do { \ + if (acm->bit_avail >= bits) { \ + tmpval = acm->bit_data & ((1 << bits) - 1); \ + acm->bit_data >>= bits; \ + acm->bit_avail -= bits; \ + } else \ + tmpval = get_bits_reload(acm, bits); \ + } while (0) + +#define GET_BITS(res, acm, bits) do { \ + int tmpval; \ + GET_BITS_NOERR(tmpval, acm, bits); \ + if (tmpval < 0) \ + return tmpval; \ + res = tmpval; \ + } while (0) + +#define GET_BITS_EXPECT_EOF(res, acm, bits) do { \ + int tmpval; \ + GET_BITS_NOERR(tmpval, acm, bits); \ + if (tmpval < 0) { \ + if (tmpval == ACM_ERR_UNEXPECTED_EOF) \ + return ACM_EXPECTED_EOF; \ + return tmpval; \ + } \ + res = tmpval; \ + } while (0) + +/************************************************* + * Table filling + *************************************************/ +static const int map_1bit[] = { -1, +1 }; +static const int map_2bit_near[] = { -2, -1, +1, +2 }; +static const int map_2bit_far[] = { -3, -2, +2, +3 }; +static const int map_3bit[] = { -4, -3, -2, -1, +1, +2, +3, +4 }; +static int mul_3x3[3*3*3]; +static int mul_3x5[5*5*5]; +static int mul_2x11[11*11]; +static int tables_generated; + +static void generate_tables(void) +{ + int x1, x2, x3; + if (tables_generated) + return; + for (x3 = 0; x3 < 3; x3++) + for (x2 = 0; x2 < 3; x2++) + for (x1 = 0; x1 < 3; x1++) + mul_3x3[x1 + x2*3 + x3*3*3] = + x1 + (x2 << 4) + (x3 << 8); + for (x3 = 0; x3 < 5; x3++) + for (x2 = 0; x2 < 5; x2++) + for (x1 = 0; x1 < 5; x1++) + mul_3x5[x1 + x2*5 + x3*5*5] = + x1 + (x2 << 4) + (x3 << 8); + for (x2 = 0; x2 < 11; x2++) + for (x1 = 0; x1 < 11; x1++) + mul_2x11[x1 + x2*11] = x1 + (x2 << 4); + + tables_generated = 1; +} + +/* IOW: (r * acm->subblock_len) + c */ +#define set_pos(acm, r, c, idx) do { \ + unsigned _pos = ((r) << acm->info.acm_level) + (c); \ + acm->block[_pos] = acm->midbuf[idx]; \ + } while (0) + +/************ Fillers **********/ + +static int f_zero(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i; + for (i = 0; i < acm->info.acm_rows; i++) + set_pos(acm, i, col, 0); + + return 1; +} + +static int f_bad(ACMStream *acm, unsigned ind, unsigned col) +{ + /* corrupt block? */ + return ACM_ERR_CORRUPT; +} + +static int f_linear(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned int i; + int b, middle = 1 << (ind - 1); + + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, ind); + set_pos(acm, i, col, b - middle); + } + return 1; +} + +static int f_k13(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i++, col, 0); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, 0); + continue; + } + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 0 */ + set_pos(acm, i, col, 0); + continue; + } + /* 1, 1, ? */ + GET_BITS(b, acm, 1); + set_pos(acm, i, col, map_1bit[b]); + } + return 1; +} + +static int f_k12(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i, col, 0); + continue; + } + + /* 1, ? */ + GET_BITS(b, acm, 1); + set_pos(acm, i, col, map_1bit[b]); + } + return 1; +} + +static int f_k24(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i++, col, 0); + if (i >= acm->info.acm_rows) break; + set_pos(acm, i, col, 0); + continue; + } + + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 0 */ + set_pos(acm, i, col, 0); + continue; + } + + /* 1, 1, ?, ? */ + GET_BITS(b, acm, 2); + set_pos(acm, i, col, map_2bit_near[b]); + } + return 1; +} + +static int f_k23(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i, col, 0); + continue; + } + + /* 1, ?, ? */ + GET_BITS(b, acm, 2); + set_pos(acm, i, col, map_2bit_near[b]); + } + return 1; +} + +static int f_k35(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i++, col, 0); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, 0); + continue; + } + + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 0 */ + set_pos(acm, i, col, 0); + continue; + } + + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 1, 0, ? */ + GET_BITS(b, acm, 1); + set_pos(acm, i, col, map_1bit[b]); + continue; + } + + /* 1, 1, 1, ?, ? */ + GET_BITS(b, acm, 2); + set_pos(acm, i, col, map_2bit_far[b]); + } + return 1; +} + +static int f_k34(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i, col, 0); + continue; + } + + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 0, ? */ + GET_BITS(b, acm, 1); + set_pos(acm, i, col, map_1bit[b]); + continue; + } + + /* 1, 1, ?, ? */ + GET_BITS(b, acm, 2); + set_pos(acm, i, col, map_2bit_far[b]); + } + return 1; +} + +static int f_k45(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i, col, 0); i++; + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, 0); + continue; + } + + GET_BITS(b, acm, 1); + if (b == 0) { + /* 1, 0 */ + set_pos(acm, i, col, 0); + continue; + } + + /* 1, 1, ?, ?, ? */ + GET_BITS(b, acm, 3); + set_pos(acm, i, col, map_3bit[b]); + } + return 1; +} + +static int f_k44(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + for (i = 0; i < acm->info.acm_rows; i++) { + GET_BITS(b, acm, 1); + if (b == 0) { + /* 0 */ + set_pos(acm, i, col, 0); + continue; + } + + /* 1, ?, ?, ? */ + GET_BITS(b, acm, 3); + set_pos(acm, i, col, map_3bit[b]); + } + return 1; +} + +static int f_t15(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + int n1, n2, n3; + for (i = 0; i < acm->info.acm_rows; i++) { + /* b = (x1) + (x2 * 3) + (x3 * 9) */ + GET_BITS(b, acm, 5); + + n1 = (mul_3x3[b] & 0x0F) - 1; + n2 = ((mul_3x3[b] >> 4) & 0x0F) - 1; + n3 = ((mul_3x3[b] >> 8) & 0x0F) - 1; + + set_pos(acm, i++, col, n1); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i++, col, n2); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, n3); + } + return 1; +} + +static int f_t27(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + int n1, n2, n3; + for (i = 0; i < acm->info.acm_rows; i++) { + /* b = (x1) + (x2 * 5) + (x3 * 25) */ + GET_BITS(b, acm, 7); + + n1 = (mul_3x5[b] & 0x0F) - 2; + n2 = ((mul_3x5[b] >> 4) & 0x0F) - 2; + n3 = ((mul_3x5[b] >> 8) & 0x0F) - 2; + + set_pos(acm, i++, col, n1); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i++, col, n2); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, n3); + } + return 1; +} + +static int f_t37(ACMStream *acm, unsigned ind, unsigned col) +{ + unsigned i, b; + int n1, n2; + for (i = 0; i < acm->info.acm_rows; i++) { + /* b = (x1) + (x2 * 11) */ + GET_BITS(b, acm, 7); + + n1 = (mul_2x11[b] & 0x0F) - 5; + n2 = ((mul_2x11[b] >> 4) & 0x0F) - 5; + + set_pos(acm, i++, col, n1); + if (i >= acm->info.acm_rows) + break; + set_pos(acm, i, col, n2); + } + return 1; +} + +/****************/ + +static const filler_t filler_list[] = { + f_zero, f_bad, f_bad, f_linear, /* 0..3 */ + f_linear, f_linear, f_linear, f_linear, /* 4..7 */ + f_linear, f_linear, f_linear, f_linear, /* 8..11 */ + f_linear, f_linear, f_linear, f_linear, /* 12..15 */ + f_linear, f_k13, f_k12, f_t15, /* 16..19 */ + f_k24, f_k23, f_t27, f_k35, /* 20..23 */ + f_k34, f_bad, f_k45, f_k44, /* 24..27 */ + f_bad, f_t37, f_bad, f_bad /* 28..31 */ +}; + +static int fill_block(ACMStream *acm) +{ + unsigned i, ind; + int err; + for (i = 0; i < acm->info.acm_cols; i++) { + GET_BITS_EXPECT_EOF(ind, acm, 5); + err = filler_list[ind](acm, ind, i); + if (err < 0) + return err; + } + return 1; +} + +/********************************************** + * Decompress code + **********************************************/ + +static void juggle(int *wrap_p, int *block_p, unsigned sub_len, unsigned sub_count) +{ + unsigned int i, j; + int *p, r0, r1, r2, r3; + for (i = 0; i < sub_len; i++) { + p = block_p; + r0 = wrap_p[0]; + r1 = wrap_p[1]; + for (j = 0; j < sub_count/2; j++) { + r2 = *p; *p = r1*2 + (r0 + r2); p += sub_len; + r3 = *p; *p = r2*2 - (r1 + r3); p += sub_len; + r0 = r2; r1 = r3; + } + *wrap_p++ = r0; + *wrap_p++ = r1; + block_p++; + } +} + +static void juggle_block(ACMStream *acm) +{ + unsigned sub_count, sub_len, todo_count, step_subcount, i; + int *wrap_p, *block_p, *p; + + /* juggle only if subblock_len > 1 */ + if (acm->info.acm_level == 0) + return; + + /* 2048 / subblock_len */ + if (acm->info.acm_level > 9) + step_subcount = 1; + else + step_subcount = (2048 >> acm->info.acm_level) - 2; + + /* Apply juggle() (rows)x(cols) + * from (step_subcount * 2) x (subblock_len/2) + * to (step_subcount * subblock_len) x (1) + */ + todo_count = acm->info.acm_rows; + block_p = acm->block; + while (1) { + wrap_p = acm->wrapbuf; + sub_count = step_subcount; + if (sub_count > todo_count) + sub_count = todo_count; + + sub_len = acm->info.acm_cols / 2; + sub_count *= 2; + + juggle(wrap_p, block_p, sub_len, sub_count); + wrap_p += sub_len*2; + + for (i = 0, p = block_p; i < sub_count; i++) { + p[0]++; + p += sub_len; + } + + while (sub_len > 1) { + sub_len /= 2; + sub_count *= 2; + juggle(wrap_p, block_p, sub_len, sub_count); + wrap_p += sub_len*2; + } + if (todo_count <= step_subcount) + break; + todo_count -= step_subcount; + block_p += step_subcount << acm->info.acm_level; + } +} + +/***************************************************************/ +static int decode_block(ACMStream *acm) +{ + int pwr, count, val, i, x, err; + + acm->block_ready = 0; + acm->block_pos = 0; + + /* read header */ + GET_BITS_EXPECT_EOF(pwr, acm, 4); + GET_BITS_EXPECT_EOF(val, acm, 16); + + /* generate tables */ + count = 1 << pwr; + for (i = 0, x = 0; i < count; i++) { + acm->midbuf[i] = x; + x += val; + } + for (i = 1, x = -val; i <= count; i++) { + acm->midbuf[-i] = x; + x -= val; + } + + /* to_check? */ + if ((err = fill_block(acm)) <= 0) + return err; + + juggle_block(acm); + + acm->block_ready = 1; + + return 1; +} + +/****************************** + * Output formats + ******************************/ + +static unsigned char *out_s16le(int *src, unsigned char *dst, unsigned n, unsigned shift) +{ + while (n--) { + int val = *src++ >> shift; + *dst++ = val & 0xFF; + *dst++ = (val >> 8) & 0xFF; + } + return dst; +} + +static unsigned char *out_s16be(int *src, unsigned char *dst, unsigned n, unsigned shift) +{ + while (n--) { + int val = *src++ >> shift; + *dst++ = (val >> 8) & 0xFF; + *dst++ = val & 0xFF; + } + return dst; +} + +static unsigned char *out_u16le(int *src, unsigned char *dst, unsigned n, unsigned shift) +{ + while (n--) { + int val = (*src++ >> shift) + 0x8000; + *dst++ = val & 0xFF; + *dst++ = (val >> 8) & 0xFF; + } + return dst; +} + +static unsigned char *out_u16be(int *src, unsigned char *dst, unsigned n, unsigned shift) +{ + while (n--) { + int val = (*src++ >> shift) + 0x8000; + *dst++ = (val >> 8) & 0xFF; + *dst++ = val & 0xFF; + } + return dst; +} + +static int output_values(int *src, unsigned char *dst, int n, + int acm_level, int bigendianp, int wordlen, int sgned) +{ + unsigned char *res = NULL; + if (wordlen == 2) { + if (bigendianp == 0) { + if (sgned) + res = out_s16le(src, dst, n, acm_level); + else + res = out_u16le(src, dst, n, acm_level); + } else { + if (sgned) + res = out_s16be(src, dst, n, acm_level); + else + res = out_u16be(src, dst, n, acm_level); + } + } + if (res != NULL) + return res - dst; + return ACM_ERR_BADFMT; +} + +/* + * Header parsing. + */ + +static int read_header(ACMStream *acm) +{ + int tmp; + /* read header */ + GET_BITS(acm->info.acm_id, acm, 24); + if (acm->info.acm_id != ACM_ID) + return ACM_ERR_NOT_ACM; + GET_BITS(acm->info.acm_version, acm, 8); + if (acm->info.acm_version != 1) + return ACM_ERR_NOT_ACM; + GET_BITS(acm->total_values, acm, 16); + GET_BITS(tmp, acm, 16); + acm->total_values += tmp << 16; + if (acm->total_values == 0) + return ACM_ERR_NOT_ACM; + GET_BITS(acm->info.channels, acm, 16); + if (acm->info.channels < 1) + return ACM_ERR_NOT_ACM; + /* we play music, music is stereo, though not all headers agree */ + acm->info.channels = 2; + GET_BITS(acm->info.rate, acm, 16); + + GET_BITS(acm->info.acm_level, acm, 4); + GET_BITS(acm->info.acm_rows, acm, 12); + return 0; +} + +/*********************************************** + * Public functions + ***********************************************/ + +int acm_open_decoder(ACMStream **res, STREAMFILE *facilitator_file, + const char *const filename) +{ + int err = ACM_ERR_OTHER; + ACMStream *acm; + + acm = malloc(sizeof(*acm)); + if (!acm) + return err; + memset(acm, 0, sizeof(*acm)); + + acm->streamfile = facilitator_file->open(facilitator_file,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!acm->streamfile) + { + err = ACM_ERR_OPEN; + goto err_out; + } + + acm->data_len = get_streamfile_size(acm->streamfile); + + /* read header data */ + err = ACM_ERR_NOT_ACM; + if (read_header(acm) < 0) + goto err_out; + + /* calculate blocks */ + acm->info.acm_cols = 1 << acm->info.acm_level; + acm->wrapbuf_len = 2 * acm->info.acm_cols - 2; + acm->block_len = acm->info.acm_rows * acm->info.acm_cols; + + /* allocate */ + acm->block = malloc(acm->block_len * sizeof(int)); + acm->wrapbuf = malloc(acm->wrapbuf_len * sizeof(int)); + acm->ampbuf = malloc(0x10000 * sizeof(int)); + acm->midbuf = acm->ampbuf + 0x8000; + + memset(acm->wrapbuf, 0, acm->wrapbuf_len * sizeof(int)); + + generate_tables(); + + *res = acm; + return ACM_OK; + +err_out: + + acm_close(acm); + return err; +} + +int acm_read(ACMStream *acm, void *dst, unsigned numbytes, + int bigendianp, int wordlen, int sgned) +{ + int avail, gotbytes = 0, err; + int *src, numwords; + + if (wordlen == 2) + numwords = numbytes / 2; + else + return ACM_ERR_BADFMT; + + if (acm->stream_pos >= acm->total_values) + return 0; + + if (!acm->block_ready) { + err = decode_block(acm); + if (err == ACM_EXPECTED_EOF) + return 0; + if (err < 0) + return err; + } + + /* check how many words can be read */ + avail = acm->block_len - acm->block_pos; + if (avail < numwords) + numwords = avail; + + if (acm->stream_pos + numwords > acm->total_values) + numwords = acm->total_values - acm->stream_pos; + + if (acm->info.channels > 1) + numwords -= numwords % acm->info.channels; + + /* convert, but if dst == NULL, simulate */ + if (dst != NULL) { + src = acm->block + acm->block_pos; + gotbytes = output_values(src, dst, numwords, + acm->info.acm_level, + bigendianp, wordlen, sgned); + } else + gotbytes = numwords * wordlen; + + if (gotbytes >= 0) { + acm->stream_pos += numwords; + acm->block_pos += numwords; + if (acm->block_pos == acm->block_len) + acm->block_ready = 0; + } + + return gotbytes; +} + +void acm_close(ACMStream *acm) +{ + if (acm == NULL) + return; + if (acm->streamfile) { + close_streamfile(acm->streamfile); + acm->streamfile = NULL; + } + if (acm->block) + free(acm->block); + if (acm->wrapbuf) + free(acm->wrapbuf); + if (acm->ampbuf) + free(acm->ampbuf); + free(acm); +} + +void acm_reset(ACMStream *acm) +{ + acm->bit_avail = 0; + acm->bit_data = 0; + + acm->stream_pos = 0; + acm->block_pos = 0; + acm->block_ready = 0; + acm->buf_start_ofs = ACM_HEADER_LEN; + + memset(acm->wrapbuf, 0, acm->wrapbuf_len * sizeof(int)); +} + +/* interface to vgmstream */ +void decode_acm(ACMStream * acm, sample * outbuf, + int32_t samples_to_do, int channelspacing) { + int32_t samples_read = 0; + while (samples_read < samples_to_do) { + int32_t bytes_read_just_now; + bytes_read_just_now = + acm_read(acm,(char*)( + outbuf+samples_read*channelspacing), + (samples_to_do-samples_read)*sizeof(sample)* + channelspacing,0,2,1); + + if (bytes_read_just_now > 0) { + samples_read += + bytes_read_just_now/sizeof(sample)/channelspacing; + } else { + return; + } + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.h new file mode 100644 index 000000000..917c748c2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/acm_decoder.h @@ -0,0 +1,91 @@ +/* + * libacm - Interplay ACM audio decoder. + * + * Copyright (c) 2004-2008, Marko Kreen + * Copyright (c) 2008, Adam Gashlin + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef __LIBACM_H +#define __LIBACM_H + +#ifdef BUILD_VGMSTREAM +#include "../streamfile.h" +#else +#include "streamfile.h" +#endif + +#define LIBACM_VERSION "1.0-svn" + +#define ACM_ID 0x032897 +#define ACM_WORD 2 + +#define ACM_HEADER_LEN 14 +#define ACM_OK 0 +#define ACM_ERR_OTHER -1 +#define ACM_ERR_OPEN -2 +#define ACM_ERR_NOT_ACM -3 +#define ACM_ERR_READ_ERR -4 +#define ACM_ERR_BADFMT -5 +#define ACM_ERR_CORRUPT -6 +#define ACM_ERR_UNEXPECTED_EOF -7 +#define ACM_ERR_NOT_SEEKABLE -8 + +typedef struct ACMInfo { + unsigned channels; + unsigned rate; + unsigned acm_id; + unsigned acm_version; + unsigned acm_level; + unsigned acm_cols; /* 1 << acm_level */ + unsigned acm_rows; +} ACMInfo; + +struct ACMStream { + ACMInfo info; + unsigned total_values; + + /* acm data stream */ + STREAMFILE *streamfile; + unsigned data_len; + + /* acm stream buffer */ + unsigned bit_avail; + unsigned bit_data; + unsigned buf_start_ofs; + + /* block lengths (in samples) */ + unsigned block_len; + unsigned wrapbuf_len; + /* buffers */ + int *block; + int *wrapbuf; + int *ampbuf; + int *midbuf; /* pointer into ampbuf */ + /* result */ + unsigned block_ready:1; + unsigned file_eof:1; + unsigned stream_pos; /* in words. absolute */ + unsigned block_pos; /* in words, relative */ +}; +typedef struct ACMStream ACMStream; + +/* decode.c */ +int acm_open_decoder(ACMStream **res, STREAMFILE *facilitator_file, const char *const filename); +int acm_read(ACMStream *acm, void *buf, unsigned nbytes, + int bigendianp, int wordlen, int sgned); +void acm_close(ACMStream *acm); +void acm_reset(ACMStream *acm); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/adx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/adx_decoder.c new file mode 100644 index 000000000..ccac0b468 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/adx_decoder.c @@ -0,0 +1,81 @@ +#include "coding.h" +#include "../util.h" + +void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + int framesin = first_sample/32; + + int32_t scale = read_16bitBE(stream->offset+framesin*18,stream->streamfile) + 1; + int32_t hist1 = stream->adpcm_history1_32; + int32_t hist2 = stream->adpcm_history2_32; + int coef1 = stream->adpcm_coef[0]; + int coef2 = stream->adpcm_coef[1]; + + first_sample = first_sample%32; + + for (i=first_sample,sample_count=0; ioffset+framesin*18+2+i/2,stream->streamfile); + + outbuf[sample_count] = clamp16( + (i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) * scale + + ((coef1 * hist1 + coef2 * hist2) >> 12) + ); + + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_history2_32 = hist2; +} + +void adx_next_key(VGMSTREAMCHANNEL * stream) +{ + stream->adx_xor = ( stream->adx_xor * stream->adx_mult + stream->adx_add ) & 0x7fff; +} + +void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + int framesin = first_sample/32; + + int32_t scale = ((read_16bitBE(stream->offset+framesin*18,stream->streamfile) ^ stream->adx_xor)&0x1fff) + 1; + int32_t hist1 = stream->adpcm_history1_32; + int32_t hist2 = stream->adpcm_history2_32; + int coef1 = stream->adpcm_coef[0]; + int coef2 = stream->adpcm_coef[1]; + + first_sample = first_sample%32; + + for (i=first_sample,sample_count=0; ioffset+framesin*18+2+i/2,stream->streamfile); + + outbuf[sample_count] = clamp16( + (i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) * scale + + ((coef1 * hist1 + coef2 * hist2) >> 12) + ); + + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_history2_32 = hist2; + + if (!(i % 32)) { + for (i=0;iadx_channels;i++) + { + adx_next_key(stream); + } + } + +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/aica_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/aica_decoder.c new file mode 100644 index 000000000..d1134c79e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/aica_decoder.c @@ -0,0 +1,50 @@ +#include "../util.h" +#include "coding.h" + +/* fixed point (.8) amount to scale the current step size by */ +/* part of the same series as used in MS ADPCM "ADPCMTable" */ +static const unsigned int scale_step[16] = +{ + 230, 230, 230, 230, 307, 409, 512, 614, + 230, 230, 230, 230, 307, 409, 512, 614 +}; + +/* expand an unsigned four bit delta to a wider signed range */ +static const int scale_delta[16] = +{ + 1, 3, 5, 7, 9, 11, 13, 15, + -1, -3, -5, -7, -9,-11,-13,-15 +}; + +/* Yamaha AICA ADPCM (as seen in Dreamcast) */ + +void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + int32_t hist1 = stream->adpcm_history1_16; + unsigned long step_size = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile) >> + (i&1?4:0) + )&0xf; + + int32_t sample_delta = (int32_t)step_size * scale_delta[sample_nibble]; + int32_t new_sample; + + new_sample = hist1 + sample_delta/8; + + outbuf[sample_count] = clamp16(new_sample); + + hist1 = outbuf[sample_count]; + + step_size = (step_size * scale_step[sample_nibble])/0x100; + if (step_size < 0x7f) step_size = 0x7f; + if (step_size > 0x6000) step_size = 0x6000; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_size; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/at3_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/at3_decoder.c new file mode 100644 index 000000000..c9c538d08 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/at3_decoder.c @@ -0,0 +1,40 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_MAIATRAC3PLUS +#include "maiatrac3plus.h" +#include "coding.h" +#include "../util.h" + +void decode_at3plus(VGMSTREAM * vgmstream, + sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { + VGMSTREAMCHANNEL *ch = &vgmstream->ch[0]; + maiatrac3plus_codec_data *data = vgmstream->codec_data; + int i; + + int first_sample = vgmstream->samples_into_block % 2048; + + if (0 == channel && (0 == first_sample || data->samples_discard == first_sample)) + { + uint8_t code_buffer[0x8000]; + int blocks_to_decode = 1; + int max_blocks_to_decode = (ch->offset - ch->channel_start_offset) / vgmstream->interleave_block_size + 1; + if (data->samples_discard) blocks_to_decode = 8; + if (blocks_to_decode > max_blocks_to_decode) blocks_to_decode = max_blocks_to_decode; + while (blocks_to_decode--) { + ch->streamfile->read(ch->streamfile, code_buffer, ch->offset - blocks_to_decode * vgmstream->interleave_block_size, vgmstream->interleave_block_size); + Atrac3plusDecoder_decodeFrame(data->handle, code_buffer, vgmstream->interleave_block_size, &data->channels, (void**)&data->buffer); + } + data->samples_discard = 0; + } + + for (i = 0; i < samples_to_do; i++) + { + outbuf[i*channelspacing] = data->buffer[(first_sample+i)*data->channels+channel]; + } + + if (0 == channel && 2048 == first_sample + samples_to_do) { + ch->offset += vgmstream->interleave_block_size; + } +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/coding.h b/Frameworks/vgmstream/vgmstream/src/coding/coding.h new file mode 100644 index 000000000..dfaad0efa --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/coding.h @@ -0,0 +1,128 @@ +#ifndef _CODING_H +#define _CODING_H + +#include "../vgmstream.h" + +void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void adx_next_key(VGMSTREAMCHANNEL * stream); + +void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void g72x_init_state(struct g72x_state *state_ptr); + +void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); +void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); +void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); + +void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); + +void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); + +void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); + +void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); +void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem); + +int32_t dsp_nibbles_to_samples(int32_t nibbles); + +void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); + +void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm16LE_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm16BE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm8(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_invert_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void init_get_high_nibble(VGMSTREAM * vgmstream); + +void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); +void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); + +#ifdef VGM_USE_VORBIS +void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); +#endif + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) +void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels); +#endif + +void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +#ifdef VGM_USE_MPEG +void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream, + mpeg_codec_data * data, + sample * outbuf, int32_t samples_to_do); +mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels); +long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi); +void decode_mpeg(VGMSTREAMCHANNEL * stream, + mpeg_codec_data * data, + sample * outbuf, int32_t samples_to_do, int channels); +#endif + +#ifdef VGM_USE_G7221 +void decode_g7221(VGMSTREAM *vgmstream, + sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS +void decode_at3plus(VGMSTREAM *vgmstream, + sample * outbuf, int channelspacing, int32_t samples_to_do, int channel); +#endif + +void decode_acm(ACMStream * acm, sample * outbuf, + int32_t samples_to_do, int channelspacing); + +void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do); + +long msadpcm_bytes_to_samples(long bytes, int block_size, int channels); +void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); + +void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); + +void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + +void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c new file mode 100644 index 000000000..4e77769d8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/eaxa_decoder.c @@ -0,0 +1,170 @@ +#include "coding.h" +#include "../util.h" + +long EA_XA_TABLE[28] = {0,0,240,0,460,-208,0x0188,-220, + 0x0000,0x0000,0x00F0,0x0000, + 0x01CC,0x0000,0x0188,0x0000, + 0x0000,0x0000,0x0000,0x0000, + -208,-1,-220,-1, + 0x0000,0x0000,0x0000,0x3F70}; + +long EA_TABLE[20]= { 0x00000000, 0x000000F0, 0x000001CC, 0x00000188, + 0x00000000, 0x00000000, 0xFFFFFF30, 0xFFFFFF24, + 0x00000000, 0x00000001, 0x00000003, 0x00000004, + 0x00000007, 0x00000008, 0x0000000A, 0x0000000B, + 0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFC}; + +void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + uint8_t frame_info; + int32_t sample_count; + long coef1,coef2; + int i,shift; + off_t channel_offset=stream->channel_start_offset; + + first_sample = first_sample%28; + frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile); + + if(frame_info==0xEE) { + + channel_offset++; + stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset,stream->streamfile); + stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+2,stream->streamfile); + + channel_offset+=4; + + for (i=first_sample,sample_count=0; ioffset+channel_offset,stream->streamfile); + channel_offset+=2; + } + + // Only increment offset on complete frame + if(channel_offset-stream->channel_start_offset==(2*28)+5) + stream->channel_start_offset+=(2*28)+5; + + } else { + + + coef1 = EA_XA_TABLE[((frame_info >> 4) & 0x0F) << 1]; + coef2 = EA_XA_TABLE[(((frame_info >> 4) & 0x0F) << 1) + 1]; + shift = (frame_info & 0x0F) + 8; + + channel_offset++; + + for (i=first_sample,sample_count=0; ioffset+channel_offset+i/2,stream->streamfile); + int32_t sample = ((((i&1? + sample_byte & 0x0F: + sample_byte >> 4 + ) << 0x1C) >> shift) + + (coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32)) >> 8; + + outbuf[sample_count] = clamp16(sample); + stream->adpcm_history2_32 = stream->adpcm_history1_32; + stream->adpcm_history1_32 = sample; + } + + channel_offset+=i/2; + + // Only increment offset on complete frame + if(channel_offset-stream->channel_start_offset==0x0F) + stream->channel_start_offset+=0x0F; + } +} + + +void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + uint8_t frame_info; + int32_t sample_count; + long coef1,coef2; + int i,shift; + VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]); + off_t channel_offset=stream->channel_start_offset; + + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + first_sample = first_sample%28; + frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); + + coef1 = EA_TABLE[(vgmstream->get_high_nibble? frame_info & 0x0F: frame_info >> 4)]; + coef2 = EA_TABLE[(vgmstream->get_high_nibble? frame_info & 0x0F: frame_info >> 4) + 4]; + + channel_offset++; + + frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile); + shift = (vgmstream->get_high_nibble? frame_info & 0x0F : frame_info >> 4)+8; + + channel_offset++; + + for (i=first_sample,sample_count=0; ioffset+channel_offset+i,stream->streamfile); + + sample = ((((vgmstream->get_high_nibble? + sample_byte & 0x0F: + sample_byte >> 4 + ) << 0x1C) >> shift) + + (coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8; + + outbuf[sample_count] = clamp16(sample); + stream->adpcm_history2_32 = stream->adpcm_history1_32; + stream->adpcm_history1_32 = sample; + } + + channel_offset+=i; + + // Only increment offset on complete frame + if(channel_offset-stream->channel_start_offset==0x1E) + stream->channel_start_offset+=0x1E; +} + + +void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + uint8_t frame_info; + int32_t sample_count; + long coef1,coef2; + int i,shift; + int frameSize = channelspacing*15;//mono samples have a frame of 15, stereo files have frames of 30 + VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]); + off_t channel_offset=stream->channel_start_offset; + + first_sample = first_sample%28; + frame_info = read_8bit(channel_offset,stream->streamfile); + + coef1 = EA_TABLE[frame_info >> 4]; + coef2 = EA_TABLE[(frame_info >> 4) + 4]; + shift = (frame_info & 0x0F)+8; + + channel_offset+=channelspacing; + //stream->offset = first_sample*channelspacing/2; + + for (i=first_sample,sample_count=0; ioffset+channel_offset,stream->streamfile); + + sample = (((((i&1)? + sample_byte & 0x0F: + sample_byte >> 4 + ) << 0x1C) >> shift) + + (coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8; + + outbuf[sample_count] = clamp16(sample); + stream->adpcm_history2_32 = stream->adpcm_history1_32; + stream->adpcm_history1_32 = sample; + + if(i&1) + stream->offset+=channelspacing; + } + + channel_offset+=i; + + // Only increment offset on complete frame + + if(channel_offset-stream->channel_start_offset==frameSize) { + stream->channel_start_offset+=frameSize; + stream->offset=0; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c new file mode 100644 index 000000000..41e147ac4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g721_decoder.c @@ -0,0 +1,471 @@ +/* G.721 decoder, from Sun's public domain CCITT-ADPCM sources, + * retrieved from ftp://ftp.cwi.nl/pub/audio/ccitt-adpcm.tar.gz + * + * For reference, here's the original license: + * + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + * + */ + +#include "coding.h" +#include "../util.h" + +static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000}; + +/* + * quan() + * + * quantizes the input val against the table of size short integers. + * It returns i if table[i - 1] <= val < table[i]. + * + * Using linear search for simple coding. + */ +static int +quan( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) + if (val < *table++) + break; + return (i); +} + +/* + * fmult() + * + * returns the integer product of the 14-bit integer "an" and + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". + */ +static int +fmult( + int an, + int srn) +{ + short anmag, anexp, anmant; + short wanexp, wanmant; + short retval; + + anmag = (an > 0) ? an : ((-an) & 0x1FFF); + anexp = quan(anmag, power2, 15) - 6; + anmant = (anmag == 0) ? 32 : + (anexp >= 0) ? anmag >> anexp : anmag << -anexp; + wanexp = anexp + ((srn >> 6) & 0xF) - 13; + + wanmant = (anmant * (srn & 077) + 0x30) >> 4; + retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : + (wanmant >> -wanexp); + + return (((an ^ srn) < 0) ? -retval : retval); +} + +/* + * g72x_init_state() + * + * This routine initializes and/or resets the g72x_state structure + * pointed to by 'state_ptr'. + * All the initial state values are specified in the CCITT G.721 document. + */ +void +g72x_init_state( + struct g72x_state *state_ptr) +{ + int cnta; + + state_ptr->yl = 34816; + state_ptr->yu = 544; + state_ptr->dms = 0; + state_ptr->dml = 0; + state_ptr->ap = 0; + for (cnta = 0; cnta < 2; cnta++) { + state_ptr->a[cnta] = 0; + state_ptr->pk[cnta] = 0; + state_ptr->sr[cnta] = 32; + } + for (cnta = 0; cnta < 6; cnta++) { + state_ptr->b[cnta] = 0; + state_ptr->dq[cnta] = 32; + } + state_ptr->td = 0; +} + +/* + * predictor_zero() + * + * computes the estimated signal from 6-zero predictor. + * + */ +int +predictor_zero( + struct g72x_state *state_ptr) +{ + int i; + int sezi; + + sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); + for (i = 1; i < 6; i++) /* ACCUM */ + sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); + return (sezi); +} +/* + * predictor_pole() + * + * computes the estimated signal from 2-pole predictor. + * + */ +int +predictor_pole( + struct g72x_state *state_ptr) +{ + return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); +} +/* + * step_size() + * + * computes the quantization step size of the adaptive quantizer. + * + */ +int +step_size( + struct g72x_state *state_ptr) +{ + int y; + int dif; + int al; + + if (state_ptr->ap >= 256) + return (state_ptr->yu); + else { + y = state_ptr->yl >> 6; + dif = state_ptr->yu - y; + al = state_ptr->ap >> 2; + if (dif > 0) + y += (dif * al) >> 6; + else if (dif < 0) + y += (dif * al + 0x3F) >> 6; + return (y); + } +} + +/* + * reconstruct() + * + * Returns reconstructed difference signal 'dq' obtained from + * codeword 'i' and quantization step size scale factor 'y'. + * Multiplication is performed in log base 2 domain as addition. + */ +int +reconstruct( + int sign, /* 0 for non-negative value */ + int dqln, /* G.72x codeword */ + int y) /* Step size multiplier */ +{ + short dql; /* Log of 'dq' magnitude */ + short dex; /* Integer part of log */ + short dqt; + short dq; /* Reconstructed difference signal sample */ + + dql = dqln + (y >> 2); /* ADDA */ + + if (dql < 0) { + return ((sign) ? -0x8000 : 0); + } else { /* ANTILOG */ + dex = (dql >> 7) & 15; + dqt = 128 + (dql & 127); + dq = (dqt << 7) >> (14 - dex); + return ((sign) ? (dq - 0x8000) : dq); + } +} + + +/* + * update() + * + * updates the state variables for each output code + */ +void +update( + /*int code_size,*/ /* distinguish 723_40 with others */ + int y, /* quantizer step size */ + int wi, /* scale factor multiplier */ + int fi, /* for long/short term energies */ + int dq, /* quantized prediction difference */ + int sr, /* reconstructed signal */ + int dqsez, /* difference from 2-pole predictor */ + struct g72x_state *state_ptr) /* coder state pointer */ +{ + int cnt; + short mag, exp; /* Adaptive predictor, FLOAT A */ + short a2p; /* LIMC */ + short a1ul; /* UPA1 */ + short pks1; /* UPA2 */ + short fa1; + char tr; /* tone/transition detector */ + short ylint, thr2, dqthr; + short ylfrac, thr1; + short pk0; + + pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ + + mag = dq & 0x7FFF; /* prediction difference magnitude */ + /* TRANS */ + ylint = state_ptr->yl >> 15; /* exponent part of yl */ + ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ + thr1 = (32 + ylfrac) << ylint; /* threshold */ + thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ + dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ + if (state_ptr->td == 0) /* signal supposed voice */ + tr = 0; + else if (mag <= dqthr) /* supposed data, but small mag */ + tr = 0; /* treated as voice */ + else /* signal is data (modem) */ + tr = 1; + + /* + * Quantizer scale factor adaptation. + */ + + /* FUNCTW & FILTD & DELAY */ + /* update non-steady state step size multiplier */ + state_ptr->yu = y + ((wi - y) >> 5); + + /* LIMB */ + if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ + state_ptr->yu = 544; + else if (state_ptr->yu > 5120) + state_ptr->yu = 5120; + + /* FILTE & DELAY */ + /* update steady state step size multiplier */ + state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); + + /* + * Adaptive predictor coefficients. + */ + if (tr == 1) { /* reset a's and b's for modem signal */ + state_ptr->a[0] = 0; + state_ptr->a[1] = 0; + state_ptr->b[0] = 0; + state_ptr->b[1] = 0; + state_ptr->b[2] = 0; + state_ptr->b[3] = 0; + state_ptr->b[4] = 0; + state_ptr->b[5] = 0; + a2p=0; /* won't be used, clear warning */ + } else { /* update a's and b's */ + pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ + + /* update predictor pole a[1] */ + a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); + if (dqsez != 0) { + fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; + if (fa1 < -8191) /* a2p = function of fa1 */ + a2p -= 0x100; + else if (fa1 > 8191) + a2p += 0xFF; + else + a2p += fa1 >> 5; + + if (pk0 ^ state_ptr->pk[1]) + /* LIMC */ + if (a2p <= -12160) + a2p = -12288; + else if (a2p >= 12416) + a2p = 12288; + else + a2p -= 0x80; + else if (a2p <= -12416) + a2p = -12288; + else if (a2p >= 12160) + a2p = 12288; + else + a2p += 0x80; + } + + /* TRIGB & DELAY */ + state_ptr->a[1] = a2p; + + /* UPA1 */ + /* update predictor pole a[0] */ + state_ptr->a[0] -= state_ptr->a[0] >> 8; + if (dqsez != 0) { + if (pks1 == 0) + state_ptr->a[0] += 192; + else + state_ptr->a[0] -= 192; + } + + /* LIMD */ + a1ul = 15360 - a2p; + if (state_ptr->a[0] < -a1ul) + state_ptr->a[0] = -a1ul; + else if (state_ptr->a[0] > a1ul) + state_ptr->a[0] = a1ul; + + /* UPB : update predictor zeros b[6] */ + for (cnt = 0; cnt < 6; cnt++) { + /*if (code_size == 5)*/ /* for 40Kbps G.723 */ + /* state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;*/ + /*else*/ /* for G.721 and 24Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; + if (dq & 0x7FFF) { /* XOR */ + if ((dq ^ state_ptr->dq[cnt]) >= 0) + state_ptr->b[cnt] += 128; + else + state_ptr->b[cnt] -= 128; + } + } + } + + for (cnt = 5; cnt > 0; cnt--) + state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ + if (mag == 0) { + state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; + } else { + exp = quan(mag, power2, 15); + state_ptr->dq[0] = (dq >= 0) ? + (exp << 6) + ((mag << 6) >> exp) : + (exp << 6) + ((mag << 6) >> exp) - 0x400; + } + + state_ptr->sr[1] = state_ptr->sr[0]; + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ + if (sr == 0) { + state_ptr->sr[0] = 0x20; + } else if (sr > 0) { + exp = quan(sr, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); + } else if (sr > -32768) { + mag = -sr; + exp = quan(mag, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; + } else + state_ptr->sr[0] = 0xFC20; + + /* DELAY A */ + state_ptr->pk[1] = state_ptr->pk[0]; + state_ptr->pk[0] = pk0; + + /* TONE */ + if (tr == 1) /* this sample has been treated as data */ + state_ptr->td = 0; /* next one will be treated as voice */ + else if (a2p < -11776) /* small sample-to-sample correlation */ + state_ptr->td = 1; /* signal may be data */ + else /* signal is voice */ + state_ptr->td = 0; + + /* + * Adaptation speed control. + */ + state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ + state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ + + if (tr == 1) + state_ptr->ap = 256; + else if (y < 1536) /* SUBTC */ + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (state_ptr->td == 1) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= + (state_ptr->dml >> 3)) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else + state_ptr->ap += (-state_ptr->ap) >> 4; +} + +/* + * Maps G.721 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, -2048}; + +/* Maps G.721 code word to log of scale factor multiplier. */ +static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +/* + * Maps G.721 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, + 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; +/* + * g721_decoder() + * + * Description: + * + * Decodes a 4-bit code of G.721 encoded data of i and + * returns the resulting linear PCM, A-law or u-law value. + * return -1 for unknown out_coding value. + */ +int +g721_decoder( + int i, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x0f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* dynamic quantizer step size */ + + dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + return (sr << 2); /* sr was 14-bit dynamic range */ +} + +void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile)>>(i&1?4:0), + &(stream->g72x_state) + ); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c new file mode 100644 index 000000000..a55e4602e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g7221_decoder.c @@ -0,0 +1,28 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_G7221 +#include "g7221.h" +#include "coding.h" +#include "../util.h" + +void decode_g7221(VGMSTREAM * vgmstream, + sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) { + VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel]; + g7221_codec_data *data = vgmstream->codec_data; + g7221_codec_data *ch_data = &data[channel]; + int i; + + if (0 == vgmstream->samples_into_block) + { + int16_t code_buffer[960/8]; + vgmstream->ch[channel].streamfile->read(ch->streamfile, (uint8_t*)code_buffer, ch->offset, vgmstream->interleave_block_size); + g7221_decode_frame(ch_data->handle, code_buffer, ch_data->buffer); + } + + for (i = 0; i < samples_to_do; i++) + { + outbuf[i*channelspacing] = ch_data->buffer[vgmstream->samples_into_block+i]; + } +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h b/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h new file mode 100644 index 000000000..bf1a6ade5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/g72x_state.h @@ -0,0 +1,35 @@ +/* + * streamtypes.h - widely used type definitions + */ + + +#ifndef _G72X_STATE_H +#define _G72X_STATE_H + +struct g72x_state { + long yl; /* Locked or steady state step size multiplier. */ + short yu; /* Unlocked or non-steady state step size multiplier. */ + short dms; /* Short term energy estimate. */ + short dml; /* Long term energy estimate. */ + short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ + + short a[2]; /* Coefficients of pole portion of prediction filter. */ + short b[6]; /* Coefficients of zero portion of prediction filter. */ + short pk[2]; /* + * Signs of previous two samples of a partially + * reconstructed signal. + */ + short dq[6]; /* + * Previous 6 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + short sr[2]; /* + * Previous 2 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + char td; /* delayed tone detect, new in 1988 version */ +}; + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c new file mode 100644 index 000000000..434303c4c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c @@ -0,0 +1,637 @@ +#include "../util.h" +#include "coding.h" + +const int32_t ADPCMTable[89] = + +{ + + 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 19, 21, 23, 25, 28, 31, + 34, 37, 41, 45, 50, 55, 60, 66, + 73, 80, 88, 97, 107, 118, 130, 143, + 157, 173, 190, 209, 230, 253, 279, 307, + 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, + 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 + +}; + +const int IMA_IndexTable[16] = + +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + int32_t hist1 = stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + if (first_sample==0) { + hist1 = read_16bitLE(stream->offset,stream->streamfile); + step_index = read_16bitLE(stream->offset+2,stream->streamfile); + } + + for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?4:0))&0xf; + int delta; + int step = ADPCMTable[step_index]; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + outbuf[sample_count] = clamp16(hist1 - delta); + else + outbuf[sample_count] = clamp16(hist1 + delta); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + int32_t hist1 = stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + if (first_sample==0) { + hist1 = read_16bitLE(stream->offset,stream->streamfile); + step_index = read_8bit(stream->offset+2,stream->streamfile); + } + + for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?0:4))&0xf; + int delta; + int step = ADPCMTable[step_index]; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + outbuf[sample_count] = clamp16(hist1 - delta); + else + outbuf[sample_count] = clamp16(hist1 + delta); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +/* Xbox IMA is MS IMA, but I'll leave it alone for now (esp as it has > 2 channel support) */ +void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+channel*4,stream->streamfile); + step_index = read_16bitLE(offset+channel*4+2,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/8*4*vgmstream->channels) + (i%8)/2 + 4*channel; + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + // Only increment offset on complete frame + if (i == block_samples) stream->offset += vgmstream->interleave_block_size; + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +// "Radical ADPCM", essentially MS IMA +void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+channel*4+2,stream->streamfile); + step_index = read_16bitLE(offset+channel*4,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/2*vgmstream->channels) + channel; + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + // Only increment offset on complete frame + if (i == block_samples) stream->offset += vgmstream->interleave_block_size; + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +// "Radical ADPCM", mono form (for use with interleave layout) +// I think this is exactly equivalent to mono MS APDCM, but I need a +// channel-agnostic version to use within an interleave. +void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = 0x14 * 2; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+2,stream->streamfile); + step_index = read_16bitLE(offset,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4 + (i/2); + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + if(vgmstream->channels==1) + first_sample = first_sample % 32; + else + first_sample = first_sample % (32*(vgmstream->channels&2)); + + if (first_sample == 0) { + + if(vgmstream->layout_type==layout_ea_blocked) { + hist1 = read_16bitLE(offset,stream->streamfile); + step_index = read_16bitLE(offset+2,stream->streamfile); + } else { + hist1 = read_16bitLE(offset+(channel%2)*4,stream->streamfile); + step_index = read_16bitLE(offset+(channel%2)*4+2,stream->streamfile); + } + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ilayout_type==layout_ea_blocked) + offset = stream->offset + (i/8*4+(i%8)/2+4); + else { + if(channelspacing==1) + offset = stream->offset + 4 + (i/8*4+(i%8)/2+4*(channel%2)); + else + offset = stream->offset + 4*2 + (i/8*4*2+(i%8)/2+4*(channel%2)); + } + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + // Only increment offset on complete frame + if(vgmstream->layout_type==layout_ea_blocked) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(channelspacing==1) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(offset-stream->offset==64+(4*(channel%2))+3) // ?? + stream->offset+=36*channelspacing; + } + } + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + if(vgmstream->channels==1) + first_sample = first_sample % 32; + else + first_sample = first_sample % (32*(vgmstream->channels&2)); + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset,stream->streamfile); + step_index = read_16bitLE(offset+2,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4 + (i/8*4+(i%8)/2); + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + // Only increment offset on complete frame + if(channelspacing==1) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(offset-stream->offset==64+(4*(channel%2))+3) // ?? + stream->offset+=36*channelspacing; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile); + /* old-style DVI takes high nibble first */ + sample_nibble = (sample_byte >> (i&1?0:4))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + + +void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i; + VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]); + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + if((first_sample) && (channelspacing==1)) + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + sample_nibble = (sample_byte >> (vgmstream->get_high_nibble?0:4))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile); + sample_nibble = (sample_byte >> (i&1?4:0))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count=0; + int16_t hist1=stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + off_t packet_offset = stream->offset + first_sample/64*34; + + first_sample = first_sample % 64; + + if (first_sample == 0) + { + hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80); + step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f; + } + + for (i=first_sample,sample_count=0; istreamfile); + sample_nibble = (sample_byte >> (i&1?4:0))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_16=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + sample_nibble = (sample_byte >> (channel==0?0:4))&0xf; + + // update step before doing current sample + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + step = ADPCMTable[step_index]; + + delta = (sample_nibble & 7) * step / 4 + step / 8; + if (sample_nibble & 8) delta = -delta; + sample_decoded = hist1 + delta; + + hist1=clamp16(sample_decoded); + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/coding/l5_555_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/l5_555_decoder.c new file mode 100644 index 000000000..0a12e8372 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/l5_555_decoder.c @@ -0,0 +1,58 @@ +#include "coding.h" +#include "../util.h" + +static const int32_t l5_scales[32] = { + 0x00001000, 0x0000144E, 0x000019C5, 0x000020B4, 0x00002981, 0x000034AC, 0x000042D9, 0x000054D6, + 0x00006BAB, 0x000088A4, 0x0000AD69, 0x0000DC13, 0x0001174C, 0x00016275, 0x0001C1D8, 0x00023AE5, + 0x0002D486, 0x0003977E, 0x00048EEE, 0x0005C8F3, 0x00075779, 0x0009513E, 0x000BD31C, 0x000F01B5, + 0x00130B82, 0x00182B83, 0x001EAC92, 0x0026EDB2, 0x00316777, 0x003EB2E6, 0x004F9232, 0x0064FBD1 +}; + +void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/32; + + uint16_t header = (uint16_t)read_16bitLE(framesin*0x12+stream->offset,stream->streamfile); + int32_t pos_scale = l5_scales[(header>>5)&0x1f]; + int32_t neg_scale = l5_scales[header&0x1f]; + + int coef_index = (header >> 10) & 0x1f; + int16_t hist1 = stream->adpcm_history1_16; + int16_t hist2 = stream->adpcm_history2_16; + int16_t hist3 = stream->adpcm_history3_16; + int32_t coef1 = stream->adpcm_coef_3by32[coef_index*3]; + int32_t coef2 = stream->adpcm_coef_3by32[coef_index*3+1]; + int32_t coef3 = stream->adpcm_coef_3by32[coef_index*3+2]; + /*printf("offset: %x\nscale: %d\nindex: %d (%lf,%lf)\nhist: %d %d\n", + (unsigned)stream->offset,scale,coef_index,coef1/2048.0,coef2/2048.0,hist1,hist2);*/ + + first_sample = first_sample%32; + + for (i=first_sample,sample_count=0; ioffset+2+i/2,stream->streamfile); + int nibble = (i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte)); + int32_t prediction = + -(hist1 * coef1 + hist2 * coef2 + hist3 * coef3); + + if (nibble >= 0) + { + outbuf[sample_count] = clamp16((prediction + nibble * pos_scale) >> 12); + } + else + { + outbuf[sample_count] = clamp16((prediction + nibble * neg_scale) >> 12); + } + + hist3 = hist2; + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_history2_16 = hist2; + stream->adpcm_history3_16 = hist3; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/lsf_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/lsf_decoder.c new file mode 100644 index 000000000..3bed79014 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/lsf_decoder.c @@ -0,0 +1,52 @@ +#include "coding.h" +#include "../util.h" + +/* lsf ADPCM, as seen in Fastlane Street Racing */ + +static const short lsf_coefs[5][2] = { + {0x73, -0x34}, + {0, 0}, + {0x62, -0x37}, + {0x3C, 0}, + {0x7A, -0x3c} +}; + +void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + const int bytes_per_frame = 0x1c; + const int samples_per_frame = (bytes_per_frame-1)*2; + + int framesin = first_sample/samples_per_frame; + + uint8_t q = 0xFF - read_8bit(framesin*bytes_per_frame + stream->offset,stream->streamfile); + int scale = (q&0xF0)>>4; + int coef_idx = q&0x0F; + int32_t hist1 = stream->adpcm_history1_16; + int32_t hist2 = stream->adpcm_history2_16; + + first_sample = first_sample%samples_per_frame; + + for (i=first_sample,sample_count=0; ioffset+1+i/2,stream->streamfile); + + long prediction = + (hist1 * lsf_coefs[coef_idx][0] + + hist2 * lsf_coefs[coef_idx][1]) / 0x40; + + prediction += (i&1? + get_high_nibble_signed(sample_byte): + get_low_nibble_signed(sample_byte) + ) * (1 << (12-scale)); + + prediction = clamp16(prediction); + + hist2 = hist1; + hist1 = prediction; + + outbuf[sample_count] = prediction; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_history2_16 = hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mp4_aac_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mp4_aac_decoder.c new file mode 100644 index 000000000..7b6a25898 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/mp4_aac_decoder.c @@ -0,0 +1,85 @@ +#include "../vgmstream.h" + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) +static void convert_samples(INT_PCM * src, sample * dest, int32_t count) { + int32_t i; + for ( i = 0; i < count; i++ ) { + INT_PCM sample = *src++; + sample >>= SAMPLE_BITS - 16; + if ( ( sample + 0x8000 ) & 0xFFFF0000 ) sample = 0x7FFF ^ ( sample >> 31 ); + *dest++ = sample; + } +} + +void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) { + int samples_done = 0; + + uint8_t * buffer = NULL; + uint32_t buffer_size; + UINT ubuffer_size, bytes_valid; + + CStreamInfo * stream_info = aacDecoder_GetStreamInfo( data->h_aacdecoder ); + + int32_t samples_remain = data->samples_per_frame - data->sample_ptr; + + if ( data->samples_discard ) { + if ( samples_remain <= data->samples_discard ) { + data->samples_discard -= samples_remain; + samples_remain = 0; + } + else { + samples_remain -= data->samples_discard; + data->sample_ptr += data->samples_discard; + data->samples_discard = 0; + } + } + + if ( samples_remain > samples_to_do ) samples_remain = samples_to_do; + + convert_samples( data->sample_buffer + data->sample_ptr * stream_info->numChannels, outbuf, samples_remain * stream_info->numChannels ); + + outbuf += samples_remain * stream_info->numChannels; + + data->sample_ptr += samples_remain; + + samples_done += samples_remain; + + while ( samples_done < samples_to_do ) { + if (data->sampleId >= data->numSamples) { + memset(outbuf, 0, (samples_to_do - samples_done) * stream_info->numChannels * sizeof(sample)); + break; + } + if (!MP4ReadSample( data->h_mp4file, data->track_id, ++data->sampleId, (uint8_t**)(&buffer), (uint32_t*)(&buffer_size), 0, 0, 0, 0)) return; + ubuffer_size = buffer_size; + bytes_valid = buffer_size; + if ( aacDecoder_Fill( data->h_aacdecoder, &buffer, &ubuffer_size, &bytes_valid ) || bytes_valid ) { + free( buffer ); + return; + } + if ( aacDecoder_DecodeFrame( data->h_aacdecoder, data->sample_buffer, ( (6) * (2048)*4 ), 0 ) ) { + free( buffer ); + return; + } + free( buffer ); buffer = NULL; + stream_info = aacDecoder_GetStreamInfo( data->h_aacdecoder ); + samples_remain = data->samples_per_frame = stream_info->frameSize; + data->sample_ptr = 0; + if ( data->samples_discard ) { + if ( samples_remain <= data->samples_discard ) { + data->samples_discard -= samples_remain; + samples_remain = 0; + } + else { + samples_remain -= data->samples_discard; + data->sample_ptr = data->samples_discard; + data->samples_discard = 0; + } + } + if ( samples_remain > samples_to_do - samples_done ) samples_remain = samples_to_do - samples_done; + convert_samples( data->sample_buffer + data->sample_ptr * stream_info->numChannels, outbuf, samples_remain * stream_info->numChannels ); + samples_done += samples_remain; + outbuf += samples_remain * stream_info->numChannels; + data->sample_ptr = samples_remain; + } +} +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c new file mode 100644 index 000000000..921287b8a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/mpeg_decoder.c @@ -0,0 +1,229 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_MPEG +#include +#include +#include "coding.h" +#include "../util.h" + +/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they + * actually vary and are much shorter */ +void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream, + mpeg_codec_data * data, + sample * outbuf, int32_t samples_to_do) { + int samples_done = 0; + + while (samples_done < samples_to_do) { + size_t bytes_done; + int rc; + + if (!data->buffer_full) { + /* fill buffer up to next frame ending (or file ending) */ + int bytes_into_header = 0; + const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0}; + off_t frame_offset = 0; + + /* assume that we are starting at a header, skip it and look for the + * next one */ + read_streamfile(data->buffer, stream->offset+frame_offset, 4, + stream->streamfile); + frame_offset += 4; + + do { + uint8_t byte; + byte = + read_8bit(stream->offset+frame_offset,stream->streamfile); + data->buffer[frame_offset] = byte; + frame_offset++; + + if (byte == header[bytes_into_header]) { + bytes_into_header++; + } else { + /* This might have been the first byte of the header, so + * we need to check again. + * No need to get more complicated than this, though, since + * there are no repeated characters in the search string. */ + if (bytes_into_header>0) { + frame_offset--; + } + bytes_into_header=0; + } + + if (bytes_into_header==4) { + break; + } + } while (frame_offset < AHX_EXPECTED_FRAME_SIZE); + + if (bytes_into_header==4) frame_offset-=4; + memset(data->buffer+frame_offset,0, + AHX_EXPECTED_FRAME_SIZE-frame_offset); + + data->buffer_full = 1; + data->buffer_used = 0; + + stream->offset += frame_offset; + } + + if (!data->buffer_used) { + rc = mpg123_decode(data->m, + data->buffer,AHX_EXPECTED_FRAME_SIZE, + (unsigned char *)(outbuf+samples_done), + (samples_to_do-samples_done)*sizeof(sample), + &bytes_done); + data->buffer_used = 1; + } else { + rc = mpg123_decode(data->m, + NULL,0, + (unsigned char *)(outbuf+samples_done), + (samples_to_do-samples_done)*sizeof(sample), + &bytes_done); + } + + if (rc == MPG123_NEED_MORE) data->buffer_full = 0; + + samples_done += bytes_done/sizeof(sample); + } +} + +mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels) { + int rc; + off_t read_offset; + mpeg_codec_data *data = NULL; + + data = calloc(1,sizeof(mpeg_codec_data)); + if (!data) goto mpeg_fail; + + data->m = mpg123_new(NULL,&rc); + if (rc==MPG123_NOT_INITIALIZED) { + if (mpg123_init()!=MPG123_OK) goto mpeg_fail; + data->m = mpg123_new(NULL,&rc); + if (rc!=MPG123_OK) goto mpeg_fail; + } else if (rc!=MPG123_OK) { + goto mpeg_fail; + } + + mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0); + + if (mpg123_open_feed(data->m)!=MPG123_OK) { + goto mpeg_fail; + } + + /* check format */ + read_offset=0; + do { + size_t bytes_done; + if (read_streamfile(data->buffer, start_offset+read_offset, + MPEG_BUFFER_SIZE,streamfile) != + MPEG_BUFFER_SIZE) goto mpeg_fail; + read_offset+=1; + rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE, + NULL,0,&bytes_done); + if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT && + rc != MPG123_NEED_MORE) goto mpeg_fail; + } while (rc != MPG123_NEW_FORMAT); + + { + long rate; + int channels,encoding; + struct mpg123_frameinfo mi; + rc = mpg123_getformat(data->m,&rate,&channels,&encoding); + if (rc != MPG123_OK) goto mpeg_fail; + //fprintf(stderr,"getformat ok, sr=%ld (%ld) ch=%d (%d) enc=%d (%d)\n",rate,given_sample_rate,channels,vgmstream->channels,encoding,MPG123_ENC_SIGNED_16); + if ((given_sample_rate != -1 && rate != given_sample_rate) || + (given_channels != -1 && channels != given_channels) || + encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail; + mpg123_info(data->m,&mi); + if (given_sample_rate != -1 && + mi.rate != given_sample_rate) goto mpeg_fail; + + //fprintf(stderr,"mi.version=%d, mi.layer=%d\n",mi.version,mi.layer); + + if (mi.version == MPG123_1_0 && mi.layer == 1) + *coding_type = coding_MPEG1_L1; + else if (mi.version == MPG123_1_0 && mi.layer == 2) + *coding_type = coding_MPEG1_L2; + else if (mi.version == MPG123_1_0 && mi.layer == 3) + *coding_type = coding_MPEG1_L3; + else if (mi.version == MPG123_2_0 && mi.layer == 1) + *coding_type = coding_MPEG2_L1; + else if (mi.version == MPG123_2_0 && mi.layer == 2) + *coding_type = coding_MPEG2_L2; + else if (mi.version == MPG123_2_0 && mi.layer == 3) + *coding_type = coding_MPEG2_L3; + else if (mi.version == MPG123_2_5 && mi.layer == 1) + *coding_type = coding_MPEG25_L1; + else if (mi.version == MPG123_2_5 && mi.layer == 2) + *coding_type = coding_MPEG25_L2; + else if (mi.version == MPG123_2_5 && mi.layer == 3) + *coding_type = coding_MPEG25_L3; + else goto mpeg_fail; + + if ( actual_sample_rate ) *actual_sample_rate = rate; + if ( actual_channels ) *actual_channels = channels; + } + + /* reinit, to ignore the reading we've done so far */ + mpg123_open_feed(data->m); + + return data; + +mpeg_fail: + fprintf(stderr, "mpeg_fail start_offset=%x\n",(unsigned int)start_offset); + if (data) { + mpg123_delete(data->m); + free(data); + } + return NULL; +} + +/* decode anything mpg123 can */ +void decode_mpeg(VGMSTREAMCHANNEL *stream, + mpeg_codec_data * data, + sample * outbuf, int32_t samples_to_do, int channels) { + int samples_done = 0; + + while (samples_done < samples_to_do) { + size_t bytes_done; + int rc; + + if (!data->buffer_full) { + data->bytes_in_buffer = read_streamfile(data->buffer, + stream->offset,MPEG_BUFFER_SIZE,stream->streamfile); + + if (!data->bytes_in_buffer) { + memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample)); + break; + } + + data->buffer_full = 1; + data->buffer_used = 0; + + stream->offset += data->bytes_in_buffer; + } + + if (!data->buffer_used) { + rc = mpg123_decode(data->m, + data->buffer,data->bytes_in_buffer, + (unsigned char *)(outbuf+samples_done*channels), + (samples_to_do-samples_done)*sizeof(sample)*channels, + &bytes_done); + data->buffer_used = 1; + } else { + rc = mpg123_decode(data->m, + NULL,0, + (unsigned char *)(outbuf+samples_done*channels), + (samples_to_do-samples_done)*sizeof(sample)*channels, + &bytes_done); + } + + if (rc == MPG123_NEED_MORE) data->buffer_full = 0; + + samples_done += bytes_done/sizeof(sample)/channels; + } +} + +long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi) { + return (int64_t)bytes * mi->rate * 8 / (mi->bitrate * 1000); +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c new file mode 100644 index 000000000..04a9add09 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/msadpcm_decoder.c @@ -0,0 +1,163 @@ +#include "../util.h" +#include "coding.h" + +/* used to compute next scale */ +static const int ADPCMTable[16] = +{ + 230, 230, 230, 230, + 307, 409, 512, 614, + 768, 614, 512, 409, + 307, 230, 230, 230 +}; + +static const int ADPCMCoeffs[7][2] = +{ + { 256, 0 }, + { 512, -256 }, + { 0, 0 }, + { 192, 64 }, + { 240, 0 }, + { 460, -208 }, + { 392, -232 } +}; + +long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) { + return bytes/block_size*((block_size-(7-1)*channels)*2/channels); +} + +void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) { + VGMSTREAMCHANNEL *ch1,*ch2; + int i; + int framesin; + STREAMFILE *streamfile; + off_t offset; + + framesin = first_sample/get_vgmstream_samples_per_frame(vgmstream); + first_sample = first_sample%get_vgmstream_samples_per_frame(vgmstream); + + ch1 = &vgmstream->ch[0]; + ch2 = &vgmstream->ch[1]; + streamfile = ch1->streamfile; + offset = ch1->offset+framesin*get_vgmstream_frame_size(vgmstream); + + if (first_sample==0) { + ch1->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset,streamfile)][0]; + ch1->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset,streamfile)][1]; + ch2->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][0]; + ch2->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][1]; + ch1->adpcm_scale = read_16bitLE(offset+2,streamfile); + ch2->adpcm_scale = read_16bitLE(offset+4,streamfile); + ch1->adpcm_history1_16 = read_16bitLE(offset+6,streamfile); + ch2->adpcm_history1_16 = read_16bitLE(offset+8,streamfile); + ch1->adpcm_history2_16 = read_16bitLE(offset+10,streamfile); + ch2->adpcm_history2_16 = read_16bitLE(offset+12,streamfile); + + outbuf[0] = ch1->adpcm_history2_16; + outbuf[1] = ch2->adpcm_history2_16; + + outbuf+=2; + first_sample++; + samples_to_do--; + } + if (first_sample==1 && samples_to_do > 0) { + outbuf[0] = ch1->adpcm_history1_16; + outbuf[1] = ch2->adpcm_history1_16; + + outbuf+=2; + first_sample++; + samples_to_do--; + } + + for (i=first_sample; ich[j]; + int sample_nibble = + (j == 0 ? + get_high_nibble_signed(read_8bit(offset+14+i-2,streamfile)) : + get_low_nibble_signed(read_8bit(offset+14+i-2,streamfile)) + ); + int32_t hist1,hist2; + int32_t predicted; + + hist1 = ch->adpcm_history1_16; + hist2 = ch->adpcm_history2_16; + predicted = hist1 * ch->adpcm_coef[0] + hist2 * ch->adpcm_coef[1]; + predicted /= 256; + predicted += sample_nibble*ch->adpcm_scale; + outbuf[0] = clamp16(predicted); + ch->adpcm_history2_16 = ch->adpcm_history1_16; + ch->adpcm_history1_16 = outbuf[0]; + ch->adpcm_scale = (ADPCMTable[sample_nibble&0xf] * + ch->adpcm_scale) / 256; + if (ch->adpcm_scale < 0x10) ch->adpcm_scale = 0x10; + + outbuf++; + } + } +} + +void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) { + VGMSTREAMCHANNEL *ch1; + int i; + int framesin; + STREAMFILE *streamfile; + off_t offset; + + framesin = first_sample/get_vgmstream_samples_per_frame(vgmstream); + first_sample = first_sample%get_vgmstream_samples_per_frame(vgmstream); + + ch1 = &vgmstream->ch[0]; + streamfile = ch1->streamfile; + offset = ch1->offset+framesin*get_vgmstream_frame_size(vgmstream); + + if (first_sample==0) { + ch1->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset,streamfile)][0]; + ch1->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset,streamfile)][1]; + ch1->adpcm_scale = read_16bitLE(offset+1,streamfile); + ch1->adpcm_history1_16 = read_16bitLE(offset+3,streamfile); + ch1->adpcm_history2_16 = read_16bitLE(offset+5,streamfile); + + outbuf[0] = ch1->adpcm_history2_16; + + outbuf++; + first_sample++; + samples_to_do--; + } + if (first_sample==1 && samples_to_do > 0) { + outbuf[0] = ch1->adpcm_history1_16; + + outbuf++; + first_sample++; + samples_to_do--; + } + + for (i=first_sample; ich[0]; + int sample_nibble = + (i & 1 ? + get_low_nibble_signed(read_8bit(offset+7+(i-2)/2,streamfile)) : + get_high_nibble_signed(read_8bit(offset+7+(i-2)/2,streamfile)) + ); + int32_t hist1,hist2; + int32_t predicted; + + hist1 = ch->adpcm_history1_16; + hist2 = ch->adpcm_history2_16; + predicted = hist1 * ch->adpcm_coef[0] + hist2 * ch->adpcm_coef[1]; + predicted /= 256; + predicted += sample_nibble*ch->adpcm_scale; + outbuf[0] = clamp16(predicted); + ch->adpcm_history2_16 = ch->adpcm_history1_16; + ch->adpcm_history1_16 = outbuf[0]; + ch->adpcm_scale = (ADPCMTable[sample_nibble&0xf] * + ch->adpcm_scale) / 256; + if (ch->adpcm_scale < 0x10) ch->adpcm_scale = 0x10; + + outbuf++; + } + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c new file mode 100644 index 000000000..d2d7f8933 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/mtaf_decoder.c @@ -0,0 +1,154 @@ +//#include +//#include +#include "coding.h" +#include "../util.h" + +// A hybrid of IMA and Yamaha ADPCM found in Metal Gear Solid 3 +// Thanks to X_Tra (http://metalgear.in/) for pointing me to the step size table. + +int index_table[16] = { + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +static int16_t step_size[32][16] = { +{ 1, 5, 9, 13, 16, 20, 24, 28, + -1, -5, -9, -13, -16, -20, -24, -28, }, +{ 2, 6, 11, 15, 20, 24, 29, 33, + -2, -6, -11, -15, -20, -24, -29, -33, }, +{ 2, 7, 13, 18, 23, 28, 34, 39, + -2, -7, -13, -18, -23, -28, -34, -39, }, +{ 3, 9, 15, 21, 28, 34, 40, 46, + -3, -9, -15, -21, -28, -34, -40, -46, }, +{ 3, 11, 18, 26, 33, 41, 48, 56, + -3, -11, -18, -26, -33, -41, -48, -56, }, +{ 4, 13, 22, 31, 40, 49, 58, 67, + -4, -13, -22, -31, -40, -49, -58, -67, }, +{ 5, 16, 26, 37, 48, 59, 69, 80, + -5, -16, -26, -37, -48, -59, -69, -80, }, +{ 6, 19, 31, 44, 57, 70, 82, 95, + -6, -19, -31, -44, -57, -70, -82, -95, }, +{ 7, 22, 38, 53, 68, 83, 99, 114, + -7, -22, -38, -53, -68, -83, -99, -114, }, +{ 9, 27, 45, 63, 81, 99, 117, 135, + -9, -27, -45, -63, -81, -99, -117, -135, }, +{ 10, 32, 53, 75, 96, 118, 139, 161, + -10, -32, -53, -75, -96, -118, -139, -161, }, +{ 12, 38, 64, 90, 115, 141, 167, 193, + -12, -38, -64, -90, -115, -141, -167, -193, }, +{ 15, 45, 76, 106, 137, 167, 198, 228, + -15, -45, -76, -106, -137, -167, -198, -228, }, +{ 18, 54, 91, 127, 164, 200, 237, 273, + -18, -54, -91, -127, -164, -200, -237, -273, }, +{ 21, 65, 108, 152, 195, 239, 282, 326, + -21, -65, -108, -152, -195, -239, -282, -326, }, +{ 25, 77, 129, 181, 232, 284, 336, 388, + -25, -77, -129, -181, -232, -284, -336, -388, }, +{ 30, 92, 153, 215, 276, 338, 399, 461, + -30, -92, -153, -215, -276, -338, -399, -461, }, +{ 36, 109, 183, 256, 329, 402, 476, 549, + -36, -109, -183, -256, -329, -402, -476, -549, }, +{ 43, 130, 218, 305, 392, 479, 567, 654, + -43, -130, -218, -305, -392, -479, -567, -654, }, +{ 52, 156, 260, 364, 468, 572, 676, 780, + -52, -156, -260, -364, -468, -572, -676, -780, }, +{ 62, 186, 310, 434, 558, 682, 806, 930, + -62, -186, -310, -434, -558, -682, -806, -930, }, +{ 73, 221, 368, 516, 663, 811, 958, 1106, + -73, -221, -368, -516, -663, -811, -958, -1106, }, +{ 87, 263, 439, 615, 790, 966, 1142, 1318, + -87, -263, -439, -615, -790, -966, -1142, -1318, }, +{ 104, 314, 523, 733, 942, 1152, 1361, 1571, + -104, -314, -523, -733, -942, -1152, -1361, -1571, }, +{ 124, 374, 623, 873, 1122, 1372, 1621, 1871, + -124, -374, -623, -873, -1122, -1372, -1621, -1871, }, +{ 148, 445, 743, 1040, 1337, 1634, 1932, 2229, + -148, -445, -743, -1040, -1337, -1634, -1932, -2229, }, +{ 177, 531, 885, 1239, 1593, 1947, 2301, 2655, + -177, -531, -885, -1239, -1593, -1947, -2301, -2655, }, +{ 210, 632, 1053, 1475, 1896, 2318, 2739, 3161, + -210, -632, -1053, -1475, -1896, -2318, -2739, -3161, }, +{ 251, 753, 1255, 1757, 2260, 2762, 3264, 3766, + -251, -753, -1255, -1757, -2260, -2762, -3264, -3766, }, +{ 299, 897, 1495, 2093, 2692, 3290, 3888, 4486, + -299, -897, -1495, -2093, -2692, -3290, -3888, -4486, }, +{ 356, 1068, 1781, 2493, 3206, 3918, 4631, 5343, + -356, -1068, -1781, -2493, -3206, -3918, -4631, -5343, }, +{ 424, 1273, 2121, 2970, 3819, 4668, 5516, 6365, + -424, -1273, -2121, -2970, -3819, -4668, -5516, -6365, }, +}; + + +void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels) { + int32_t sample_count; + int framesin = first_sample / 0x100; + unsigned long cur_off = stream->offset + framesin*(0x10+0x80*2)*(channels/2); + int i; + int c = channel%2; + int16_t init_idx = read_16bitLE(cur_off+4+c*2, stream->streamfile); + int16_t init_hist = read_16bitLE(cur_off+8+c*4, stream->streamfile); + int32_t hist = stream->adpcm_history1_16; + int step_idx = stream->adpcm_step_index; + + //printf("channel %d: first_sample = %d, stream->offset = 0x%lx, cur_off = 0x%lx init_idx = %d\n", channel, first_sample, (unsigned long)stream->offset, cur_off, init_idx); + +#if 0 + if (init_idx < 0 || init_idx > 31) { + fprintf(stderr, "step idx out of range at 0x%lx ch %d\n", cur_off, c); + exit(1); + } + if (0 != read_16bitLE(cur_off+10+c*4, stream->streamfile)) { + fprintf(stderr, "exp. zero after hist at 0x%lx ch %d\n", cur_off, c); + exit(1); + } +#endif + + first_sample = first_sample%0x100; + + if (first_sample%0x100 == 0) { + hist = init_hist; + +#if 0 + if (step_idx != init_idx) { + fprintf(stderr, "step_idx does not match at 0x%lx, %d!=%d\n",cur_off,step_idx, init_idx); + exit(1); + } +#endif + step_idx = init_idx; + } + + + for (i=first_sample,sample_count=0; istreamfile); + if (i%2!=1) + { + // low nibble first + nibble = byte&0xf; + } + else + { + // high nibble last + nibble = byte >> 4; + } + + hist = clamp16(hist+step_size[step_idx][nibble]); + + outbuf[sample_count] = hist; + + step_idx += index_table[nibble]; + if (step_idx < 0) + { + step_idx = 0; + } + if (step_idx > 31) + { + step_idx = 31; + } + } /* end sample loop */ + + // update state + stream->adpcm_step_index = step_idx; + stream->adpcm_history1_16 = hist; + +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/nds_procyon_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/nds_procyon_decoder.c new file mode 100644 index 000000000..75f86125b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/nds_procyon_decoder.c @@ -0,0 +1,60 @@ +#include "coding.h" +#include "../util.h" + +/* ADPCM found in NDS games using Procyon Studio Digital Sound Elements */ + +static const int8_t proc_coef[5][2] = +{ + {0x00,0x00}, + {0x3C,0x00}, + {0x73,0xCC}, + {0x62,0xC9}, + {0x7A,0xC4}, +}; + +void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/30; + + uint8_t header = read_8bit(framesin*16+15+stream->offset,stream->streamfile) ^ 0x80; + int scale = 12 - (header & 0xf); + int coef_index = (header >> 4) & 0xf; + int32_t hist1 = stream->adpcm_history1_32; + int32_t hist2 = stream->adpcm_history2_32; + int32_t coef1; + int32_t coef2; + + if (coef_index > 4) coef_index = 0; + coef1 = proc_coef[coef_index][0]; + coef2 = proc_coef[coef_index][1]; + first_sample = first_sample%30; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile) ^ 0x80; + + int32_t sample = + (int32_t) + (i&1? + get_high_nibble_signed(sample_byte): + get_low_nibble_signed(sample_byte) + ) * 64 * 64; + if (scale < 0) + { + sample <<= -scale; + } + else + sample >>= scale; + + sample = (hist1 * coef1 + hist2 * coef2 + 32) / 64 + (sample * 64); + + hist2 = hist1; + hist1 = sample; + + outbuf[sample_count] = clamp16((sample + 32) / 64) / 64 * 64; + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_history2_32 = hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_afc_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_afc_decoder.c new file mode 100644 index 000000000..8c796f951 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_afc_decoder.c @@ -0,0 +1,58 @@ +#include "coding.h" +#include "../util.h" + +const short afc_coef[16][2] = +{{0,0}, +{0x0800,0}, +{0,0x0800}, +{0x0400,0x0400}, +{0x1000,0xf800}, +{0x0e00,0xfa00}, +{0x0c00,0xfc00}, +{0x1200,0xf600}, +{0x1068,0xf738}, +{0x12c0,0xf704}, +{0x1400,0xf400}, +{0x0800,0xf800}, +{0x0400,0xfc00}, +{0xfc00,0x0400}, +{0xfc00,0}, +{0xf800,0}}; + +void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/16; + + int8_t header = read_8bit(framesin*9+stream->offset,stream->streamfile); + int32_t scale = 1 << ((header>>4) & 0xf); + int coef_index = (header & 0xf); + int32_t hist1 = stream->adpcm_history1_16; + int32_t hist2 = stream->adpcm_history2_16; + int coef1 = afc_coef[coef_index][0]; + int coef2 = afc_coef[coef_index][1]; + /*printf("offset: %x\nscale: %d\nindex: %d (%lf,%lf)\nhist: %d %d\n", + (unsigned)stream->offset,scale,coef_index,coef1/2048.0,coef2/2048.0,hist1,hist2);*/ + + first_sample = first_sample%16; + + for (i=first_sample,sample_count=0; ioffset+1+i/2,stream->streamfile); + + outbuf[sample_count] = clamp16(( + (((i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) * scale)<<11) + + (coef1 * hist1 + coef2 * hist2))>>11 + ); + /*printf("%hd\n",outbuf[sample_count]);*/ + + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_history2_16 = hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c new file mode 100644 index 000000000..27825ae96 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dsp_decoder.c @@ -0,0 +1,106 @@ +#include "coding.h" +#include "../util.h" + +void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/14; + + int8_t header = read_8bit(framesin*8+stream->offset,stream->streamfile); + int32_t scale = 1 << (header & 0xf); + int coef_index = (header >> 4) & 0xf; + int32_t hist1 = stream->adpcm_history1_16; + int32_t hist2 = stream->adpcm_history2_16; + int coef1 = stream->adpcm_coef[coef_index*2]; + int coef2 = stream->adpcm_coef[coef_index*2+1]; + + first_sample = first_sample%14; + + for (i=first_sample,sample_count=0; ioffset+1+i/2,stream->streamfile); + +#ifdef DEBUG + if (hist1==stream->loop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done); + stream->samples_done++; +#endif + + outbuf[sample_count] = clamp16(( + (((i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) * scale)<<11) + 1024 + + (coef1 * hist1 + coef2 * hist2))>>11 + ); + + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_history2_16 = hist2; +} + +/* read from memory rather than a file */ +void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/14; + + int8_t header = mem[framesin*8]; + int32_t scale = 1 << (header & 0xf); + int coef_index = (header >> 4) & 0xf; + int32_t hist1 = stream->adpcm_history1_16; + int32_t hist2 = stream->adpcm_history2_16; + int coef1 = stream->adpcm_coef[coef_index*2]; + int coef2 = stream->adpcm_coef[coef_index*2+1]; + + first_sample = first_sample%14; + + for (i=first_sample,sample_count=0; iloop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done); + stream->samples_done++; +#endif + + outbuf[sample_count] = clamp16(( + (((i&1? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) * scale)<<11) + 1024 + + (coef1 * hist1 + coef2 * hist2))>>11 + ); + + hist2 = hist1; + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_history2_16 = hist2; +} + +/* + * The original DSP spec uses nibble counts for loop points, and some + * variants don't have a proper sample count, so we (who are interested + * in sample counts) need to do this conversion occasionally. + */ +int32_t dsp_nibbles_to_samples(int32_t nibbles) { + int32_t whole_frames = nibbles/16; + int32_t remainder = nibbles%16; + + /* + fprintf(stderr,"%d (%#x) nibbles => %x bytes and %d samples\n",nibbles,nibbles,whole_frames*8,remainder); + */ + +#if 0 + if (remainder > 0 && remainder < 14) + return whole_frames*14 + remainder; + else if (remainder >= 14) + fprintf(stderr,"***** last frame %d leftover nibbles makes no sense\n",remainder); +#endif + if (remainder>0) return whole_frames*14+remainder-2; + else return whole_frames*14; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c new file mode 100644 index 000000000..21d189021 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ngc_dtk_decoder.c @@ -0,0 +1,53 @@ +#include "coding.h" +#include "../util.h" + +void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i=first_sample; + int32_t sample_count; + + int framesin = first_sample/28; + + uint8_t q = read_8bit(framesin*32+stream->offset+channel,stream->streamfile); + int32_t hist1 = stream->adpcm_history1_32; + int32_t hist2 = stream->adpcm_history2_32; + + first_sample = first_sample%28; + + for (i=first_sample,sample_count=0; ioffset+4+i,stream->streamfile); + + int32_t hist=0; + + switch (q>>4) + { + case 0: + hist = 0; + break; + case 1: + hist = (hist1 * 0x3c); + break; + case 2: + hist = (hist1 * 0x73) - (hist2 * 0x34); + break; + case 3: + hist = (hist1 * 0x62) - (hist2 * 0x37); + break; + } + + hist = (hist+0x20)>>6; + if (hist > 0x1fffff) hist = 0x1fffff; + if (hist < -0x200000) hist = -0x200000; + + hist2 = hist1; + + hist1 = ((((channel==0? + get_low_nibble_signed(sample_byte): + get_high_nibble_signed(sample_byte) + ) << 12) >> (q & 0xf)) << 6) + hist; + + outbuf[sample_count] = clamp16(hist1 >> 6); + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_history2_32 = hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.c new file mode 100644 index 000000000..cc14a5d64 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.c @@ -0,0 +1,351 @@ +/* originally from nwatowav.cc 2007.7.28 version, which read: */ +/* + * Copyright 2001-2007 jagarl / Kazunori Ueno + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * ¤³¤Î¥×¥í¥°¥é¥à¤Îºî¼Ô¤Ï jagarl ¤Ç¤¹¡£ + * + * ¤³¤Î¥×¥í¥°¥é¥à¡¢µÚ¤Ó¥³¥ó¥Ñ¥¤¥ë¤Ë¤è¤Ã¤ÆÀ¸À®¤·¤¿¥Ð¥¤¥Ê¥ê¤Ï + * ¥×¥í¥°¥é¥à¤òÊѹ¹¤¹¤ë¡¢¤·¤Ê¤¤¤Ë¤«¤«¤ï¤é¤ººÆÇÛÉÛ²Äǽ¤Ç¤¹¡£ + * ¤½¤ÎºÝ¡¢¾åµ­ Copyright ɽ¼¨¤òÊÝ»ý¤¹¤ë¤Ê¤É¤Î¾ò·ï¤Ï²Ý¤·¤Þ + * ¤»¤ó¡£Âбþ¤¬ÌÌÅݤʤΤǥХ°Êó¹ð¤ò½ü¤­¡¢¥á¡¼¥ë¤ÇÏ¢Íí¤ò¤¹¤ë + * ¤Ê¤É¤ÎɬÍפ⤢¤ê¤Þ¤»¤ó¡£¥½¡¼¥¹¤Î°ìÉô¤òήÍѤ¹¤ë¤³¤È¤ò´Þ¤á¡¢ + * ¤´¼«Í³¤Ë¤ª»È¤¤¤¯¤À¤µ¤¤¡£ + * + * THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +#include +#include "nwa_decoder.h" + +/* can serve up 8 bits at a time */ +static int +getbits (STREAMFILE *file, off_t *offset, int *shift, int bits) +{ + int ret; + if (*shift > 8) + { + ++*offset; + *shift -= 8; + } + ret = read_16bitLE(*offset,file) >> *shift; + *shift += bits; + return ret & ((1 << bits) - 1); /* mask */ +} + +NWAData * +open_nwa (STREAMFILE * streamFile, const char *filename) +{ + int i; + NWAData * const nwa = malloc(sizeof(NWAData)); + if (!nwa) goto fail; + + nwa->channels = read_16bitLE(0x00,streamFile); + nwa->bps = read_16bitLE(0x02,streamFile); + nwa->freq = read_32bitLE(0x04,streamFile); + nwa->complevel = read_32bitLE(0x08,streamFile); + nwa->blocks = read_32bitLE(0x10,streamFile); + nwa->datasize = read_32bitLE(0x14,streamFile); + nwa->compdatasize = read_32bitLE(0x18,streamFile); + nwa->samplecount = read_32bitLE(0x1c,streamFile); + nwa->blocksize = read_32bitLE(0x20,streamFile); + nwa->restsize = read_32bitLE(0x24,streamFile); + nwa->offsets = NULL; + nwa->buffer = NULL; + nwa->buffer_readpos = NULL; + nwa->file = NULL; + + /* PCM not handled here */ + if (nwa->complevel < 0 || nwa->complevel > 5) goto fail; + + if (nwa->channels != 1 && nwa->channels != 2) goto fail; + + if (nwa->bps != 8 && nwa->bps != 16) goto fail; + + if (nwa->blocks <= 0) goto fail; + + if (nwa->compdatasize == 0 + || get_streamfile_size(streamFile) != nwa->compdatasize) goto fail; + + if (nwa->datasize != nwa->samplecount * (nwa->bps/8)) goto fail; + + if (nwa->samplecount != + (nwa->blocks-1) * nwa->blocksize + nwa->restsize) goto fail; + + nwa->offsets = malloc(sizeof(off_t)*nwa->blocks); + if (!nwa->offsets) goto fail; + + for (i = 0; i < nwa->blocks; i++) + { + int32_t o = read_32bitLE(0x2c+i*4,streamFile); + if (o < 0) goto fail; + nwa->offsets[i] = o; + } + + if (nwa->offsets[nwa->blocks-1] >= nwa->compdatasize) goto fail; + + if (nwa->restsize > nwa->blocksize) nwa->buffer = + malloc(sizeof(sample)*nwa->restsize); + else nwa->buffer = + malloc(sizeof(sample)*nwa->blocksize); + if (nwa->buffer == NULL) goto fail; + + nwa->buffer_readpos = nwa->buffer; + + nwa->samples_in_buffer = 0; + + nwa->curblock = 0; + + /* if we got this far, it's probably safe */ + nwa->file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!nwa->file) goto fail; + + return nwa; +fail: + if (nwa) + { + close_nwa(nwa); + } + + return NULL; +} + +void +close_nwa(NWAData * nwa) +{ + if (!nwa) return; + + if (nwa->offsets) + free (nwa->offsets); + nwa->offsets = NULL; + if (nwa->buffer) + free (nwa->buffer); + nwa->buffer = NULL; + if (nwa->file) + close_streamfile (nwa->file); + nwa->file = NULL; + free(nwa); +} + +void +reset_nwa(NWAData *nwa) +{ + nwa->curblock = 0; + nwa->buffer_readpos = nwa->buffer; + nwa->samples_in_buffer = 0; +} + +static int use_runlength(NWAData *nwa) +{ + if (nwa->channels == 2 && nwa->bps == 16 && nwa->complevel == 2) + { + /* sw2 */ + return 0; + } + if (nwa->complevel == 5) + { + if (nwa->channels == 2) return 0; /* BGM*.nwa in Little Busters! */ + return 1; /* Tomoyo After (.nwk koe file) */ + } + return 0; +} + +static void +nwa_decode_block(NWAData *nwa) +{ + /* º£²óÆÉ¤ß¹þ¤à¡¿¥Ç¥³¡¼¥É¤¹¤ë¥Ç¡¼¥¿¤ÎÂ礭¤µ¤òÆÀ¤ë */ + int curblocksize, curcompsize; + if (nwa->curblock != nwa->blocks - 1) + { + curblocksize = nwa->blocksize * (nwa->bps / 8); + curcompsize = nwa->offsets[nwa->curblock + 1] - nwa->offsets[nwa->curblock]; + } + else + { + curblocksize = nwa->restsize * (nwa->bps / 8); + curcompsize = nwa->blocksize * (nwa->bps / 8) * 2; + } + + nwa->samples_in_buffer = 0; + nwa->buffer_readpos = nwa->buffer; + + { + sample d[2]; + int i; + int shift = 0; + off_t offset = nwa->offsets[nwa->curblock]; + int dsize = curblocksize / (nwa->bps / 8); + int flip_flag = 0; /* stereo ÍÑ */ + int runlength = 0; + + /* read initial sample value */ + for (i=0;ichannels;i++) + { + if (nwa->bps == 8) { d[i] = read_8bit(offset,nwa->file); } + else /* bps == 16 */ + { + d[i] = read_16bitLE(offset,nwa->file); + offset += 2; + } + } + + for (i = 0; i < dsize; i++) + { + if (runlength == 0) + { /* ¥³¥Ô¡¼¥ë¡¼¥×Ãæ¤Ç¤Ê¤¤¤Ê¤é¥Ç¡¼¥¿ÆÉ¤ß¹þ¤ß */ + int type = getbits(nwa->file, &offset, &shift, 3); + /* type ¤Ë¤è¤êʬ´ô¡§0, 1-6, 7 */ + if (type == 7) + { + /* 7 : Â礭¤Êº¹Ê¬ */ + /* RunLength() Í­¸ú»þ¡ÊCompLevel==5, ²»À¼¥Õ¥¡¥¤¥ë) ¤Ç¤Ï̵¸ú */ + if (getbits(nwa->file, &offset, &shift, 1) == 1) + { + d[flip_flag] = 0; /* ̤»ÈÍÑ */ + } + else + { + int BITS, SHIFT; + if (nwa->complevel >= 3) + { + BITS = 8; + SHIFT = 9; + } + else + { + BITS = 8 - nwa->complevel; + SHIFT = 2 + 7 + nwa->complevel; + } + { + const int MASK1 = (1 << (BITS - 1)); + const int MASK2 = (1 << (BITS - 1)) - 1; + int b = getbits(nwa->file, &offset, &shift, BITS); + if (b & MASK1) + d[flip_flag] -= (b & MASK2) << SHIFT; + else + d[flip_flag] += (b & MASK2) << SHIFT; + } + } + } + else if (type != 0) + { + /* 1-6 : Ä̾ï¤Îº¹Ê¬ */ + int BITS, SHIFT; + if (nwa->complevel >= 3) + { + BITS = nwa->complevel + 3; + SHIFT = 1 + type; + } + else + { + BITS = 5 - nwa->complevel; + SHIFT = 2 + type + nwa->complevel; + } + { + const int MASK1 = (1 << (BITS - 1)); + const int MASK2 = (1 << (BITS - 1)) - 1; + int b = getbits(nwa->file, &offset, &shift, BITS); + if (b & MASK1) + d[flip_flag] -= (b & MASK2) << SHIFT; + else + d[flip_flag] += (b & MASK2) << SHIFT; + } + } + else + { /* type == 0 */ + /* ¥é¥ó¥ì¥ó¥°¥¹°µ½Ì¤Ê¤·¤Î¾ì¹ç¤Ï¤Ê¤Ë¤â¤·¤Ê¤¤ */ + if (use_runlength(nwa)) + { + /* ¥é¥ó¥ì¥ó¥°¥¹°µ½Ì¤¢¤ê¤Î¾ì¹ç */ + runlength = getbits(nwa->file, &offset, &shift, 1); + if (runlength == 1) + { + runlength = getbits(nwa->file, &offset, &shift, 2); + if (runlength == 3) + { + runlength = getbits(nwa->file, &offset, &shift, 8); + } + } + } + } + } + else + { + runlength--; + } + if (nwa->bps == 8) + { + nwa->buffer[i] = d[flip_flag]*0x100; + } + else + { + nwa->buffer[i] = d[flip_flag]; + } + nwa->samples_in_buffer++; + if (nwa->channels == 2) + flip_flag ^= 1; /* channel ÀÚ¤êÂØ¤¨ */ + } + } + + nwa->curblock++; + return; +} + +void +seek_nwa(NWAData *nwa, int32_t seekpos) +{ + int dest_block = seekpos/(nwa->blocksize/nwa->channels); + int32_t remainder = seekpos%(nwa->blocksize/nwa->channels); + + nwa->curblock = dest_block; + + nwa_decode_block(nwa); + + nwa->buffer_readpos = nwa->buffer + remainder*nwa->channels; + nwa->samples_in_buffer -= remainder*nwa->channels; +} + +/* interface to vgmstream */ +void +decode_nwa(NWAData *nwa, sample *outbuf, + int32_t samples_to_do) +{ + while (samples_to_do > 0) + { + int32_t samples_to_read; + + if (nwa->samples_in_buffer > 0) + { + samples_to_read = nwa->samples_in_buffer/nwa->channels; + if (samples_to_read > samples_to_do) + samples_to_read = samples_to_do; + + memcpy(outbuf,nwa->buffer_readpos, + sizeof(sample)*samples_to_read*nwa->channels); + + nwa->buffer_readpos += samples_to_read*nwa->channels; + nwa->samples_in_buffer -= samples_to_read*nwa->channels; + outbuf += samples_to_read*nwa->channels; + samples_to_do -= samples_to_read; + } + else + { + nwa_decode_block(nwa); + } + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.h b/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.h new file mode 100644 index 000000000..2dbd9f1ef --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/nwa_decoder.h @@ -0,0 +1,71 @@ +/* originally from nwatowav.cc 2007.7.28 version, which read: */ +/* + * Copyright 2001-2007 jagarl / Kazunori Ueno + * All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted. + * + * ¤³¤Î¥×¥í¥°¥é¥à¤Îºî¼Ô¤Ï jagarl ¤Ç¤¹¡£ + * + * ¤³¤Î¥×¥í¥°¥é¥à¡¢µÚ¤Ó¥³¥ó¥Ñ¥¤¥ë¤Ë¤è¤Ã¤ÆÀ¸À®¤·¤¿¥Ð¥¤¥Ê¥ê¤Ï + * ¥×¥í¥°¥é¥à¤òÊѹ¹¤¹¤ë¡¢¤·¤Ê¤¤¤Ë¤«¤«¤ï¤é¤ººÆÇÛÉÛ²Äǽ¤Ç¤¹¡£ + * ¤½¤ÎºÝ¡¢¾åµ­ Copyright ɽ¼¨¤òÊÝ»ý¤¹¤ë¤Ê¤É¤Î¾ò·ï¤Ï²Ý¤·¤Þ + * ¤»¤ó¡£Âбþ¤¬ÌÌÅݤʤΤǥХ°Êó¹ð¤ò½ü¤­¡¢¥á¡¼¥ë¤ÇÏ¢Íí¤ò¤¹¤ë + * ¤Ê¤É¤ÎɬÍפ⤢¤ê¤Þ¤»¤ó¡£¥½¡¼¥¹¤Î°ìÉô¤òήÍѤ¹¤ë¤³¤È¤ò´Þ¤á¡¢ + * ¤´¼«Í³¤Ë¤ª»È¤¤¤¯¤À¤µ¤¤¡£ + * + * THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE + * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + */ + +#ifndef _NWA_DECODER_H +#define _NWA_DECODER_H + +#ifdef BUILD_VGMSTREAM +#include "../streamfile.h" +#else +#include "streamfile.h" +#endif + +typedef struct NWAData_s +{ + int channels; + int bps; /* bits per sample */ + int freq; /* samples per second */ + int complevel; /* compression level */ + int blocks; /* block count */ + int datasize; /* all data size */ + int compdatasize; /* compressed data size */ + int samplecount; /* all samples */ + int blocksize; /* samples per block */ + int restsize; /* samples of the last block */ + + int curblock; + off_t *offsets; + + STREAMFILE *file; + + /* temporarily store samples */ + sample *buffer; + sample *buffer_readpos; + int samples_in_buffer; +} NWAData; + +NWAData *open_nwa(STREAMFILE *streamFile, const char *filename); +void close_nwa(NWAData *nwa); +void reset_nwa(NWAData *nwa); +void seek_nwa(NWAData *nwa, int32_t seekpos); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ogg_vorbis_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ogg_vorbis_decoder.c new file mode 100644 index 000000000..5f571d1e7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ogg_vorbis_decoder.c @@ -0,0 +1,22 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_VORBIS +#include +#include "coding.h" +#include "../util.h" + +void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) { + int samples_done = 0; + OggVorbis_File *ogg_vorbis_file = &data->ogg_vorbis_file; + + do { + long rc = ov_read(ogg_vorbis_file, (char *)(outbuf + samples_done*channels), + (samples_to_do - samples_done)*sizeof(sample)*channels, 0, + sizeof(sample), 1, &data->bitstream); + + if (rc > 0) samples_done += rc/sizeof(sample)/channels; + else return; + } while (samples_done < samples_to_do); +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c new file mode 100644 index 000000000..3ae9bcea8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/pcm_decoder.c @@ -0,0 +1,87 @@ +#include "coding.h" +#include "../util.h" + +void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*2,stream->streamfile); + } +} + +void decode_pcm16BE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*2,stream->streamfile); + } +} + +void decode_pcm8(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile)*0x100; + } +} + +void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*channelspacing,stream->streamfile)*0x100; + } +} + +void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*channelspacing,stream->streamfile); + if (v&0x80) v = 0-(v&0x7f); + outbuf[sample_count] = v*0x100; + } +} + +void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*channelspacing,stream->streamfile); + outbuf[sample_count] = v*0x100 - 0x8000; + } +} + +void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + outbuf[sample_count] = v*0x100 - 0x8000; + } +} + +void decode_pcm16LE_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*2*channelspacing,stream->streamfile); + } +} + +void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*2*channelspacing,stream->streamfile)^stream->key_xor; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c new file mode 100644 index 000000000..7674f573e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/psx_decoder.c @@ -0,0 +1,214 @@ +#include +#include "coding.h" +#include "../util.h" + +double VAG_f[5][2] = { { 0.0 , 0.0 }, + { 60.0 / 64.0 , 0.0 }, + { 115.0 / 64.0 , -52.0 / 64.0 }, + { 98.0 / 64.0 , -55.0 / 64.0 } , + { 122.0 / 64.0 , -60.0 / 64.0 } } ; +long VAG_coefs[5][2] = { { 0 , 0 }, + { 60 , 0 }, + { 115 , -52 }, + { 98 , -55 } , + { 122 , -60 } } ; + +void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + + short scale; + int i; + int32_t sample_count; + uint8_t flag; + + int framesin = first_sample/28; + + predict_nr = read_8bit(stream->offset+framesin*16,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+framesin*16,stream->streamfile) & 0xf; + flag = read_8bit(stream->offset+framesin*16+1,stream->streamfile); + + first_sample = first_sample % 28; + + for (i=first_sample,sample_count=0; ioffset+(framesin*16)+2+i/2,stream->streamfile); + + scale = ((i&1 ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + + sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]); + } + + outbuf[sample_count] = clamp16(sample); + hist2=hist1; + hist1=sample; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} + +void decode_invert_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + + short scale; + int i; + int32_t sample_count; + uint8_t flag; + + int framesin = first_sample/28; + int head = read_8bit(stream->offset+framesin*16,stream->streamfile) ^ stream->bmdx_xor; + + predict_nr = ((head >> 4) & 0xf); + shift_factor = (head & 0xf); + flag = read_8bit(stream->offset+framesin*16+1,stream->streamfile); + + first_sample = first_sample % 28; + + for (i=first_sample,sample_count=0; ioffset+(framesin*16)+2+i/2,stream->streamfile); + if (i/2 == 0) + sample_byte = (short)(int8_t)(sample_byte+stream->bmdx_add); + + scale = ((i&1 ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + + sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]); + } + + outbuf[sample_count] = clamp16(sample); + hist2=hist1; + hist1=sample; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} + +/* some TAITO games have garbage (?) in their flags, this decoder + * just ignores that byte */ +void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + + short scale; + int i; + int32_t sample_count; + + int framesin = first_sample/28; + + predict_nr = read_8bit(stream->offset+framesin*16,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+framesin*16,stream->streamfile) & 0xf; + first_sample = first_sample % 28; + + for (i=first_sample,sample_count=0; ioffset+(framesin*16)+2+i/2,stream->streamfile); + + scale = ((i&1 ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + + sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]); + + outbuf[sample_count] = clamp16(sample); + hist2=hist1; + hist1=sample; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} + +/* FF XI's Vag-ish format */ +void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + + short scale; + int i; + int32_t sample_count; + long predictor; + + int framesin = first_sample/16; + + predict_nr = read_8bit(stream->offset+framesin*9,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+framesin*9,stream->streamfile) & 0xf; + first_sample = first_sample % 16; + + for (i=first_sample,sample_count=0; ioffset+(framesin*9)+1+i/2,stream->streamfile); + + sample=0; + + scale = ((i&1 ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + +#if 1 + predictor = + (int)((hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1])); +#else + predictor = + (hist1*VAG_coefs[predict_nr][0]+hist2*VAG_coefs[predict_nr][1])/64; +#endif + sample=(scale >> shift_factor) + predictor; + + outbuf[sample_count] = clamp16(sample); + hist2=hist1; + hist1=sample; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} + +void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + + short scale; + int i; + int32_t sample_count; + + int framesin = first_sample/64; + + predict_nr = read_8bit(stream->offset+framesin*33,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+framesin*33,stream->streamfile) & 0xf; + + first_sample = first_sample % 64; + + for (i=first_sample,sample_count=0; ioffset+(framesin*33)+1+i/2,stream->streamfile); + + scale = ((i&1 ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + + sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]); + + outbuf[sample_count] = clamp16(sample); + hist2=hist1; + hist1=sample; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/sdx2_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/sdx2_decoder.c new file mode 100644 index 000000000..b911f511e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/sdx2_decoder.c @@ -0,0 +1,118 @@ +#include +#include "coding.h" +#include "../util.h" + +/* SDX2 - 2:1 Squareroot-delta-exact compression */ +/* CBD2 - 2:1 Cuberoot-delta-exact compression (from the unreleased 3DO M2) */ + +/* for (i=-128;i<128;i++) squares[i+128]=i<0?(-i*i)*2:(i*i)*2; */ +static int16_t squares[256] = { +-32768,-32258,-31752,-31250,-30752,-30258,-29768,-29282,-28800,-28322,-27848, +-27378,-26912,-26450,-25992,-25538,-25088,-24642,-24200,-23762,-23328,-22898, +-22472,-22050,-21632,-21218,-20808,-20402,-20000,-19602,-19208,-18818,-18432, +-18050,-17672,-17298,-16928,-16562,-16200,-15842,-15488,-15138,-14792,-14450, +-14112,-13778,-13448,-13122,-12800,-12482,-12168,-11858,-11552,-11250,-10952, +-10658,-10368,-10082, -9800, -9522, -9248, -8978, -8712, -8450, -8192, -7938, + -7688, -7442, -7200, -6962, -6728, -6498, -6272, -6050, -5832, -5618, -5408, + -5202, -5000, -4802, -4608, -4418, -4232, -4050, -3872, -3698, -3528, -3362, + -3200, -3042, -2888, -2738, -2592, -2450, -2312, -2178, -2048, -1922, -1800, + -1682, -1568, -1458, -1352, -1250, -1152, -1058, -968, -882, -800, -722, + -648, -578, -512, -450, -392, -338, -288, -242, -200, -162, -128, + -98, -72, -50, -32, -18, -8, -2, 0, 2, 8, 18, + 32, 50, 72, 98, 128, 162, 200, 242, 288, 338, 392, + 450, 512, 578, 648, 722, 800, 882, 968, 1058, 1152, 1250, + 1352, 1458, 1568, 1682, 1800, 1922, 2048, 2178, 2312, 2450, 2592, + 2738, 2888, 3042, 3200, 3362, 3528, 3698, 3872, 4050, 4232, 4418, + 4608, 4802, 5000, 5202, 5408, 5618, 5832, 6050, 6272, 6498, 6728, + 6962, 7200, 7442, 7688, 7938, 8192, 8450, 8712, 8978, 9248, 9522, + 9800, 10082, 10368, 10658, 10952, 11250, 11552, 11858, 12168, 12482, 12800, + 13122, 13448, 13778, 14112, 14450, 14792, 15138, 15488, 15842, 16200, 16562, + 16928, 17298, 17672, 18050, 18432, 18818, 19208, 19602, 20000, 20402, 20808, + 21218, 21632, 22050, 22472, 22898, 23328, 23762, 24200, 24642, 25088, 25538, + 25992, 26450, 26912, 27378, 27848, 28322, 28800, 29282, 29768, 30258, 30752, + 31250, 31752, 32258 +}; + +//for (i=-128;i<128;i++) +//{ +// double j = (i/2)/2.0; +// cubes[i+128]=floor(j*j*j); +//} +static int16_t cubes[256]={ +-32768,-31256,-31256,-29791,-29791,-28373,-28373,-27000,-27000,-25672,-25672, +-24389,-24389,-23149,-23149,-21952,-21952,-20797,-20797,-19683,-19683,-18610, +-18610,-17576,-17576,-16581,-16581,-15625,-15625,-14706,-14706,-13824,-13824, +-12978,-12978,-12167,-12167,-11391,-11391,-10648,-10648, -9938, -9938, -9261, + -9261, -8615, -8615, -8000, -8000, -7415, -7415, -6859, -6859, -6332, -6332, + -5832, -5832, -5359, -5359, -4913, -4913, -4492, -4492, -4096, -4096, -3724, + -3724, -3375, -3375, -3049, -3049, -2744, -2744, -2460, -2460, -2197, -2197, + -1953, -1953, -1728, -1728, -1521, -1521, -1331, -1331, -1158, -1158, -1000, + -1000, -857, -857, -729, -729, -614, -614, -512, -512, -422, -422, + -343, -343, -275, -275, -216, -216, -166, -166, -125, -125, -91, + -91, -64, -64, -43, -43, -27, -27, -16, -16, -8, -8, + -3, -3, -1, -1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 3, 3, 8, 8, 16, 16, 27, 27, 43, + 43, 64, 64, 91, 91, 125, 125, 166, 166, 216, 216, + 275, 275, 343, 343, 422, 422, 512, 512, 614, 614, 729, + 729, 857, 857, 1000, 1000, 1158, 1158, 1331, 1331, 1521, 1521, + 1728, 1728, 1953, 1953, 2197, 2197, 2460, 2460, 2744, 2744, 3049, + 3049, 3375, 3375, 3724, 3724, 4096, 4096, 4492, 4492, 4913, 4913, + 5359, 5359, 5832, 5832, 6332, 6332, 6859, 6859, 7415, 7415, 8000, + 8000, 8615, 8615, 9261, 9261, 9938, 9938, 10648, 10648, 11391, 11391, + 12167, 12167, 12978, 12978, 13824, 13824, 14706, 14706, 15625, 15625, 16581, + 16581, 17576, 17576, 18610, 18610, 19683, 19683, 20797, 20797, 21952, 21952, + 23149, 23149, 24389, 24389, 25672, 25672, 27000, 27000, 28373, 28373, 29791, + 29791, 31256, 31256}; +static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) { + + int32_t hist = stream->adpcm_history1_32; + + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + int16_t sample; + + if (!(sample_byte & 1)) hist = 0; + sample = hist + table[sample_byte+128]; + + hist = outbuf[sample_count] = clamp16(sample); + } + stream->adpcm_history1_32=hist; +} + +static void decode_delta_exact_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) { + + int32_t hist = stream->adpcm_history1_32; + + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset+i*channelspacing,stream->streamfile); + int16_t sample; + + if (!(sample_byte & 1)) hist = 0; + sample = hist + table[sample_byte+128]; + + hist = outbuf[sample_count] = clamp16(sample); + } + stream->adpcm_history1_32=hist; +} + +void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, squares); +} + +void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, squares); +} + +void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes); +} + +void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes); +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c new file mode 100644 index 000000000..b72193dc7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/ws_decoder.c @@ -0,0 +1,146 @@ +#include +#include "coding.h" +#include "../util.h" + +/* Westwood Studios ADPCM */ + +/* Based on Valery V. Anisimovsky's WS-AUD.txt */ + +static char WSTable2bit[4]={-2,-1,0,1}; +static char WSTable4bit[16]={-9,-8,-6,-5,-4,-3,-2,-1, + 0, 1, 2, 3, 4, 5 ,6, 8}; + +/* We pass in the VGMSTREAM here, unlike in other codings, because + the decoder has to know about the block structure. */ +void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, + int32_t samples_to_do) { + + VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]); + int16_t hist = stream->adpcm_history1_16; + off_t offset = stream->offset; + int samples_left_in_frame = stream->samples_left_in_frame; + off_t header_off = stream->frame_header_offset; + + int i; + int32_t sample_count; + + if (vgmstream->ws_output_size == vgmstream->current_block_size) { + /* uncompressed, we just need to convert to 16-bit */ + for (i=first_sample,sample_count=0; istreamfile)-0x80)*0x100; + } + } else { + if (first_sample == 0) { + hist = 0x80; + samples_left_in_frame = 0; + } + /* actually decompress */ + for (i=first_sample,sample_count=0; istreamfile); + count = header & 0x3f; + switch (header>>6) { /* code */ + case 0: /* 2-bit ADPCM */ + if (samples_left_in_frame == 0) { + samples_left_in_frame = (count + 1)*4; + } + for (;samples_left_in_frame>0 && /* read this frame */ + istreamfile); + sample = (sample >> (twobit*2)) & 0x3; + hist += WSTable2bit[sample]; + if (hist < 0) hist = 0; + if (hist > 0xff) hist = 0xff; + outbuf[sample_count]=(hist-0x80)*0x100; + + if (twobit == 3) + offset++; /* done with that byte */ + } + break; + case 1: /* 4-bit ADPCM */ + if (samples_left_in_frame == 0) { + samples_left_in_frame = (count + 1)*2; + } + for (;samples_left_in_frame>0 && /* read this frame */ + istreamfile); + if (nibble == 0) + sample &= 0xf; + else + sample >>= 4; + hist += WSTable4bit[sample]; + if (hist < 0) hist = 0; + if (hist > 0xff) hist = 0xff; + outbuf[sample_count]=(hist-0x80)*0x100; + + if (nibble == 1) + offset++; /* done with that byte */ + } + break; + case 2: /* no compression */ + if (count & 0x20) { /* delta */ + /* Note no checks against samples_to_do here, + at the top of the for loop we can always do at + least one sample */ + /* low 5 bits are a signed delta */ + if (count & 0x10) { + hist -= ((count & 0xf)^0xf) + 1; + } else { + hist += count & 0xf; + } + + /* Valery doesn't specify this, but I will assume */ + if (hist < 0) hist = 0; + if (hist > 0xff) hist = 0xff; + + outbuf[sample_count]=(hist-0x80)*0x100; + sample_count+=channelspacing; + i++; + + /* just one, and we got it */ + samples_left_in_frame = 0; + } else { /* copy bytes verbatim */ + if (samples_left_in_frame == 0) + samples_left_in_frame=count+1; + for (;samples_left_in_frame>0 && /* read this frame */ + istreamfile))-0x80)*0x100; + } + } + break; + case 3: /* RLE */ + if (samples_left_in_frame == 0) + samples_left_in_frame=count+1; + for (;samples_left_in_frame>0 && /* read this frame */ + ioffset = offset; + stream->adpcm_history1_16 = hist; + stream->samples_left_in_frame = samples_left_in_frame; + stream->frame_header_offset = header_off; +} diff --git a/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c new file mode 100644 index 000000000..083ce1037 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/coding/xa_decoder.c @@ -0,0 +1,72 @@ +#include "coding.h" +#include "../util.h" + +const int SH = 4; +const int SHC = 10; + +double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125}; +double K1[4] = { 0.0, 0.0, -0.8125,-0.859375}; + +int IK0(int fid) +{ return ((int)((-K0[fid]) * (1 << SHC))); } + +int IK1(int fid) +{ return ((int)((-K1[fid]) * (1 << SHC))); } + +int CLAMP(int value, int Minim, int Maxim) +{ + if (value < Minim) value = Minim; + if (value > Maxim) value = Maxim; + return value; +} + +void init_get_high_nibble(VGMSTREAM *vgmstream) { + vgmstream->get_high_nibble=1; +} + +void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + + VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]); + int predict_nr, shift_factor, sample; + int32_t hist1=stream->adpcm_history1_32; + int32_t hist2=stream->adpcm_history2_32; + int HeadTable[8]={0,2,8,10}; + + short scale; + int i; + int32_t sample_count; + + int framesin = first_sample / (56 / channelspacing); + + + first_sample = first_sample % 28; + + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + if((first_sample) && (channelspacing==1)) + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) >> 4; + shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) & 0xf; + + for (i=first_sample,sample_count=0; ioffset+16+framesin+(i*4),stream->streamfile); + + scale = ((vgmstream->get_high_nibble ? + sample_byte >> 4 : + sample_byte & 0x0f)<<12); + + sample = (short)(scale & 0xf000) >> shift_factor; + sample <<= SH; + sample -= (IK0(predict_nr) * hist1 + (IK1(predict_nr) * hist2)) >> SHC; + + hist2=hist1; + hist1=sample; + + sample = CLAMP(sample, -32768 << SH, 32767 << SH); + outbuf[sample_count] = (short)(sample >> SH); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_history2_32=hist2; +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/Makefile.unix.am b/Frameworks/vgmstream/vgmstream/src/layout/Makefile.unix.am new file mode 100644 index 000000000..caa724d50 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/Makefile.unix.am @@ -0,0 +1,41 @@ +noinst_LTLIBRARIES = liblayout.la + +AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir) +AM_MAKEFLAGS=-f Makefile.unix + +liblayout_la_LDFLAGS = +liblayout_la_SOURCES = +liblayout_la_SOURCES += ast_blocked.c +liblayout_la_SOURCES += blocked.c +liblayout_la_SOURCES += caf_blocked.c +liblayout_la_SOURCES += ea_block.c +liblayout_la_SOURCES += halpst_blocked.c +liblayout_la_SOURCES += interleave.c +liblayout_la_SOURCES += nolayout.c +liblayout_la_SOURCES += xa_blocked.c +liblayout_la_SOURCES += wsi_blocked.c +liblayout_la_SOURCES += str_snds_blocked.c +liblayout_la_SOURCES += ws_aud_blocked.c +liblayout_la_SOURCES += interleave_byte.c +liblayout_la_SOURCES += mus_acm_layout.c +liblayout_la_SOURCES += aix_layout.c +liblayout_la_SOURCES += ims_block.c +liblayout_la_SOURCES += de2_blocked.c +liblayout_la_SOURCES += xvas_block.c +liblayout_la_SOURCES += vs_blocked.c +liblayout_la_SOURCES += emff_blocked.c +liblayout_la_SOURCES += thp_blocked.c +liblayout_la_SOURCES += gsb_blocked.c +liblayout_la_SOURCES += filp_blocked.c +liblayout_la_SOURCES += aax_layout.c +liblayout_la_SOURCES += ivaud_layout.c +liblayout_la_SOURCES += mxch_blocked.c +liblayout_la_SOURCES += psx_mgav_blocked.c +liblayout_la_SOURCES += ps2_adm_blocked.c +liblayout_la_SOURCES += bdsp_blocked.c +liblayout_la_SOURCES += tra_blocked.c +liblayout_la_SOURCES += ps2_iab_blocked.c +liblayout_la_SOURCES += ps2_strlr_blocked.c +liblayout_la_SOURCES += scd_int_layout.c + +EXTRA_DIST = layout.h diff --git a/Frameworks/vgmstream/vgmstream/src/layout/aax_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/aax_layout.c new file mode 100644 index 000000000..2e0834ae9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/aax_layout.c @@ -0,0 +1,67 @@ +#include "layout.h" +#include "../vgmstream.h" +#include "../coding/coding.h" + +void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + aax_codec_data *data = vgmstream->codec_data; + + while (samples_writtensample_counts[data->current_segment]; + + if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + int i; + data->current_segment = data->loop_segment; + + reset_vgmstream(data->adxs[data->current_segment]); + + /* carry over the history from the loop point */ + if (data->loop_segment > 0) + { + for (i=0;iadxs[0]->channels;i++) + { + data->adxs[data->loop_segment]->ch[i].adpcm_history1_32 = + data->adxs[data->loop_segment-1]->ch[i].adpcm_history1_32; + data->adxs[data->loop_segment]->ch[i].adpcm_history2_32 = + data->adxs[data->loop_segment-1]->ch[i].adpcm_history2_32; + } + } + vgmstream->samples_into_block = 0; + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream); + + /*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/ + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + if (samples_to_do == 0) + { + int i; + data->current_segment++; + /*printf("advance to %d at %d samples\n",data->current_segment,vgmstream->current_sample);*/ + reset_vgmstream(data->adxs[data->current_segment]); + + /* carry over the history from the previous segment */ + for (i=0;iadxs[0]->channels;i++) + { + data->adxs[data->current_segment]->ch[i].adpcm_history1_32 = + data->adxs[data->current_segment-1]->ch[i].adpcm_history1_32; + data->adxs[data->current_segment]->ch[i].adpcm_history2_32 = + data->adxs[data->current_segment-1]->ch[i].adpcm_history2_32; + } + vgmstream->samples_into_block = 0; + continue; + } + + render_vgmstream(&buffer[samples_written*data->adxs[data->current_segment]->channels], + samples_to_do,data->adxs[data->current_segment]); + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/aix_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/aix_layout.c new file mode 100644 index 000000000..2e8a7b831 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/aix_layout.c @@ -0,0 +1,92 @@ +#include "layout.h" +#include "../vgmstream.h" +#include "../coding/coding.h" + +void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + aix_codec_data *data = vgmstream->codec_data; + + while (samples_writtensample_counts[data->current_segment]; + int current_stream; + int channels_sofar = 0; + + if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + data->current_segment = 1; + for (current_stream = 0; current_stream < data->stream_count; current_stream++) + { + int i; + reset_vgmstream(data->adxs[data->current_segment*data->stream_count+current_stream]); + + /* carry over the history from the loop point */ + for (i=0;iadxs[data->stream_count+current_stream]->channels;i++) + { + data->adxs[1*data->stream_count+current_stream]->ch[i].adpcm_history1_32 = + data->adxs[0+current_stream]->ch[i].adpcm_history1_32; + data->adxs[1*data->stream_count+current_stream]->ch[i].adpcm_history2_32 = + data->adxs[0+current_stream]->ch[i].adpcm_history2_32; + } + } + vgmstream->samples_into_block = 0; + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream); + + /*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/ + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + if (samples_to_do == 0) + { + int i; + data->current_segment++; + /*printf("next %d, %d samples\n",data->current_file,data->files[data->current_file]->total_values/data->files[data->current_file]->info.channels);*/ + for (current_stream = 0; current_stream < data->stream_count; current_stream++) + { + reset_vgmstream(data->adxs[data->current_segment*data->stream_count+current_stream]); + + /* carry over the history from the previous segment */ + for (i=0;iadxs[data->current_segment*data->stream_count+current_stream]->channels;i++) + { + data->adxs[data->current_segment*data->stream_count+current_stream]->ch[i].adpcm_history1_32 = + data->adxs[(data->current_segment-1)*data->stream_count+current_stream]->ch[i].adpcm_history1_32; + data->adxs[data->current_segment*data->stream_count+current_stream]->ch[i].adpcm_history2_32 = + data->adxs[(data->current_segment-1)*data->stream_count+current_stream]->ch[i].adpcm_history2_32; + } + } + vgmstream->samples_into_block = 0; + continue; + } + + /*printf("decode %d samples file %d\n",samples_to_do,data->current_file);*/ + if (samples_to_do > AIX_BUFFER_SIZE/2) + { + samples_to_do = AIX_BUFFER_SIZE/2; + } + + for (current_stream = 0; current_stream < data->stream_count; current_stream++) + { + int i,j; + VGMSTREAM *adx = data->adxs[data->current_segment*data->stream_count+current_stream]; + + render_vgmstream(data->buffer,samples_to_do,adx); + + for (i = 0; i < samples_to_do; i++) + { + for (j = 0; j < adx->channels; j++) + { + buffer[(i+samples_written)*vgmstream->channels+channels_sofar+j] = data->buffer[i*adx->channels+j]; + } + } + + channels_sofar += adx->channels; + } + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ast_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/ast_blocked.c new file mode 100644 index 000000000..d882a0de1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ast_blocked.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ast_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitBE( + vgmstream->current_block_offset+4, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + + vgmstream->current_block_size*vgmstream->channels + 0x20; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + + 0x20 + vgmstream->current_block_size*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/bdsp_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/bdsp_blocked.c new file mode 100644 index 000000000..88f640b66 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/bdsp_blocked.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitBE(vgmstream->current_block_offset,vgmstream->ch[0].streamfile)/7*8; + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0xC0; + + for (i=0;ichannels;i++) { + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=vgmstream->current_block_offset*i; + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c new file mode 100644 index 000000000..9b9e4b7a3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/blocked.c @@ -0,0 +1,150 @@ +#include "layout.h" +#include "../vgmstream.h" + +void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + + int frame_size = get_vgmstream_frame_size(vgmstream); + int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + int samples_this_block; + + if (frame_size == 0) { + /* assume 4 bit */ + /* TODO: get_vgmstream_frame_size() really should return bits... */ + samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; + } else { + samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; + } + + while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { + if (frame_size == 0) { + samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; + } else { + samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; + } + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + if (vgmstream->current_block_offset>=0) + decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); + else { + int i; + /* we've run off the end! */ + for (i=samples_written*vgmstream->channels; + i<(samples_written+samples_to_do)*vgmstream->channels;i++) + buffer[i]=0; + } + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + + if (vgmstream->samples_into_block==samples_this_block) { + switch (vgmstream->layout_type) { + case layout_ast_blocked: + ast_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_mxch_blocked: + mxch_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_halpst_blocked: + if (vgmstream->next_block_offset>=0) + halpst_block_update(vgmstream->next_block_offset,vgmstream); + else + vgmstream->current_block_offset=-1; + break; + case layout_xa_blocked: + xa_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ea_blocked: + ea_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_eacs_blocked: + eacs_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_caf_blocked: + caf_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_wsi_blocked: + wsi_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_str_snds_blocked: + str_snds_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ws_aud_blocked: + ws_aud_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_matx_blocked: + matx_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_de2_blocked: + de2_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_emff_ps2_blocked: + emff_ps2_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_emff_ngc_blocked: + emff_ngc_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_gsb_blocked: + gsb_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_vs_blocked: + vs_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_xvas_blocked: + xvas_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_thp_blocked: + thp_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_filp_blocked: + filp_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ivaud_blocked: + ivaud_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_psx_mgav_blocked: + psx_mgav_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ps2_adm_blocked: + ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_dsp_bdsp_blocked: + dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_tra_blocked: + tra_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ps2_iab_blocked: + ps2_iab_block_update(vgmstream->next_block_offset,vgmstream); + break; + case layout_ps2_strlr_blocked: + ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream); + break; + default: + break; + } + + /* for VBR these may change */ + frame_size = get_vgmstream_frame_size(vgmstream); + samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + + if (frame_size == 0) { + samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; + } else { + samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; + } + vgmstream->samples_into_block=0; + } + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/caf_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/caf_blocked.c new file mode 100644 index 000000000..d944baa01 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/caf_blocked.c @@ -0,0 +1,26 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitBE( + vgmstream->current_block_offset+0x14, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + + (off_t)read_32bitBE(vgmstream->current_block_offset+0x04, + vgmstream->ch[0].streamfile); + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + + read_32bitBE(block_offset+0x10+(8*i),vgmstream->ch[0].streamfile); + } + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(block_offset+0x34+(2*i),vgmstream->ch[0].streamfile); + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(block_offset+0x60+(2*i),vgmstream->ch[0].streamfile); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c new file mode 100644 index 000000000..a89ddbafa --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/de2_blocked.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = block_offset+8+read_32bitLE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile); + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + 8; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ea_block.c b/Frameworks/vgmstream/vgmstream/src/layout/ea_block.c new file mode 100644 index 000000000..800192a18 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ea_block.c @@ -0,0 +1,149 @@ +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + init_get_high_nibble(vgmstream); + + // Search for next SCDL or SCEl block ... + do { + block_offset+=4; + if(block_offset>=(off_t)get_streamfile_size(vgmstream->ch[0].streamfile)) { + vgmstream->next_block_offset=block_offset; + return; + } + } while (read_32bitBE(block_offset,vgmstream->ch[0].streamfile)!=0x5343446C); + + // reset channel offset + for(i=0;ichannels;i++) { + vgmstream->ch[i].channel_start_offset=0; + } + + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset+read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-4; + + if(vgmstream->ea_big_endian) { + vgmstream->current_block_size = read_32bitBE(block_offset+8,vgmstream->ch[0].streamfile); + + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=read_32bitBE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels); + vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C; + } + vgmstream->current_block_size /= 28; + + } else { + switch(vgmstream->coding_type) { + case coding_PSX: + vgmstream->ch[0].offset=vgmstream->current_block_offset+0x10; + vgmstream->ch[1].offset=(read_32bitLE(block_offset+0x04,vgmstream->ch[0].streamfile)-0x10)/vgmstream->channels; + vgmstream->ch[1].offset+=vgmstream->ch[0].offset; + vgmstream->current_block_size=read_32bitLE(block_offset+0x04,vgmstream->ch[0].streamfile)-0x10; + vgmstream->current_block_size/=vgmstream->channels; + break; + case coding_EA_ADPCM: + vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile); + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=vgmstream->current_block_offset+0x0C+(4*vgmstream->channels); + vgmstream->ch[i].adpcm_history1_32=(uint32_t)read_16bitLE(vgmstream->current_block_offset+0x0c+(i*4),vgmstream->ch[0].streamfile); + vgmstream->ch[i].adpcm_history2_32=(uint32_t)read_16bitLE(vgmstream->current_block_offset+0x0e +(i*4),vgmstream->ch[0].streamfile); + } + break; + case coding_PCM16BE: + vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-0x14; + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=block_offset+0x14+vgmstream->current_block_size/vgmstream->channels*i; + } + vgmstream->current_block_size/=vgmstream->channels; + break; + case coding_PCM16LE_int: + vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-0x0C; + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=block_offset+0x0C+(i*2); + } + vgmstream->current_block_size/=2; + vgmstream->current_block_size-=2; + break; + case coding_XBOX: + vgmstream->current_block_size = read_32bitLE(block_offset+0x10,vgmstream->ch[0].streamfile); + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=read_32bitLE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels); + vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C; + } + break; + default: + vgmstream->current_block_size = read_32bitLE(block_offset+8,vgmstream->ch[0].streamfile); + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset=read_32bitLE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels); + vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C; + } + vgmstream->current_block_size /= 28; + } + } + + if((vgmstream->ea_compression_version<3) && (vgmstream->coding_type!=coding_PSX) && (vgmstream->coding_type!=coding_EA_ADPCM) && (vgmstream->coding_type!=coding_XBOX) && (vgmstream->coding_type!=coding_PCM16BE)) { + for(i=0;ichannels;i++) { + if(vgmstream->ea_big_endian) { + vgmstream->ch[i].adpcm_history1_32=read_16bitBE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile); + vgmstream->ch[i].adpcm_history2_32=read_16bitBE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile); + } else { + vgmstream->ch[i].adpcm_history1_32=read_16bitLE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile); + vgmstream->ch[i].adpcm_history2_32=read_16bitLE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile); + } + vgmstream->ch[i].offset+=4; + } + } +} + +void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + off_t block_size=vgmstream->current_block_size; + + if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) { + block_offset+=0x0C; + } + + vgmstream->current_block_offset = block_offset; + + if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E64) { /* 1Snd */ + block_offset+=4; + if(vgmstream->ea_platform==0) + block_size=read_32bitLE(vgmstream->current_block_offset+0x04, + vgmstream->ch[0].streamfile); + else + block_size=read_32bitBE(vgmstream->current_block_offset+0x04, + vgmstream->ch[0].streamfile); + block_offset+=4; + } + + vgmstream->current_block_size=block_size-8; + + if(vgmstream->coding_type==coding_EACS_IMA) { + init_get_high_nibble(vgmstream); + vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile); + + for(i=0;ichannels;i++) { + vgmstream->ch[i].adpcm_step_index = read_32bitLE(block_offset+0x04+i*4,vgmstream->ch[0].streamfile); + vgmstream->ch[i].adpcm_history1_32 = read_32bitLE(block_offset+0x04+i*4+(4*vgmstream->channels),vgmstream->ch[0].streamfile); + vgmstream->ch[i].offset = block_offset+0x14; + } + } else { + if(vgmstream->coding_type==coding_PSX) { + for (i=0;ichannels;i++) + vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2)); + } else { + + for (i=0;ichannels;i++) { + if(vgmstream->coding_type==coding_PCM16LE_int) + vgmstream->ch[i].offset = block_offset+(i*2); + else + vgmstream->ch[i].offset = block_offset+i; + } + } + vgmstream->current_block_size/=vgmstream->channels; + } + vgmstream->next_block_offset = vgmstream->current_block_offset + + (off_t)block_size; +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/emff_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/emff_blocked.c new file mode 100644 index 000000000..b3ed7f5f2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/emff_blocked.c @@ -0,0 +1,34 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void emff_ps2_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset+0x10, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i); + } +} + +void emff_ngc_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitBE( + vgmstream->current_block_offset+0x20, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x40; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x40+(vgmstream->current_block_size*i); + } +} + diff --git a/Frameworks/vgmstream/vgmstream/src/layout/filp_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/filp_blocked.c new file mode 100644 index 000000000..550c6e738 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/filp_blocked.c @@ -0,0 +1,19 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset+0x18, + vgmstream->ch[0].streamfile)-0x800; + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x800; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x800+(vgmstream->current_block_size*i); + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c new file mode 100644 index 000000000..80ce3eef1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/gsb_blocked.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void gsb_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = 0x10000; /*read_32bitLE( + vgmstream->current_block_offset+0x10, + vgmstream->ch[0].streamfile); */ + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/halpst_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/halpst_blocked.c new file mode 100644 index 000000000..affb135f7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/halpst_blocked.c @@ -0,0 +1,19 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void halpst_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitBE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile)/vgmstream->channels; + vgmstream->next_block_offset = read_32bitBE( + vgmstream->current_block_offset+8, + vgmstream->ch[0].streamfile); + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + + 0x20 + vgmstream->current_block_size*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ims_block.c b/Frameworks/vgmstream/vgmstream/src/layout/ims_block.c new file mode 100644 index 000000000..c5df59480 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ims_block.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void matx_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 8; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + 8; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/interleave.c b/Frameworks/vgmstream/vgmstream/src/layout/interleave.c new file mode 100644 index 000000000..f10ee574e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/interleave.c @@ -0,0 +1,65 @@ +#include "layout.h" +#include "../vgmstream.h" + +void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + + int frame_size = get_vgmstream_frame_size(vgmstream); + int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + int samples_this_block; + + samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame; + + if (vgmstream->layout_type == layout_interleave_shortblock && + vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block> vgmstream->num_samples) { + frame_size = get_vgmstream_shortframe_size(vgmstream); + samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream); + + samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame; + } + + while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { + /* we assume that the loop is not back into a short block */ + if (vgmstream->layout_type == layout_interleave_shortblock) { + frame_size = get_vgmstream_frame_size(vgmstream); + samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame; + } + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + /*printf("vgmstream_samples_to_do(samples_this_block=%d,samples_per_frame=%d,vgmstream) returns %d\n",samples_this_block,samples_per_frame,samples_to_do);*/ + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + + if (vgmstream->samples_into_block==samples_this_block) { + int chan; + if (vgmstream->layout_type == layout_interleave_shortblock && + vgmstream->current_sample + samples_this_block > vgmstream->num_samples) { + frame_size = get_vgmstream_shortframe_size(vgmstream); + samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream); + + samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame; + for (chan=0;chanchannels;chan++) + vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_smallblock_size*chan; + } else { + + for (chan=0;chanchannels;chan++) + vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*vgmstream->channels; + } + vgmstream->samples_into_block=0; + } + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c b/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c new file mode 100644 index 000000000..c9f8eb088 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/interleave_byte.c @@ -0,0 +1,62 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* for formats where the interleave is smaller than a frame, so we need to + * deinterleave in memory before passing it along to a specialized decoder which + * reads from memory + */ + +/* just do one frame at a time */ + +void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + /* frame sizes are much smaller than this */ + uint8_t sample_data[0x400]; + int samples_written=0; + + int frame_size = get_vgmstream_frame_size(vgmstream); + int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + int samples_this_block; + + samples_this_block = samples_per_frame; + + while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + { + int i,j; + for (j=0;jchannels;j++) { + for (i=0;ich[j].offset+ + i/vgmstream->interleave_block_size* + vgmstream->interleave_block_size* + vgmstream->channels+ + i%vgmstream->interleave_block_size, + vgmstream->ch[j].streamfile); + } + decode_vgmstream_mem(vgmstream, samples_written, + samples_to_do, buffer, sample_data, j); + } + } + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + + if (vgmstream->samples_into_block==samples_this_block) { + int chan; + for (chan=0;chanchannels;chan++) + vgmstream->ch[chan].offset+=frame_size*vgmstream->channels; + vgmstream->samples_into_block=0; + } + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c new file mode 100644 index 000000000..f5df3c7bf --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ivaud_layout.c @@ -0,0 +1,25 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + off_t start_offset; + off_t interleave_size; + int32_t nextFrame=0; + STREAMFILE *streamFile=vgmstream->ch[0].streamfile; + + vgmstream->current_block_offset = block_offset; + + nextFrame=(read_32bitLE(vgmstream->current_block_offset+0x28,streamFile)<<12)+0x800; + + vgmstream->next_block_offset = vgmstream->current_block_offset + nextFrame; + vgmstream->current_block_size=read_32bitLE(block_offset+0x24,streamFile)/2; + + start_offset=vgmstream->current_block_offset + 0x800; + interleave_size=(read_32bitLE(block_offset+0x28,streamFile)<<12)/2; + + for(i=0;ichannels;i++) { + vgmstream->ch[i].offset = start_offset + (i*interleave_size); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/layout.h b/Frameworks/vgmstream/vgmstream/src/layout/layout.h new file mode 100644 index 000000000..599e93538 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/layout.h @@ -0,0 +1,79 @@ +#ifndef _LAYOUT_H +#define _LAYOUT_H + +#include "../streamtypes.h" +#include "../vgmstream.h" + +void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream); + +void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream); + +void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream); + +void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void matx_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void emff_ps2_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void emff_ngc_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void gsb_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void xvas_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void mtaf_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +void ps2_mtaf_block_update(off_t block_ofset, VGMSTREAM * vgmstream); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/layout/mus_acm_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/mus_acm_layout.c new file mode 100644 index 000000000..bda82b501 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/mus_acm_layout.c @@ -0,0 +1,50 @@ +#include "layout.h" +#include "../vgmstream.h" +#include "../coding/acm_decoder.h" +#include "../coding/coding.h" + +void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + mus_acm_codec_data *data = vgmstream->codec_data; + + while (samples_writtenfiles[data->current_file]; + int samples_to_do; + int samples_this_block = acm->total_values / acm->info.channels; + + if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + data->current_file = data->loop_start_file; + acm_reset(data->files[data->current_file]); + vgmstream->samples_into_block = 0; + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream); + + /*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/ + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + if (samples_to_do == 0) + { + data->current_file++; + /*printf("next %d, %d samples\n",data->current_file,data->files[data->current_file]->total_values/data->files[data->current_file]->info.channels);*/ + /* force loop back to first file in case we're still playing for some + * reason, prevent out of bounds stuff */ + if (data->current_file >= data->file_count) data->current_file = 0; + acm_reset(data->files[data->current_file]); + vgmstream->samples_into_block = 0; + continue; + } + + /*printf("decode %d samples file %d\n",samples_to_do,data->current_file);*/ + decode_acm(acm, + buffer+samples_written*vgmstream->channels, + samples_to_do, vgmstream->channels); + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/mxch_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/mxch_blocked.c new file mode 100644 index 000000000..8e49a4a95 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/mxch_blocked.c @@ -0,0 +1,22 @@ +#include "layout.h" +#include "../vgmstream.h" + +//MxCh blocked layout as used by Lego Island +void mxch_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + + read_32bitLE(vgmstream->current_block_offset+4,vgmstream->ch[0].streamfile)+8; + /* skip pad blocks */ + while ( + read_32bitBE(vgmstream->current_block_offset, + vgmstream->ch[0].streamfile) == 0x70616420) + { + vgmstream->current_block_offset = vgmstream->next_block_offset; + vgmstream->next_block_offset = vgmstream->current_block_offset + + read_32bitLE(vgmstream->current_block_offset+4,vgmstream->ch[0].streamfile)+8; + } + vgmstream->current_block_size = + read_32bitLE(vgmstream->current_block_offset+4, vgmstream->ch[0].streamfile)-0xe; + // only one channel for now + vgmstream->ch[0].offset = vgmstream->current_block_offset+8+0xe; +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/nolayout.c b/Frameworks/vgmstream/vgmstream/src/layout/nolayout.c new file mode 100644 index 000000000..dd36976fb --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/nolayout.c @@ -0,0 +1,28 @@ +#include "layout.h" +#include "../vgmstream.h" + +void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + int samples_written=0; + + const int samples_this_block = vgmstream->num_samples; + int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + + while (samples_writtenloop_flag && vgmstream_do_loop(vgmstream)) { + continue; + } + + samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + + if (samples_written+samples_to_do > sample_count) + samples_to_do=sample_count-samples_written; + + decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); + + samples_written += samples_to_do; + vgmstream->current_sample += samples_to_do; + vgmstream->samples_into_block+=samples_to_do; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ps2_adm_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/ps2_adm_blocked.c new file mode 100644 index 000000000..87c7c606e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ps2_adm_blocked.c @@ -0,0 +1,18 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = 0x1000; /*read_32bitLE( + vgmstream->current_block_offset+0x10, + vgmstream->ch[0].streamfile); */ + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size; + //vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+(0x400*i); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ps2_iab_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/ps2_iab_blocked.c new file mode 100644 index 000000000..0b375b1ea --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ps2_iab_blocked.c @@ -0,0 +1,17 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x08,vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x10; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x10+(vgmstream->current_block_size*i); + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ps2_strlr_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/ps2_strlr_blocked.c new file mode 100644 index 000000000..7bf23bda5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ps2_strlr_blocked.c @@ -0,0 +1,19 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset+0x4, + vgmstream->ch[0].streamfile)*2; + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x40; + //vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(0x800*i); + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c new file mode 100644 index 000000000..e2a3d21a6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/psx_mgav_blocked.c @@ -0,0 +1,17 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x04,vgmstream->ch[0].streamfile)-0x1C; + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i); + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/scd_int_layout.c b/Frameworks/vgmstream/vgmstream/src/layout/scd_int_layout.c new file mode 100644 index 000000000..1a2c5e8a9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/scd_int_layout.c @@ -0,0 +1,38 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* TODO: currently only properly handles mono substreams */ +/* TODO: there must be a reasonable way to respect the loop settings, as is + the substreams are in their own little world */ + +#define INTERLEAVE_BUF_SIZE 512 +void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + sample interleave_buf[INTERLEAVE_BUF_SIZE]; + int32_t samples_done = 0; + scd_int_codec_data *data = vgmstream->codec_data; + + while (samples_done < sample_count) + { + int32_t samples_to_do = INTERLEAVE_BUF_SIZE; + int c; + if (samples_to_do > sample_count - samples_done) + samples_to_do = sample_count - samples_done; + + for (c=0; c < data->substream_count; c++) + { + int32_t i; + + render_vgmstream(interleave_buf, + samples_to_do, data->substreams[c]); + + for (i=0; i < samples_to_do; i++) + { + buffer[(samples_done+i)*data->substream_count + c] = interleave_buf[i]; + } + } + + samples_done += samples_to_do; + + } +} + diff --git a/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c new file mode 100644 index 000000000..e18f1510e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/str_snds_blocked.c @@ -0,0 +1,54 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + off_t current_chunk; + size_t file_size; + int i; + STREAMFILE *streamfile; + int FoundSSMP = 0; + off_t SSMP_offset = -1; + + current_chunk = block_offset; + streamfile = vgmstream->ch[0].streamfile; + file_size = get_streamfile_size(streamfile); + + /* we may have to skip some chunks */ + while (!FoundSSMP && current_chunk < file_size) { + if (current_chunk+read_32bitBE(current_chunk+4,streamfile)>=file_size) + break; + switch (read_32bitBE(current_chunk,streamfile)) { + case 0x534e4453: /* SNDS */ + /* SSMP */ + if (read_32bitBE(current_chunk+0x10,streamfile)==0x53534d50) { + FoundSSMP = 1; + SSMP_offset = current_chunk; + } + break; + case 0x46494c4c: /* FILL, the main culprit */ + default: + break; + } + + current_chunk += read_32bitBE(current_chunk+4,streamfile); + } + + if (!FoundSSMP) { + /* if we couldn't find it all we can do is try playing the current + * block, which is going to suck */ + vgmstream->current_block_offset = block_offset; + } + + vgmstream->current_block_offset = SSMP_offset; + vgmstream->current_block_size = (read_32bitBE( + vgmstream->current_block_offset+4, + vgmstream->ch[0].streamfile) - 0x18) / vgmstream->channels; + vgmstream->next_block_offset = vgmstream->current_block_offset + + read_32bitBE(vgmstream->current_block_offset+4, + vgmstream->ch[0].streamfile); + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c new file mode 100644 index 000000000..f4ed39e87 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/thp_blocked.c @@ -0,0 +1,31 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i,j; + STREAMFILE *streamFile=vgmstream->ch[0].streamfile; + off_t start_offset; + int32_t nextFrameSize; + + vgmstream->current_block_offset = block_offset; + nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile); + + vgmstream->next_block_offset = vgmstream->current_block_offset + + vgmstream->thpNextFrameSize; + vgmstream->thpNextFrameSize=nextFrameSize; + + start_offset=vgmstream->current_block_offset + + read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10; + vgmstream->current_block_size=read_32bitBE(start_offset,streamFile); + start_offset+=8; + + for(i=0;ichannels;i++) { + for(j=0;j<16;j++) { + vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(start_offset+(i*0x20)+(j*2),streamFile); + } + vgmstream->ch[i].adpcm_history1_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4),streamFile); + vgmstream->ch[i].adpcm_history2_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4) + 2,streamFile); + vgmstream->ch[i].offset = start_offset + (0x24*vgmstream->channels)+(i*vgmstream->current_block_size); + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/tra_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/tra_blocked.c new file mode 100644 index 000000000..cc235f723 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/tra_blocked.c @@ -0,0 +1,17 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset (first 32bytes is useless for decoding) */ +void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = 0x400; + vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+8; + vgmstream->current_block_size/=vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset+(vgmstream->current_block_size*i)+0x4*(i+1); + + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/vs_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/vs_blocked.c new file mode 100644 index 000000000..76e4cb277 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/vs_blocked.c @@ -0,0 +1,17 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + for (i=0;ichannels;i++) { + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_32bitLE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 0x4; + vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x4; + if(i==0) block_offset=vgmstream->next_block_offset; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/ws_aud_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/ws_aud_blocked.c new file mode 100644 index 000000000..dfc824a57 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/ws_aud_blocked.c @@ -0,0 +1,24 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + vgmstream->current_block_offset = block_offset; + vgmstream->current_block_size = read_16bitLE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile); + vgmstream->next_block_offset = vgmstream->current_block_offset + + vgmstream->current_block_size + 8; + + if (vgmstream->coding_type == coding_WS) { + vgmstream->ws_output_size = read_16bitLE( + vgmstream->current_block_offset+2, + vgmstream->ch[0].streamfile); + } + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + + 8 + vgmstream->current_block_size*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/wsi_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/wsi_blocked.c new file mode 100644 index 000000000..6dcd79a52 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/wsi_blocked.c @@ -0,0 +1,23 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + /* assume that all channels have the same size for this block */ + + vgmstream->current_block_offset = block_offset; + /* current_block_size is the data size in this block, so subtract header */ + vgmstream->current_block_size = read_32bitBE( + vgmstream->current_block_offset, + vgmstream->ch[0].streamfile) - 0x10; + vgmstream->next_block_offset = + vgmstream->current_block_offset + + (vgmstream->current_block_size + 0x10) * vgmstream->channels; + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset + + 0x10 + (vgmstream->current_block_size+0x10)*i; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c b/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c new file mode 100644 index 000000000..e84cb15b4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/xa_blocked.c @@ -0,0 +1,51 @@ +#include "layout.h" +#include "../coding/coding.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + + int i; + int8_t currentChannel=0; + int8_t subAudio=0; + + init_get_high_nibble(vgmstream); + + if(vgmstream->samples_into_block!=0) + // don't change this variable in the init process + vgmstream->xa_sector_length+=128; + + // We get to the end of a sector ? + if(vgmstream->xa_sector_length==(18*128)) { + vgmstream->xa_sector_length=0; + + // 0x30 of unused bytes/sector :( + if (!vgmstream->xa_headerless) { + block_offset+=0x30; +begin: + // Search for selected channel & valid audio + currentChannel=read_8bit(block_offset-7,vgmstream->ch[0].streamfile); + subAudio=read_8bit(block_offset-6,vgmstream->ch[0].streamfile); + + // audio is coded as 0x64 + if(!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) { + // go to next sector + block_offset+=2352; + if(currentChannel!=-1) goto begin; + } + } + } + + vgmstream->current_block_offset = block_offset; + + // Quid : how to stop the current channel ??? + // i set up 0 to current_block_size to make vgmstream not playing bad samples + // another way to do it ??? + // (as the number of samples can be false in cd-xa due to multi-channels) + vgmstream->current_block_size = (currentChannel==-1?0:112); + + vgmstream->next_block_offset = vgmstream->current_block_offset+128; + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset; + } +} diff --git a/Frameworks/vgmstream/vgmstream/src/layout/xvas_block.c b/Frameworks/vgmstream/vgmstream/src/layout/xvas_block.c new file mode 100644 index 000000000..ee78c3ad1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/layout/xvas_block.c @@ -0,0 +1,24 @@ +#include "layout.h" +#include "../vgmstream.h" + +/* set up for the block at the given offset */ +void xvas_block_update(off_t block_offset, VGMSTREAM * vgmstream) { + int i; + + vgmstream->current_block_offset = block_offset; + + if((vgmstream->current_block_offset-get_streamfile_size(vgmstream->ch[0].streamfile))>(0x20000-0x20)) + vgmstream->current_block_size = 0x20000-0x20; + else + vgmstream->current_block_size = vgmstream->current_block_offset-get_streamfile_size(vgmstream->ch[0].streamfile)-0x20; + + vgmstream->next_block_offset = + vgmstream->current_block_offset + + (vgmstream->current_block_size + 0x20); + + for (i=0;ichannels;i++) { + vgmstream->ch[i].offset = vgmstream->current_block_offset; + } + vgmstream->current_block_size /=2; + +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/2dx9.c b/Frameworks/vgmstream/vgmstream/src/meta/2dx9.c new file mode 100644 index 000000000..14912d71a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/2dx9.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* 2DX9 (found in beatmaniaIIDX16 - EMPRESS (Arcade) */ +VGMSTREAM * init_vgmstream_2dx9(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("2dx9",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x32445839) /* 2DX9 */ + goto fail; + if (read_32bitBE(0x18,streamFile) != 0x52494646) /* RIFF */ + goto fail; + if (read_32bitBE(0x20,streamFile) != 0x57415645) /* WAVE */ + goto fail; + if (read_32bitBE(0x24,streamFile) != 0x666D7420) /* fmt */ + goto fail; + if (read_32bitBE(0x6a,streamFile) != 0x64617461) /* data */ + goto fail; + + loop_flag = 0; + channel_count = read_16bitLE(0x2e,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x72; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x30,streamFile); + vgmstream->coding_type = coding_MSADPCM; + vgmstream->num_samples = read_32bitLE(0x66,streamFile); + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = read_16bitLE(0x38,streamFile); + vgmstream->meta_type = meta_2DX9; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c new file mode 100644 index 000000000..917f2a9df --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/Cstr.c @@ -0,0 +1,303 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* .dsp w/ Cstr header, seen in Star Fox Assault and Donkey Konga */ + +VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag; + off_t start_offset; + off_t first_data; + off_t loop_offset; + size_t interleave; + int loop_adjust; + int double_loop_end = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x43737472) /* "Cstr" */ + goto fail; +#ifdef DEBUG + fprintf(stderr,"header ok\n"); +#endif + + if (read_8bit(0x1b,streamFile)==1) { + /* mono version, much simpler to handle */ + /* Only seen in R Racing Evolution radio sfx */ + + start_offset = 0x80; + loop_flag = read_16bitBE(0x2c,streamFile); + + /* check initial predictor/scale */ + if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile)) + goto fail; + + loop_offset = start_offset+read_32bitBE(0x10,streamFile); + if (loop_flag) { + if (read_16bitBE(0x64,streamFile) != (uint8_t)read_8bit(loop_offset,streamFile)) goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(1,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->sample_rate = read_32bitBE(0x28,streamFile); + vgmstream->num_samples = read_32bitBE(0x20,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + read_32bitBE(0x30,streamFile)); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + read_32bitBE(0x34,streamFile))+1; + } + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_CSTR; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile); + } + + /* open the file for reading by each channel */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset= + start_offset; + + return vgmstream; + } /* end mono */ + + interleave = read_16bitBE(0x06,streamFile); + start_offset = 0xe0; + first_data = start_offset+read_32bitBE(0x0c,streamFile); + loop_flag = read_16bitBE(0x2c,streamFile); + + if (!loop_flag) { + /* Nonlooped tracks seem to follow no discernable pattern + * with where they actually start. + * But! with the magic of initial p/s redundancy, we can guess. + */ + while (first_data=-0x10;loop_adjust-=8) { +#ifdef DEBUG + fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust); +#endif + if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) && + read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) { + loops_ok=1; + break; + } + } + if (!loops_ok) + for (loop_adjust=interleave;loop_adjust<=interleave+0x10;loop_adjust+=8) { +#ifdef DEBUG + fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust); +#endif + if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) && + read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) { + loops_ok=1; + break; + } + } + + if (!loops_ok) goto fail; +#ifdef DEBUG + fprintf(stderr,"loop p/s ok (with %#4x adjust)\n",loop_adjust); +#endif + + /* check for agreement */ + /* loop end (channel 1 & 2 headers) */ + if (read_32bitBE(0x34,streamFile) != read_32bitBE(0x94,streamFile)) + goto fail; + + /* Mr. Driller oddity */ + if (dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1 <= read_32bitBE(0x20,streamFile)) { +#ifdef DEBUG + fprintf(stderr,"loop end <= half total samples, should be doubled\n"); +#endif + double_loop_end = 1; + } + + /* loop start (Cstr header and channel 1 header) */ + if (read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile) +#if 0 + /* this particular glitch only true for SFA, though it + * seems like something similar happens in Donkey Konga */ + /* loop start (Cstr, channel 1 & 2 headers) */ + || (read_32bitBE(0x0c,streamFile)+read_32bitLE(0x30,streamFile)) != + read_32bitBE(0x90,streamFile) +#endif + ) + /* alternatively (Donkey Konga) the header loop is 0x0c+0x10 */ + if ( + /* loop start (Cstr header and channel 1 header) */ + read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile)+ + read_32bitBE(0x0c,streamFile)) + /* further alternatively (Donkey Konga), if we loop back to + * the very first frame 0x30 might be 0x00000002 (which + * is a *valid* std dsp loop start, imagine that) while 0x10 + * is 0x00000000 */ + if (!(read_32bitBE(0x30,streamFile) == 2 && + read_32bitBE(0x10,streamFile) == 0)) + /* lest there be too few alternatives, in Mr. Driller we + * find that [0x30] + [0x0c] + 8 = [0x10]*2 */ + if (!(double_loop_end && + read_32bitBE(0x30,streamFile) + + read_32bitBE(0x0c,streamFile) + 8 == + read_32bitBE(0x10,streamFile)*2)) + goto fail; + +#ifdef DEBUG + fprintf(stderr,"loop points agree\n"); +#endif + } + + /* assure that sample counts, sample rates agree */ + if ( + /* sample count (channel 1 & 2 headers) */ + read_32bitBE(0x20,streamFile) != read_32bitBE(0x80,streamFile) || + /* sample rate (channel 1 & 2 headers) */ + read_32bitBE(0x28,streamFile) != read_32bitBE(0x88,streamFile) || + /* sample count (Cstr header and channel 1 header) */ + read_32bitLE(0x14,streamFile) != read_32bitBE(0x20,streamFile) || + /* sample rate (Cstr header and channel 1 header) */ + (uint16_t)read_16bitLE(0x18,streamFile) != read_32bitBE(0x28,streamFile)) + goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->sample_rate = read_32bitBE(0x28,streamFile); + /* This is a slight hack to counteract their hack. + * All the data is ofset by first_data so that the loop + * point occurs at a block boundary. However, I always begin decoding + * right after the header, as that is the start of the first block and + * my interleave code relies on starting at the beginning of a block. + * So we decode a few silent samples at the beginning, and here we make up + * for it by lengthening the track by that much. + */ + vgmstream->num_samples = read_32bitBE(0x20,streamFile) + + (first_data-start_offset)/8*14; + + if (loop_flag) { + off_t loop_start_bytes = loop_offset-start_offset-interleave; + vgmstream->loop_start_sample = dsp_nibbles_to_samples((loop_start_bytes/(2*interleave)*interleave+loop_start_bytes%(interleave*2))*2); + /*dsp_nibbles_to_samples(loop_start_bytes);*/ + /*dsp_nibbles_to_samples(read_32bitBE(0x30,streamFile)*2-inter);*/ + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + read_32bitBE(0x34,streamFile))+1; + + if (double_loop_end) + vgmstream->loop_end_sample = + dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1; + + if (vgmstream->loop_end_sample > vgmstream->num_samples) { +#ifdef DEBUG + fprintf(stderr,"loop_end_sample > num_samples, adjusting\n"); +#endif + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_CSTR; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile); + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x9c+i*2,streamFile); + } +#ifdef DEBUG + vgmstream->ch[0].loop_history1 = read_16bitBE(0x66,streamFile); + vgmstream->ch[0].loop_history2 = read_16bitBE(0x68,streamFile); + vgmstream->ch[1].loop_history1 = read_16bitBE(0xc6,streamFile); + vgmstream->ch[1].loop_history2 = read_16bitBE(0xc8,streamFile); +#endif + + /* open the file for reading by each channel */ + { + int i; + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,interleave); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset+interleave*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/Makefile.unix.am b/Frameworks/vgmstream/vgmstream/src/meta/Makefile.unix.am new file mode 100644 index 000000000..91ae2ea4f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/Makefile.unix.am @@ -0,0 +1,241 @@ +noinst_LTLIBRARIES = libmeta.la + +AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir) +AM_MAKEFLAGS=-f Makefile.unix + +libmeta_la_LDFLAGS = +libmeta_la_SOURCES = +libmeta_la_SOURCES += Cstr.c +libmeta_la_SOURCES += adx_header.c +libmeta_la_SOURCES += afc_header.c +libmeta_la_SOURCES += agsc.c +libmeta_la_SOURCES += ast.c +libmeta_la_SOURCES += brstm.c +libmeta_la_SOURCES += ea_header.c +libmeta_la_SOURCES += gcsw.c halpst.c +libmeta_la_SOURCES += nds_strm.c +libmeta_la_SOURCES += ngc_adpdtk.c +libmeta_la_SOURCES += ngc_caf.c +libmeta_la_SOURCES += ngc_dsp_std.c +libmeta_la_SOURCES += ps2_ads.c +libmeta_la_SOURCES += ps2_exst.c +libmeta_la_SOURCES += ps2_ild.c +libmeta_la_SOURCES += ps2_int.c +libmeta_la_SOURCES += ps2_mib.c +libmeta_la_SOURCES += ps2_mic.c +libmeta_la_SOURCES += ps2_npsf.c +libmeta_la_SOURCES += ps2_pnb.c +libmeta_la_SOURCES += ps2_rxw.c +libmeta_la_SOURCES += ps2_str.c +libmeta_la_SOURCES += ps2_svag.c +libmeta_la_SOURCES += ps2_vag.c +libmeta_la_SOURCES += ps2_vpk.c +libmeta_la_SOURCES += psx_cdxa.c +libmeta_la_SOURCES += raw.c +libmeta_la_SOURCES += rs03.c +libmeta_la_SOURCES += rsf.c +libmeta_la_SOURCES += rwsd.c +libmeta_la_SOURCES += psx_gms.c +libmeta_la_SOURCES += xbox_xwav.c +libmeta_la_SOURCES += xbox_wavm.c +libmeta_la_SOURCES += genh.c +libmeta_la_SOURCES += ogg_vorbis_file.c +libmeta_la_SOURCES += ps2_bmdx.c +libmeta_la_SOURCES += aifc.c +libmeta_la_SOURCES += str_snds.c +libmeta_la_SOURCES += ws_aud.c +libmeta_la_SOURCES += ahx.c +libmeta_la_SOURCES += ivb.c +libmeta_la_SOURCES += svs.c +libmeta_la_SOURCES += riff.c +libmeta_la_SOURCES += pos.c +libmeta_la_SOURCES += nwa.c +libmeta_la_SOURCES += ps2_rws.c +libmeta_la_SOURCES += ps2_hgc1.c +libmeta_la_SOURCES += xss.c +libmeta_la_SOURCES += ps2_sl3.c +libmeta_la_SOURCES += ps2_aus.c +libmeta_la_SOURCES += fsb.c +libmeta_la_SOURCES += rsd.c +libmeta_la_SOURCES += rwx.c +libmeta_la_SOURCES += xwb.c +libmeta_la_SOURCES += ea_old.c +libmeta_la_SOURCES += ps2_xa30.c +libmeta_la_SOURCES += musc.c +libmeta_la_SOURCES += ps2_leg.c +libmeta_la_SOURCES += ps2_filp.c +libmeta_la_SOURCES += ps2_ikm.c +libmeta_la_SOURCES += musx.c +libmeta_la_SOURCES += ps2_sfs.c +libmeta_la_SOURCES += sat_dvi.c +libmeta_la_SOURCES += ps2_bg00.c +libmeta_la_SOURCES += dc_kcey.c +libmeta_la_SOURCES += ps2_rstm.c +libmeta_la_SOURCES += acm.c +libmeta_la_SOURCES += ps2_kces.c +libmeta_la_SOURCES += ps2_dxh.c +libmeta_la_SOURCES += ps2_psh.c +libmeta_la_SOURCES += mus_acm.c +libmeta_la_SOURCES += sli.c +libmeta_la_SOURCES += sfl.c +libmeta_la_SOURCES += pcm.c +libmeta_la_SOURCES += ps2_psw.c +libmeta_la_SOURCES += rkv.c +libmeta_la_SOURCES += ps2_vas.c +libmeta_la_SOURCES += ps2_tec.c +libmeta_la_SOURCES += ps2_enth.c +libmeta_la_SOURCES += sdt.c +libmeta_la_SOURCES += aix.c +libmeta_la_SOURCES += ngc_tydsp.c +libmeta_la_SOURCES += wvs.c +libmeta_la_SOURCES += xbox_stma.c +libmeta_la_SOURCES += xbox_ims.c +libmeta_la_SOURCES += de2.c +libmeta_la_SOURCES += dc_str.c +libmeta_la_SOURCES += xbox_xmu.c +libmeta_la_SOURCES += ngc_bh2pcm.c +libmeta_la_SOURCES += sat_sap.c +libmeta_la_SOURCES += dc_idvi.c +libmeta_la_SOURCES += ps2_rnd.c +libmeta_la_SOURCES += xbox_xvas.c +libmeta_la_SOURCES += kraw.c +libmeta_la_SOURCES += ps2_xa2.c +libmeta_la_SOURCES += idsp.c +libmeta_la_SOURCES += ngc_ymf.c +libmeta_la_SOURCES += nds_sad.c +libmeta_la_SOURCES += ps2_ccc.c +libmeta_la_SOURCES += psx_fag.c +libmeta_la_SOURCES += ps2_mihb.c +libmeta_la_SOURCES += ngc_pdt.c +libmeta_la_SOURCES += wii_mus.c +libmeta_la_SOURCES += dc_asd.c +libmeta_la_SOURCES += naomi_spsd.c +libmeta_la_SOURCES += bgw.c +libmeta_la_SOURCES += ps2_ass.c +libmeta_la_SOURCES += ngc_waa_wac_wad_wam.c +libmeta_la_SOURCES += seg.c +libmeta_la_SOURCES += str_asr.c +libmeta_la_SOURCES += zwdsp.c +libmeta_la_SOURCES += gca.c +libmeta_la_SOURCES += ish_isd.c +libmeta_la_SOURCES += spt_spd.c +libmeta_la_SOURCES += ydsp.c +libmeta_la_SOURCES += gsp_gsb.c +libmeta_la_SOURCES += ngc_ssm.c +libmeta_la_SOURCES += msvp.c +libmeta_la_SOURCES += ps2_joe.c +libmeta_la_SOURCES += vs.c +libmeta_la_SOURCES += vgs.c +libmeta_la_SOURCES += dc_dcsw_dcs.c +libmeta_la_SOURCES += wii_smp.c +libmeta_la_SOURCES += ss_stream.c +libmeta_la_SOURCES += emff.c +libmeta_la_SOURCES += thp.c +libmeta_la_SOURCES += wii_sts.c +libmeta_la_SOURCES += capdsp.c +libmeta_la_SOURCES += wii_sng.c +libmeta_la_SOURCES += aax.c +libmeta_la_SOURCES += ps2_p2bt.c +libmeta_la_SOURCES += ps2_gbts.c +libmeta_la_SOURCES += ngc_ffcc_str.c +libmeta_la_SOURCES += sat_baka.c +libmeta_la_SOURCES += nds_swav.c +libmeta_la_SOURCES += vsf.c +libmeta_la_SOURCES += nds_rrds.c +libmeta_la_SOURCES += ps2_tk5.c +libmeta_la_SOURCES += ads.c +libmeta_la_SOURCES += wii_str.c +libmeta_la_SOURCES += zsd.c +libmeta_la_SOURCES += ps2_mcg.c +libmeta_la_SOURCES += redspark.c +libmeta_la_SOURCES += ivaud.c +libmeta_la_SOURCES += ps2_vgs.c +libmeta_la_SOURCES += ps2_sps.c +libmeta_la_SOURCES += nds_hwas.c +libmeta_la_SOURCES += ngc_lps.c +libmeta_la_SOURCES += ps2_snd.c +libmeta_la_SOURCES += naomi_adpcm.c +libmeta_la_SOURCES += sd9.c +libmeta_la_SOURCES += 2dx9.c +libmeta_la_SOURCES += ngc_dsp_ygo.c +libmeta_la_SOURCES += ps2_vgv.c +libmeta_la_SOURCES += ngc_gcub.c +libmeta_la_SOURCES += maxis_xa.c +libmeta_la_SOURCES += ngc_sck_dsp.c +libmeta_la_SOURCES += apple_caff.c +libmeta_la_SOURCES += pc_mxst.c +libmeta_la_SOURCES += pc_sob.c +libmeta_la_SOURCES += exakt_sc.c +libmeta_la_SOURCES += wii_bns.c +libmeta_la_SOURCES += pona.c +libmeta_la_SOURCES += xbox_hlwav.c +libmeta_la_SOURCES += stx.c +libmeta_la_SOURCES += ps2_stm.c +libmeta_la_SOURCES += myspd.c +libmeta_la_SOURCES += his.c +libmeta_la_SOURCES += ps2_ast.c +libmeta_la_SOURCES += dmsg_segh.c +libmeta_la_SOURCES += ngc_dsp_konami.c +libmeta_la_SOURCES += ps2_ster.c +libmeta_la_SOURCES += bnsf.c +libmeta_la_SOURCES += ps2_wb.c +libmeta_la_SOURCES += s14_sss.c +libmeta_la_SOURCES += ps2_gcm.c +libmeta_la_SOURCES += ps2_smpl.c +libmeta_la_SOURCES += ps2_msa.c +libmeta_la_SOURCES += pc_smp.c +libmeta_la_SOURCES += p3d.c +libmeta_la_SOURCES += ps2_adsc.c +libmeta_la_SOURCES += psx_str_mgav.c +libmeta_la_SOURCES += ngc_bo2.c +libmeta_la_SOURCES += ngc_dsp_mpds.c +libmeta_la_SOURCES += ps2_khv.c +libmeta_la_SOURCES += ps2_voi.c +libmeta_la_SOURCES += dsp_sth_str.c +libmeta_la_SOURCES += ps2_b1s.c +libmeta_la_SOURCES += ps2_wad.c +libmeta_la_SOURCES += ps2_lpcm.c +libmeta_la_SOURCES += ps2_adm.c +libmeta_la_SOURCES += dsp_bdsp.c +libmeta_la_SOURCES += ps2_vms.c +libmeta_la_SOURCES += ps2_xau.c +libmeta_la_SOURCES += gh3_bar.c +libmeta_la_SOURCES += ffw.c +libmeta_la_SOURCES += ps2_jstm.c +libmeta_la_SOURCES += ps3_xvag.c +libmeta_la_SOURCES += ps3_cps.c +libmeta_la_SOURCES += sqex_scd.c +libmeta_la_SOURCES += ngc_nst_dsp.c +libmeta_la_SOURCES += baf.c +libmeta_la_SOURCES += ps3_msf.c +libmeta_la_SOURCES += nub.c +libmeta_la_SOURCES += ps3_past.c +libmeta_la_SOURCES += ps3_sgh_sgb.c +libmeta_la_SOURCES += ngca.c +libmeta_la_SOURCES += wii_ras.c +libmeta_la_SOURCES += ps2_spm.c +libmeta_la_SOURCES += x360_tra.c +libmeta_la_SOURCES += ps2_iab.c +libmeta_la_SOURCES += ps2_strlr.c +libmeta_la_SOURCES += lsf.c +libmeta_la_SOURCES += ps3_vawx.c +libmeta_la_SOURCES += pc_snds.c +libmeta_la_SOURCES += ps2_wmus.c +libmeta_la_SOURCES += mattel_hyperscan.c +libmeta_la_SOURCES += ios_psnd.c +libmeta_la_SOURCES += pc_adp.c +libmeta_la_SOURCES += excitebots.c +libmeta_la_SOURCES += ps2_mtaf.c +libmeta_la_SOURCES += ps3_klbs.c +libmeta_la_SOURCES += tun.c +libmeta_la_SOURCES += wpd.c +libmeta_la_SOURCES += mn_str.c +libmeta_la_SOURCES += ps2_mss.c +libmeta_la_SOURCES += ps2_hsf.c +libmeta_la_SOURCES += ps3_ivag.c +libmeta_la_SOURCES += ps2_2pfs.c +libmeta_la_SOURCES += ubi_ckd.c +libmeta_la_SOURCES += otm.c +libmeta_la_SOURCES += bcstm.c + +EXTRA_DIST = meta.h diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aax.c b/Frameworks/vgmstream/vgmstream/src/meta/aax.c new file mode 100644 index 000000000..47b02f290 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/aax.c @@ -0,0 +1,846 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../util.h" + +typedef struct _AAXSTREAMFILE +{ + STREAMFILE sf; + STREAMFILE *real_file; + off_t start_physical_offset; + size_t file_size; +} AAXSTREAMFILE; + +static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size); + +struct utf_query +{ + /* if 0 */ + const char *name; + int index; +}; + +struct offset_size_pair +{ + uint32_t offset; + uint32_t size; +}; + +struct utf_query_result +{ + int valid; /* table is valid */ + int found; + int type; /* one of COLUMN_TYPE_* */ + union + { + uint64_t value_u64; + uint32_t value_u32; + uint16_t value_u16; + uint8_t value_u8; + float value_float; + struct offset_size_pair value_data; + uint32_t value_string; + } value; + + /* info for the queried table */ + uint32_t rows; + uint32_t name_offset; + uint32_t string_table_offset; + uint32_t data_offset; +}; + +static struct utf_query_result analyze_utf(STREAMFILE *infile, long offset, + const struct utf_query *query); + +static struct utf_query_result query_utf(STREAMFILE *infile, long offset, + const struct utf_query *query); + +static struct utf_query_result query_utf_nofail(STREAMFILE *infile, const long offset, + const struct utf_query *query, int *error); + +static struct utf_query_result query_utf_key(STREAMFILE *infile, const long offset, + int index, const char *name, int *error); + +static uint8_t query_utf_1byte(STREAMFILE *infile, const long offset, + int index, const char *name, int *error); + +static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long offset, + int index, const char *name, int *error); + +#define COLUMN_STORAGE_MASK 0xf0 +#define COLUMN_STORAGE_PERROW 0x50 +#define COLUMN_STORAGE_CONSTANT 0x30 +#define COLUMN_STORAGE_ZERO 0x10 + +#define COLUMN_TYPE_MASK 0x0f +#define COLUMN_TYPE_DATA 0x0b +#define COLUMN_TYPE_STRING 0x0a +#define COLUMN_TYPE_FLOAT 0x08 +#define COLUMN_TYPE_8BYTE 0x06 +#define COLUMN_TYPE_4BYTE 0x04 +#define COLUMN_TYPE_2BYTE2 0x03 +#define COLUMN_TYPE_2BYTE 0x02 +#define COLUMN_TYPE_1BYTE2 0x01 +#define COLUMN_TYPE_1BYTE 0x00 + +struct utf_column_info +{ + uint8_t type; + const char *column_name; + long constant_offset; +}; + +struct utf_table_info +{ + long table_offset; + uint32_t table_size; + uint32_t schema_offset; + uint32_t rows_offset; + uint32_t string_table_offset; + uint32_t data_offset; + const char *string_table; + const char *table_name; + uint16_t columns; + uint16_t row_width; + uint32_t rows; + + const struct utf_column_info *schema; +}; + + +/* Actual AAX init fcn */ +VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileAAX = NULL; + STREAMFILE * streamFileADX = NULL; + char filename[PATH_LIMIT]; + off_t *segment_offset = NULL; + off_t *segment_size = NULL; + int32_t sample_count; + int table_error = 0; + + int loop_flag = 0; + int32_t loop_start_sample=0; + int32_t loop_end_sample=0; + int loop_segment = 0; + + aax_codec_data *data = NULL; + + const long AAX_offset = 0; + + int channel_count = 0, segment_count; + int sample_rate = 0; + + int i; + + + long aax_data_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("aax",filename_extension(filename))) goto fail; + + /* get AAX entry count, data offset */ + { + struct utf_query_result result; + long aax_string_table_offset; + long aax_string_table_size; + + result = query_utf_nofail(streamFile, AAX_offset, NULL, &table_error); + if (table_error) goto fail; + segment_count = result.rows; + aax_string_table_offset = AAX_offset + 8 + result.string_table_offset; + aax_data_offset = AAX_offset + 8 + result.data_offset; + aax_string_table_size = aax_data_offset - aax_string_table_offset; + + if (result.name_offset+4 > aax_string_table_size) goto fail; + if (read_32bitBE(aax_string_table_offset + result.name_offset, + streamFile) != 0x41415800) /* "AAX\0" */ + goto fail; + } + + segment_offset = calloc(segment_count,sizeof(off_t)); + if (!segment_offset) + goto fail; + segment_size = calloc(segment_count,sizeof(off_t)); + if (!segment_size) + goto fail; + + /* get offsets of constituent ADXs */ + for (i = 0; i < segment_count; i++) + { + struct offset_size_pair offset_size; + offset_size = query_utf_data(streamFile, AAX_offset, i, "data", &table_error); + if (table_error) goto fail; + segment_offset[i] = aax_data_offset + offset_size.offset; + segment_size[i] = offset_size.size; + } + + streamFileAAX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileAAX) goto fail; + + data = malloc(sizeof(aax_codec_data)); + if (!data) goto fail; + data->segment_count = segment_count; + data->adxs = malloc(sizeof(STREAMFILE *)*segment_count); + if (!data->adxs) goto fail; + for (i=0;iadxs[i] = NULL; + } + data->sample_counts = calloc(segment_count,sizeof(int32_t)); + if (!data->sample_counts) goto fail; + + /* for each segment */ + for (i = 0; i < segment_count; i++) + { + VGMSTREAM *adx; + /*printf("try opening segment %d/%d %x\n",i,segment_count,segment_offset[i]);*/ + streamFileADX = open_aax_with_STREAMFILE(streamFileAAX,segment_offset[i],segment_size[i]); + if (!streamFileADX) goto fail; + adx = data->adxs[i] = init_vgmstream_adx(streamFileADX); + if (!adx) + goto fail; + data->sample_counts[i] = adx->num_samples; + close_streamfile(streamFileADX); streamFileADX = NULL; + + if (i == 0) + { + channel_count = adx->channels; + sample_rate = adx->sample_rate; + } + else + { + if (channel_count != adx->channels) + goto fail; + if (sample_rate != adx->sample_rate) + goto fail; + } + + if (adx->loop_flag != 0) + goto fail; + + /* save start things so we can restart for seeking/looping */ + /* copy the channels */ + memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels); + /* copy the whole VGMSTREAM */ + memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM)); + + } + + sample_count = 0; + loop_flag = 0; + for (i = 0; i < segment_count; i++) + { + int segment_loop_flag = query_utf_1byte(streamFile, AAX_offset, i, + "lpflg", &table_error); + if (table_error) segment_loop_flag = 0; + + if (!loop_flag && segment_loop_flag) + { + loop_start_sample = sample_count; + loop_segment = i; + } + + sample_count += data->sample_counts[i]; + + if (!loop_flag && segment_loop_flag) + { + loop_end_sample = sample_count; + loop_flag = 1; + } + } + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + + vgmstream->coding_type = data->adxs[0]->coding_type; + vgmstream->layout_type = layout_aax; + vgmstream->meta_type = meta_AAX; + + vgmstream->ch[0].streamfile = streamFileAAX; + data->current_segment = 0; + data->loop_segment = loop_segment; + + vgmstream->codec_data = data; + free(segment_offset); + free(segment_size); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileAAX) close_streamfile(streamFileAAX); + if (streamFileADX) close_streamfile(streamFileADX); + if (vgmstream) close_vgmstream(vgmstream); + if (segment_offset) free(segment_offset); + if (segment_size) free(segment_size); + if (data) { + if (data->adxs) + { + int i; + for (i=0;isegment_count;i++) + if (data->adxs) + close_vgmstream(data->adxs[i]); + free(data->adxs); + } + if (data->sample_counts) + { + free(data->sample_counts); + } + free(data); + } + return NULL; +} + +/* virtual file, a piece of the overall file */ + +static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) +{ + /* truncate at end of logical file */ + if (offset+length > streamfile->file_size) + { + long signed_length = length; + signed_length = streamfile->file_size - offset; + if (signed_length < 0) signed_length = 0; + length = signed_length; + } + return read_streamfile(dest, + streamfile->start_physical_offset+offset, + length,streamfile->real_file); +} + +static void close_aax(AAXSTREAMFILE *streamfile) +{ + free(streamfile); + return; +} + +static size_t get_size_aax(AAXSTREAMFILE *streamfile) +{ + return 0; +} + +static size_t get_offset_aax(AAXSTREAMFILE *streamfile) +{ + long offset = streamfile->real_file->get_offset(streamfile->real_file); + offset -= streamfile->start_physical_offset; + if (offset < 0) offset = 0; + if (offset > streamfile->file_size) offset = streamfile->file_size; + + return offset; +} + +static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length) +{ + strncpy(buffer,"ARBITRARY.ADX",length); + buffer[length-1]='\0'; +} + +static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) +{ + AAXSTREAMFILE *newfile; + if (strcmp(filename,"ARBITRARY.ADX")) + return NULL; + + newfile = malloc(sizeof(AAXSTREAMFILE)); + if (!newfile) + return NULL; + memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE)); + return &newfile->sf; +} + +static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size) +{ + AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE)); + + if (!streamfile) + return NULL; + + /* success, set our pointers */ + + streamfile->sf.read = (void*)read_aax; + streamfile->sf.get_size = (void*)get_size_aax; + streamfile->sf.get_offset = (void*)get_offset_aax; + streamfile->sf.get_name = (void*)get_name_aax; + streamfile->sf.get_realname = (void*)get_name_aax; + streamfile->sf.open = (void*)open_aax_impl; + streamfile->sf.close = (void*)close_aax; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = NULL; + streamfile->sf.get_error_count = NULL; +#endif + + streamfile->real_file = file; + streamfile->start_physical_offset = start_offset; + streamfile->file_size = file_size; + + return &streamfile->sf; +} + +/* @UTF table reading, abridged */ +static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query) +{ + unsigned char buf[4]; + struct utf_table_info table_info; + char *string_table = NULL; + struct utf_column_info * schema = NULL; + struct utf_query_result result; + uint32_t table_name_string; + int string_table_size; + + result.valid = 0; + + table_info.table_offset = offset; + + /* check header */ + { + static const char UTF_signature[4] = "@UTF"; /* intentionally unterminated */ + if (4 != read_streamfile(buf, offset, 4, infile)) goto cleanup_error; + if (memcmp(buf, UTF_signature, sizeof(UTF_signature))) + { + goto cleanup_error; + } + } + + /* get table size */ + table_info.table_size = read_32bitBE(offset+4, infile); + + table_info.schema_offset = 0x20; + table_info.rows_offset = read_32bitBE(offset+8, infile); + table_info.string_table_offset = read_32bitBE(offset+0xc,infile); + table_info.data_offset = read_32bitBE(offset+0x10,infile); + table_name_string = read_32bitBE(offset+0x14,infile); + table_info.columns = read_16bitBE(offset+0x18,infile); + table_info.row_width = read_16bitBE(offset+0x1a,infile); + table_info.rows = read_32bitBE(offset+0x1c,infile); + + /* allocate for string table */ + string_table_size = table_info.data_offset-table_info.string_table_offset; + string_table = malloc(string_table_size+1); + if (!string_table) goto cleanup_error; + table_info.string_table = string_table; + memset(string_table, 0, string_table_size+1); + + /* load schema */ + schema = malloc(sizeof(struct utf_column_info) * table_info.columns); + if (!schema) goto cleanup_error; + + { + int i; + long schema_current_offset = table_info.schema_offset; + for (i = 0; i < table_info.columns; i++) + { + schema[i].type = read_8bit(schema_current_offset,infile); + schema_current_offset ++; + schema[i].column_name = string_table + read_32bitBE(schema_current_offset,infile); + schema_current_offset += 4; + + if ((schema[i].type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT) + { + schema[i].constant_offset = schema_current_offset; + switch (schema[i].type & COLUMN_TYPE_MASK) + { + case COLUMN_TYPE_8BYTE: + case COLUMN_TYPE_DATA: + schema_current_offset+=8; + break; + case COLUMN_TYPE_STRING: + case COLUMN_TYPE_FLOAT: + case COLUMN_TYPE_4BYTE: + schema_current_offset+=4; + break; + case COLUMN_TYPE_2BYTE2: + case COLUMN_TYPE_2BYTE: + schema_current_offset+=2; + break; + case COLUMN_TYPE_1BYTE2: + case COLUMN_TYPE_1BYTE: + schema_current_offset++; + break; + default: + goto cleanup_error; + } + } + } + } + + table_info.schema = schema; + + /* read string table */ + read_streamfile((unsigned char *)string_table, + table_info.string_table_offset+8+offset, + string_table_size, infile); + table_info.table_name = table_info.string_table+table_name_string; + + /* fill in the default stuff */ + result.found = 0; + result.rows = table_info.rows; + result.name_offset = table_name_string; + result.string_table_offset = table_info.string_table_offset; + result.data_offset = table_info.data_offset; + + /* explore the values */ + if (query) { + int i, j; + + for (i = 0; i < table_info.rows; i++) + { + uint32_t row_offset = + table_info.table_offset + 8 + table_info.rows_offset + + i * table_info.row_width; + const uint32_t row_start_offset = row_offset; + + if (query && i != query->index) continue; + + for (j = 0; j < table_info.columns; j++) + { + uint8_t type = table_info.schema[j].type; + long constant_offset = table_info.schema[j].constant_offset; + int constant = 0; + + int qthis = (query && i == query->index && + !strcmp(table_info.schema[j].column_name, query->name)); + + if (qthis) + { + result.found = 1; + result.type = schema[j].type & COLUMN_TYPE_MASK; + } + + switch (schema[j].type & COLUMN_STORAGE_MASK) + { + case COLUMN_STORAGE_PERROW: + break; + case COLUMN_STORAGE_CONSTANT: + constant = 1; + break; + case COLUMN_STORAGE_ZERO: + if (qthis) + { + memset(&result.value, 0, + sizeof(result.value)); + } + continue; + default: + goto cleanup_error; + } + + if (1) + { + long data_offset; + int bytes_read; + + if (constant) + { + data_offset = constant_offset; + } + else + { + data_offset = row_offset; + } + + switch (type & COLUMN_TYPE_MASK) + { + case COLUMN_TYPE_STRING: + { + uint32_t string_offset; + string_offset = read_32bitBE(data_offset, infile); + bytes_read = 4; + if (qthis) + { + result.value.value_string = string_offset; + } + } + break; + case COLUMN_TYPE_DATA: + { + uint32_t vardata_offset, vardata_size; + + vardata_offset = read_32bitBE(data_offset, infile); + vardata_size = read_32bitBE(data_offset+4, infile); + bytes_read = 8; + if (qthis) + { + result.value.value_data.offset = vardata_offset; + result.value.value_data.size = vardata_size; + } + } + break; + + case COLUMN_TYPE_8BYTE: + { + uint64_t value = + read_32bitBE(data_offset, infile); + value <<= 32; + value |= + read_32bitBE(data_offset+4, infile); + if (qthis) + { + result.value.value_u64 = value; + } + bytes_read = 8; + break; + } + case COLUMN_TYPE_4BYTE: + { + uint32_t value = + read_32bitBE(data_offset, infile); + if (qthis) + { + result.value.value_u32 = value; + } + bytes_read = 4; + } + break; + case COLUMN_TYPE_2BYTE2: + case COLUMN_TYPE_2BYTE: + { + uint16_t value = + read_16bitBE(data_offset, infile); + if (qthis) + { + result.value.value_u16 = value; + } + bytes_read = 2; + } + break; + case COLUMN_TYPE_FLOAT: + if (sizeof(float) == 4) + { + union { + float float_value; + uint32_t int_value; + } int_float; + + int_float.int_value = read_32bitBE(data_offset, infile); + if (qthis) + { + result.value.value_float = int_float.float_value; + } + } + else + { + read_32bitBE(data_offset, infile); + if (qthis) + { + goto cleanup_error; + } + } + bytes_read = 4; + break; + case COLUMN_TYPE_1BYTE2: + case COLUMN_TYPE_1BYTE: + { + uint8_t value = + read_8bit(data_offset, infile); + if (qthis) + { + result.value.value_u8 = value; + } + bytes_read = 1; + } + break; + default: + goto cleanup_error; + } + + if (!constant) + { + row_offset += bytes_read; + } + } /* useless if end */ + } /* column for loop end */ + + if (row_offset - row_start_offset != table_info.row_width) + goto cleanup_error; + + if (query && i >= query->index) break; + } /* row for loop end */ + } /* explore values block end */ + +//cleanup: + + result.valid = 1; +cleanup_error: + + if (string_table) + { + free(string_table); + string_table = NULL; + } + + if (schema) + { + free(schema); + schema = NULL; + } + + return result; +} + +static struct utf_query_result query_utf(STREAMFILE *infile, const long offset, const struct utf_query *query) +{ + return analyze_utf(infile, offset, query); +} + +static struct utf_query_result query_utf_nofail(STREAMFILE *infile, const long offset, const struct utf_query *query, int *error) +{ + const struct utf_query_result result = query_utf(infile, offset, query); + + if (error) + { + *error = 0; + if (!result.valid) *error = 1; + if (query && !result.found) *error = 1; + } + + return result; +} + +static struct utf_query_result query_utf_key(STREAMFILE *infile, const long offset, int index, const char *name, int *error) +{ + struct utf_query query; + query.index = index; + query.name = name; + + return query_utf_nofail(infile, offset, &query, error); +} + +static uint8_t query_utf_1byte(STREAMFILE *infile, const long offset, int index, const char *name, int *error) +{ + struct utf_query_result result = query_utf_key(infile, offset, index, name, error); + if (error) + { + if (result.type != COLUMN_TYPE_1BYTE) *error = 1; + } + return result.value.value_u8; +} + +static uint32_t query_utf_4byte(STREAMFILE *infile, const long offset, int index, const char *name, int *error) +{ + struct utf_query_result result = query_utf_key(infile, offset, index, name, error); + if (error) + { + if (result.type != COLUMN_TYPE_4BYTE) *error = 1; + } + return result.value.value_u32; +} + +static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long offset, + int index, const char *name, int *error) +{ + struct utf_query_result result = query_utf_key(infile, offset, index, name, error); + if (error) + { + if (result.type != COLUMN_TYPE_DATA) *error = 1; + } + return result.value.value_data; +} + +/* CRI's UTF wrapper around DSP */ +VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int table_error = 0; + + int loop_flag = 0; + + const long top_offset = 0; + + int channel_count; + int sample_rate; + long sample_count; + + long top_data_offset, segment_count; + long body_offset, body_size; + long header_offset, header_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + //if (strcasecmp("aax",filename_extension(filename))) goto fail; + + /* get entry count, data offset */ + { + struct utf_query_result result; + long top_string_table_offset; + long top_string_table_size; + long name_offset; + + result = query_utf_nofail(streamFile, top_offset, NULL, &table_error); + if (table_error) goto fail; + segment_count = result.rows; + if (segment_count != 1) goto fail; // only simple stuff for now + top_string_table_offset = top_offset + 8 + result.string_table_offset; + top_data_offset = top_offset + 8 + result.data_offset; + top_string_table_size = top_data_offset - top_string_table_offset; + + if (result.name_offset+10 > top_string_table_size) goto fail; + + name_offset = top_string_table_offset + result.name_offset; + if (read_32bitBE(name_offset, streamFile) != 0x41445043 ||// "ADPC" + read_32bitBE(name_offset+4, streamFile) != 0x4D5F5749 ||// "M_WI" + read_16bitBE(name_offset+8, streamFile) != 0x4900) // "I\0" + goto fail; + } + + { + struct offset_size_pair offset_size; + + offset_size = query_utf_data(streamFile, top_offset, 0, "data", &table_error); + if (table_error) goto fail; + body_offset = top_data_offset + offset_size.offset; + body_size = offset_size.size; + + offset_size = query_utf_data(streamFile, top_offset, 0, "header", &table_error); + if (table_error) goto fail; + header_offset = top_data_offset + offset_size.offset; + header_size = offset_size.size; + } + + channel_count = query_utf_1byte(streamFile, top_offset, 0, "nch", &table_error); + sample_count = query_utf_4byte(streamFile, top_offset, 0, "nsmpl", &table_error); + sample_rate = query_utf_4byte(streamFile, top_offset, 0, "sfreq", &table_error); + if (table_error) goto fail; + if (channel_count != 1 && channel_count != 2) goto fail; + if (header_size != channel_count * 0x60) goto fail; + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_UTF_DSP; + + { + int i,j; + long channel_size = (body_size+7)/8*8/channel_count; + for (i = 0; i < channel_count; i++) + { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset = + vgmstream->ch[i].offset = body_offset + i * channel_size; + for (j=0;j<16;j++) + { + vgmstream->ch[i].adpcm_coef[j] = + read_16bitBE(header_offset + 0x60*i + 0x1c + j*2, streamFile); + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/acm.c b/Frameworks/vgmstream/vgmstream/src/meta/acm.c new file mode 100644 index 000000000..e91a9cb7f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/acm.c @@ -0,0 +1,66 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../util.h" +#include "../coding/acm_decoder.h" + +/* InterPlay ACM */ +/* The real work is done by libacm */ +VGMSTREAM * init_vgmstream_acm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + ACMStream *acm_stream = NULL; + mus_acm_codec_data *data; + + char filename[PATH_LIMIT]; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("acm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x97280301) + goto fail; + + data = calloc(1,sizeof(mus_acm_codec_data)); + if (!data) goto fail; + + data->files = calloc(1,sizeof(ACMStream *)); + if (!data->files) { + free(data); data = NULL; + goto fail; + } + + /* gonna do this a little backwards, open and parse the file + before creating the vgmstream */ + + if (acm_open_decoder(&acm_stream,streamFile,filename) != ACM_OK) { + goto fail; + } + + channel_count = acm_stream->info.channels; + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = acm_stream->info.rate; + vgmstream->coding_type = coding_ACM; + vgmstream->num_samples = acm_stream->total_values / acm_stream->info.channels; + vgmstream->layout_type = layout_acm; + vgmstream->meta_type = meta_ACM; + + data->file_count = 1; + data->current_file = 0; + data->files[0] = acm_stream; + /*data->end_file = -1;*/ + + vgmstream->codec_data = data; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ads.c b/Frameworks/vgmstream/vgmstream/src/meta/ads.c new file mode 100644 index 000000000..0ec46e7b9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ads.c @@ -0,0 +1,120 @@ +#include "meta.h" +#include "../util.h" + +/* ADS (from Gauntlet Dark Legends (GC)) */ +VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + int identifer_byte; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ads",filename_extension(filename))) goto fail; + + /* check dhSS Header */ + if (read_32bitBE(0x00,streamFile) != 0x64685353) + goto fail; + + /* check dbSS Header */ + if (read_32bitBE(0x20,streamFile) != 0x64625353) + goto fail; + + loop_flag = 1; + channel_count = read_32bitBE(0x10,streamFile); + + if (channel_count > 0x2) + goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + identifer_byte = read_32bitBE(0x08,streamFile); + switch (identifer_byte) { + case 0x00000020: + start_offset = 0xE8; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x28,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if (channel_count == 1){ + vgmstream->layout_type = layout_none; + } else if (channel_count == 2){ + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); + } + break; + case 0x00000021: + start_offset = 0x28; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0c,streamFile); + vgmstream->coding_type = coding_INT_XBOX; + vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x24; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + break; + default: +goto fail; +} + + vgmstream->meta_type = meta_ADS; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x44+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xA4+i*2,streamFile); + } + } + + + /* open the file for reading */ + if (vgmstream->coding_type == coding_NGC_DSP) { + int i,c; + for (c=0;cch[c].adpcm_coef[i] = + read_16bitBE(0x44+c*0x60 +i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/adx_header.c b/Frameworks/vgmstream/vgmstream/src/meta/adx_header.c new file mode 100644 index 000000000..8767ccab3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/adx_header.c @@ -0,0 +1,598 @@ +#ifdef _MSC_VER +#define _USE_MATH_DEFINES +#endif +#include +#include +#include +#include "meta.h" + +#include "../coding/coding.h" +#include "../util.h" + +static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add); + +VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t stream_offset; + size_t filesize; + uint16_t version_signature; + int loop_flag=0; + int channel_count; + int32_t loop_start_offset=0; + int32_t loop_end_offset=0; + int32_t loop_start_sample=0; + int32_t loop_end_sample=0; + meta_t header_type; + int16_t coef1, coef2; + uint16_t cutoff; + char filename[PATH_LIMIT]; + int coding_type = coding_CRI_ADX; + uint16_t xor_start=0,xor_mult=0,xor_add=0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("adx",filename_extension(filename))) goto fail; + + filesize = get_streamfile_size(streamFile); + + /* check first 2 bytes */ + if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail; + + /* get stream offset, check for CRI signature just before */ + stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4; + if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */ + (uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */ + ) goto fail; + + /* check for encoding type */ + /* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is + * ADX with exponential scale, 0x11 is AHX */ + if (read_8bit(4,streamFile) != 3) goto fail; + + /* check for frame size (only 18 is supported at the moment) */ + if (read_8bit(5,streamFile) != 18) goto fail; + + /* check for bits per sample? (only 4 makes sense for ADX) */ + if (read_8bit(6,streamFile) != 4) goto fail; + + /* check version signature, read loop info */ + version_signature = read_16bitBE(0x12,streamFile); + /* encryption */ + if (version_signature == 0x0408) { + if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add)) + { + coding_type = coding_CRI_ADX_enc_8; + version_signature = 0x0400; + } + } + else if (version_signature == 0x0409) { + if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add)) + { + coding_type = coding_CRI_ADX_enc_9; + version_signature = 0x0400; + } + } + + if (version_signature == 0x0300) { /* type 03 */ + header_type = meta_ADX_03; + if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */ + loop_flag = (read_32bitBE(0x18,streamFile) != 0); + loop_start_sample = read_32bitBE(0x1c,streamFile); + loop_start_offset = read_32bitBE(0x20,streamFile); + loop_end_sample = read_32bitBE(0x24,streamFile); + loop_end_offset = read_32bitBE(0x28,streamFile); + } + } else if (version_signature == 0x0400) { + + off_t ainf_info_length=0; + + if((uint32_t)read_32bitBE(0x24,streamFile)==0x41494E46) /* AINF Header */ + ainf_info_length = (off_t)read_32bitBE(0x28,streamFile); + + header_type = meta_ADX_04; + if (stream_offset-ainf_info_length-6 >= 0x38) { /* enough space for loop info? */ + if (read_32bitBE(0x24,streamFile) == 0xFFFEFFFE) + loop_flag = 0; + else + loop_flag = (read_32bitBE(0x24,streamFile) != 0); + + loop_start_sample = read_32bitBE(0x28,streamFile); + loop_start_offset = read_32bitBE(0x2c,streamFile); + loop_end_sample = read_32bitBE(0x30,streamFile); + loop_end_offset = read_32bitBE(0x34,streamFile); + } + } else if (version_signature == 0x0500) { /* found in some SFD : Buggy Heat, appears to have no loop */ + header_type = meta_ADX_05; + } else goto fail; /* not a known/supported version signature */ + + /* At this point we almost certainly have an ADX file, + * so let's build the VGMSTREAM. */ + + /* high-pass cutoff frequency, always 500 that I've seen */ + cutoff = (uint16_t)read_16bitBE(0x10,streamFile); + + if (loop_start_sample == 0 && loop_end_sample == 0) { + loop_flag = 0; + } + + channel_count = read_8bit(7,streamFile); + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0xc,streamFile); + vgmstream->sample_rate = read_32bitBE(8,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + + vgmstream->coding_type = coding_type; + if (channel_count==1) + vgmstream->layout_type = layout_none; + else + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = header_type; + + vgmstream->interleave_block_size=18; + + /* calculate filter coefficients */ + { + double x,y,z,a,b,c; + + x = cutoff; + y = vgmstream->sample_rate; + z = cos(2.0*M_PI*x/y); + + a = M_SQRT2-z; + b = M_SQRT2-1.0; + c = (a-sqrt((a+b)*(a-b)))/b; + + coef1 = floor(c*8192); + coef2 = floor(c*c*-4096); + } + + { + int i; + STREAMFILE * chstreamfile; + + /* ADX is so tightly interleaved that having two buffers is silly */ + chstreamfile = streamFile->open(streamFile,filename,18*0x400); + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + stream_offset+18*i; + + vgmstream->ch[i].adpcm_coef[0] = coef1; + vgmstream->ch[i].adpcm_coef[1] = coef2; + + if (coding_type == coding_CRI_ADX_enc_8 || + coding_type == coding_CRI_ADX_enc_9) + { + int j; + vgmstream->ch[i].adx_channels = channel_count; + vgmstream->ch[i].adx_xor = xor_start; + vgmstream->ch[i].adx_mult = xor_mult; + vgmstream->ch[i].adx_add = xor_add; + + for (j=0;jch[i]); + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* guessadx stuff */ + +/* type 8 keys */ +static struct { + uint16_t start,mult,add; +} keys_8[] = { + /* Clover Studio (GOD HAND, Okami) */ + /* I'm pretty sure this is right, based on a decrypted version of some GOD HAND tracks. */ + /* Also it is the 2nd result from guessadx */ + {0x49e1,0x4a57,0x553d}, + + /* Grasshopper Manufacture 0 (Blood+) */ + /* this is estimated */ + {0x5f5d,0x58bd,0x55ed}, + + /* Grasshopper Manufacture 1 (Killer7) */ + /* this is estimated */ + {0x50fb,0x5803,0x5701}, + + /* Grasshopper Manufacture 2 (Samurai Champloo) */ + /* confirmed unique with guessadx */ + {0x4f3f,0x472f,0x562f}, + + /* Moss Ltd (Raiden III) */ + /* this is estimated */ + {0x66f5,0x58bd,0x4459}, + + /* Sonic Team 0 (Phantasy Star Universe) */ + /* this is estimated */ + {0x5deb,0x5f27,0x673f}, + + /* G.rev 0 (Senko no Ronde) */ + /* this is estimated */ + {0x46d3,0x5ced,0x474d}, + + /* Sonic Team 1 (NiGHTS: Journey of Dreams) */ + /* this seems to be dead on, but still estimated */ + {0x440b,0x6539,0x5723}, + + /* from guessadx (unique?), unknown source */ + {0x586d,0x5d65,0x63eb}, + + /* Navel (Shuffle! On the Stage) */ + /* 2nd key from guessadx */ + {0x4969,0x5deb,0x467f}, + + /* Success (Aoishiro) */ + /* 1st key from guessadx */ + {0x4d65,0x5eb7,0x5dfd}, + + /* Sonic Team 2 (Sonic and the Black Knight) */ + /* confirmed unique with guessadx */ + {0x55b7,0x6191,0x5a77}, + + /* Enterbrain (Amagami) */ + /* one of 32 from guessadx */ + {0x5a17,0x509f,0x5bfd}, + + /* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */ + /* confirmed unique with guessadx */ + {0x4c01,0x549d,0x676f}, + + /* Kadokawa Shoten (Fragments Blue) */ + /* confirmed unique with guessadx */ + {0x5803,0x4555,0x47bf}, + + /* Namco (Soulcalibur IV) */ + /* confirmed unique with guessadx */ + {0x59ed,0x4679,0x46c9}, + + /* G.rev 1 (Senko no Ronde DUO) */ + /* from guessadx */ + {0x6157,0x6809,0x4045}, + + /* ASCII Media Works 0 (Nogizaka Haruka no Himitsu: Cosplay Hajimemashita) */ + /* 2nd from guessadx, other was {0x45ad,0x5f27,0x10fd} */ + {0x45af,0x5f27,0x52b1}, + + /* D3 Publisher 0 (Little Anchor) */ + /* confirmed unique with guessadx */ + {0x5f65,0x5b3d,0x5f65}, + + /* Marvelous 0 (Hanayoi Romanesque: Ai to Kanashimi) */ + /* 2nd from guessadx, other was {0x5562,0x5047,0x1433} */ + {0x5563,0x5047,0x43ed}, + + /* Capcom (Mobile Suit Gundam: Gundam vs. Gundam NEXT PLUS) */ + /* confirmed unique with guessadx */ + {0x4f7b,0x4fdb,0x5cbf}, + + /* Developer: Bridge NetShop + * Publisher: Kadokawa Shoten (Shoukan Shoujo: Elemental Girl Calling) */ + /* confirmed unique with guessadx */ + {0x4f7b,0x5071,0x4c61}, + + /* Developer: Net Corporation + * Publisher: Tecmo (Rakushou! Pachi-Slot Sengen 6: Rio 2 Cruising Vanadis) */ + /* confirmed unique with guessadx */ + {0x53e9,0x586d,0x4eaf}, + + /* Developer: Aquaplus + * Tears to Tiara Gaiden Avalon no Kagi (PS3) */ + /* confirmed unique with guessadx */ + {0x47e1,0x60e9,0x51c1}, + + /* Developer: Broccoli + * Neon Genesis Evangelion: Koutetsu no Girlfriend 2nd (PS2) */ + /* confirmed unique with guessadx */ + {0x481d,0x4f25,0x5243}, + + /* Developer: Marvelous + * Futakoi Alternative (PS2) */ + /* confirmed unique with guessadx */ + {0x413b,0x543b,0x57d1}, + + /* Developer: Marvelous + * Gakuen Utopia - Manabi Straight! KiraKira Happy Festa! (PS2) + * Second guess from guessadx, other was + * {0x440b,0x4327,0x564b} + **/ + {0x440d,0x4327,0x4fff}, + + /* Developer: Datam Polystar + * Soshite Kono Uchuu ni Kirameku Kimi no Shi XXX (PS2) */ + /* confirmed unique with guessadx */ + {0x5f5d,0x552b,0x5507}, + + /* Developer: Sega + * Sakura Taisen: Atsuki Chishio Ni (PS2) */ + /* confirmed unique with guessadx */ + {0x645d,0x6011,0x5c29}, + + /* Developer: Sega + * Sakura Taisen 3 ~Paris wa Moeteiru ka~ (PS2) */ + /* confirmed unique with guessadx */ + {0x62ad,0x4b13,0x5957}, + + /* Developer: Jinx + * Sotsugyou 2nd Generation (PS2) + * First guess from guessadx, other was + * {0x6307,0x509f,0x2ac5} + */ + {0x6305,0x509f,0x4c01}, + + /* + * La Corda d'Oro (2005)(-)(Koei)[PSP] + * confirmed unique with guessadx */ + {0x55b7,0x67e5,0x5387}, + + /* + * Nanatsuiro * Drops Pure!! (2007)(Media Works)[PS2] + * confirmed unique with guessadx */ + {0x6731,0x645d,0x566b}, + + /* + * Shakugan no Shana (2006)(Vridge)(Media Works)[PS2] + * confirmed unique with guessadx */ + {0x5fc5,0x63d9,0x599f}, + + /* + * Uragiri wa Boku no Namae o Shitteiru (2010)(Kadokawa Shoten)[PS2] + * confirmed unique with guessadx */ + {0x4c73,0x4d8d,0x5827}, + + /* + * StormLover Kai!! (2012)(D3 Publisher)[PSP] + * confirmed unique with guessadx */ + {0x5a11,0x67e5,0x6751}, + + /* + * Sora no Otoshimono - DokiDoki Summer Vacation (2010)(Kadokawa Shoten)[PSP] + * confirmed unique with guessadx */ + {0x5e75,0x4a89,0x4c61}, + + /* + * Boku wa Koukuu Kanseikan - Airport Hero Naha (2006)(Sonic Powered)(Electronic Arts)[PSP] + * confirmed unique with guessadx */ + {0x64ab,0x5297,0x632f}, + + /* + * Lucky Star - Net Idol Meister (2009)(Kadokawa Shoten)[PSP] + * confirmed unique with guessadx */ + {0x4d82,0x5243,0x685}, + + /* + * Ishin Renka: Ryouma Gaiden (2010-11-25)(-)(D3 Publisher)[PSP] + */ + {0x54d1,0x526d,0x5e8b}, + + /* + * Lucky Star - Ryouou Gakuen Outousai Portable (2010-12-22)(-)(Kadokawa Shoten)[PSP] + */ + {0x4d06,0x663b,0x7d09}, + + /* + * Marriage Royale - Prism Story (2010-04-28)(-)(ASCII Media Works)[PSP] + */ + {0x40a9,0x46b1,0x62ad}, + + /* + * Nogizaka Haruka no Himitsu - Doujinshi Hajime Mashita (2010-10-28)(-)(ASCII Media Works)[PSP] + */ + {0x4601,0x671f,0x0455}, + + /* + * Slotter Mania P - Mach Go Go Go III (2011-01-06)(-)(Dorart)[PSP] + */ + {0x41ef,0x463d,0x5507}, + + /* + * Nichijou - Uchuujin (2011-07-28)(-)(Kadokawa Shoten)[PSP] + */ + {0x4369,0x486d,0x5461}, + + /* + * R-15 Portable (2011-10-27)(-)(Kadokawa Shoten)[PSP] + */ + {0x6809,0x5fd5,0x5bb1}, + + /* + * Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP] + */ + {0x5c33,0x4133,0x4ce7}, + +}; + +/* type 9 keys */ +static struct { + uint16_t start,mult,add; +} keys_9[] = { + /* Phantasy Star Online 2 + * guessed with degod */ + {0x07d2,0x1ec5,0x0c7f}, +}; + +static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]); +static const int keys_9_count = sizeof(keys_9)/sizeof(keys_9[0]); + +/* return 0 if not found, 1 if found and set parameters */ +static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add) +{ + uint16_t * scales = NULL; + uint16_t * prescales = NULL; + int bruteframe=0,bruteframecount=-1; + int startoff, endoff; + int rc = 0; + + startoff=read_16bitBE(2, file)+4; + endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff; + + /* how many scales? */ + { + int framecount=(endoff-startoff)/18; + if (framecount longest_length) { + longest_length=length; + longest=i-length+1; + if (longest_length >= 0x8000) break; + } + } + if (longest==-1) { + goto find_key_cleanup; + } + bruteframecount = longest_length; + bruteframe = longest; + } + + { + /* try to guess key */ +#define MAX_FRAMES (INT_MAX/0x8000) + int scales_to_do; + int key_id; + + /* allocate storage for scales */ + scales_to_do = (bruteframecount > MAX_FRAMES ? MAX_FRAMES : bruteframecount); + scales = malloc(scales_to_do*sizeof(uint16_t)); + if (!scales) { + goto find_key_cleanup; + } + /* prescales are those scales before the first frame we test + * against, we use these to compute the actual start */ + if (bruteframe > 0) { + int i; + /* allocate memory for the prescales */ + prescales = malloc(bruteframe*sizeof(uint16_t)); + if (!prescales) { + goto find_key_cleanup; + } + /* read the prescales */ + for (i=0; iget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("afc",filename_extension(filename))) goto fail; + + /* don't grab AIFF-C with .afc extension */ + if ((uint32_t)read_32bitBE(0x0,streamFile)==0x464F524D) /* FORM */ + goto fail; + + /* we will get a sample rate, that's as close to checking as I think + * we can get */ + + /* build the VGMSTREAM */ + + loop_flag = read_32bitBE(0x10,streamFile); + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x04,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_AFC; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_AFC; + + /* frame-level interleave (9 bytes) */ + vgmstream->interleave_block_size = 9; + + /* open the file for reading by each channel */ + { + STREAMFILE *chstreamfile; + int i; + + /* both channels use same buffer, as interleave is so small */ + chstreamfile = streamFile->open(streamFile,filename,9*channel_count*0x100); + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + 0x20 + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/agsc.c b/Frameworks/vgmstream/vgmstream/src/meta/agsc.c new file mode 100644 index 000000000..d2f55b427 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/agsc.c @@ -0,0 +1,73 @@ +#include "meta.h" +#include "../util.h" + +/* .agsc - from Metroid Prime 2 */ + +VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t header_offset; + off_t start_offset; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("agsc",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x00000001) + goto fail; + + /* count length of name, including terminating 0 */ + for (header_offset=4;header_offset < get_streamfile_size(streamFile) && read_8bit(header_offset,streamFile)!='\0';header_offset++); + + header_offset ++; + + channel_count = 1; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(1,1); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(header_offset+0xda,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(header_offset+0xd8,streamFile); + + vgmstream->loop_start_sample = read_32bitBE(header_offset+0xde,streamFile); + /* this is cute, we actually have a "loop length" */ + vgmstream->loop_end_sample = (vgmstream->loop_start_sample + read_32bitBE(header_offset+0xe2,streamFile))-1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_AGSC; + + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(header_offset+0xf6+i*2,streamFile); + } + + start_offset = header_offset+0x116; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ahx.c b/Frameworks/vgmstream/vgmstream/src/meta/ahx.c new file mode 100644 index 000000000..908cd75a0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ahx.c @@ -0,0 +1,121 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_MPEG + +#include "meta.h" +#include "../util.h" + +/* AHX is a CRI format which contains an MPEG-2 Layer 2 audio stream. + * Although the MPEG frame headers are incorrect... */ + +VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t stream_offset; + size_t filesize; + char filename[PATH_LIMIT]; + int channel_count = 1; + int loop_flag = 0; + mpeg_codec_data *data = NULL; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ahx",filename_extension(filename))) goto fail; + + filesize = get_streamfile_size(streamFile); + + /* check first 2 bytes */ + if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail; + + /* get stream offset, check for CRI signature just before */ + stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4; + if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */ + (uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */ + ) goto fail; + + /* check for encoding type */ + /* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is + * ADX with exponential scale, 0x11 is AHX */ + /* Sappharad reports that old AHXs (Sonic Adventure 2) don't have this flag. + * When I see one perhaps I can add an exception for those. */ + if (read_8bit(4,streamFile) != 0x11) goto fail; + + /* check for frame size (0 for AHX) */ + if (read_8bit(5,streamFile) != 0) goto fail; + + /* check for bits per sample? (0 for AHX) */ + if (read_8bit(6,streamFile) != 0) goto fail; + + /* check channel count (only mono AHXs are known) */ + if (read_8bit(7,streamFile) != 1) goto fail; + + /* At this point we almost certainly have an ADX file, + * so let's build the VGMSTREAM. */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0xc,streamFile); + /* This is the One True Samplerate, the MPEG headers lie. */ + vgmstream->sample_rate = read_32bitBE(8,streamFile); + + vgmstream->coding_type = coding_fake_MPEG2_L2; + vgmstream->layout_type = layout_fake_mpeg; + vgmstream->meta_type = meta_AHX; + + { + int i; + STREAMFILE * chstreamfile; + + chstreamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + stream_offset; + } + } + + /* ooh, fun part, set up mpg123 */ + { + int rc; + data = calloc(1,sizeof(mpeg_codec_data)); + if (!data) goto fail; + + data->m = mpg123_new(NULL,&rc); + if (rc==MPG123_NOT_INITIALIZED) { + if (mpg123_init()!=MPG123_OK) goto fail; + data->m = mpg123_new(NULL,&rc); + if (rc!=MPG123_OK) goto fail; + } else if (rc!=MPG123_OK) { + goto fail; + } + + if (mpg123_open_feed(data->m)!=MPG123_OK) { + goto fail; + } + + vgmstream->codec_data = data; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (data) { + if (data->m) { + mpg123_delete(data->m); + data->m = NULL; + } + free(data); + data = NULL; + } + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aifc.c b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c new file mode 100644 index 000000000..d46617e1c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/aifc.c @@ -0,0 +1,310 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Audio Interchange File Format AIFF-C */ +/* also plain AIFF, for good measure */ + +/* Included primarily for 3DO */ + +/* for reading integers inexplicably packed into 80 bit floats */ +uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) { + uint8_t buf[10]; + int32_t exponent; + int32_t mantissa; + int i; + + if (read_streamfile(buf,offset,10,streamFile) != 10) return 0; + + exponent = ((buf[0]<<8)|(buf[1]))&0x7fff; + exponent -= 16383; + + mantissa = 0; + for (i=0;i<8;i++) { + int32_t shift = exponent-7-i*8; + if (shift >= 0) + mantissa |= buf[i+2] << shift; + else if (shift > -8) + mantissa |= buf[i+2] >> -shift; + } + + return mantissa*((buf[0]&0x80)?-1:1); +} + +uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset, + int marker_id) { + uint16_t marker_count; + int i; + off_t marker_offset; + + marker_count = read_16bitBE(MarkerChunkOffset+8,streamFile); + marker_offset = MarkerChunkOffset+10; + for (i=0;iget_name(streamFile,filename,sizeof(filename)); + if (!strcasecmp("aifc",filename_extension(filename)) || + !strcasecmp("afc",filename_extension(filename)) || + !strcasecmp("aifcl",filename_extension(filename)) || + !strcasecmp("cbd2",filename_extension(filename))) + { + AIFCext = 1; + } + else if (!strcasecmp("aiff",filename_extension(filename)) || + !strcasecmp("aif",filename_extension(filename)) || + !strcasecmp("aiffl",filename_extension(filename))) + { + AIFFext = 1; + } + else goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)==0x464F524D && /* "FORM" */ + /* check that file = header (8) + data */ + (uint32_t)read_32bitBE(4,streamFile)+8==get_streamfile_size(streamFile)) + { + if ((uint32_t)read_32bitBE(8,streamFile)==0x41494643) /* "AIFC" */ + { + if (!AIFCext) goto fail; + AIFC = 1; + } + else if ((uint32_t)read_32bitBE(8,streamFile)==0x41494646) /* "AIFF" */ + { + if (!AIFFext) goto fail; + AIFF = 1; + } + else goto fail; + } else goto fail; + + file_size = get_streamfile_size(streamFile); + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xc; /* start with first chunk within FORM */ + + while (current_chunk < file_size) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitBE(current_chunk+4,streamFile); + + /* chunks must be padded to an even number of bytes but chunk + * size does not include that padding */ + if (chunk_size % 2) chunk_size++; + + if (current_chunk+8+chunk_size > file_size) goto fail; + + switch(chunk_type) { + case 0x46564552: /* FVER */ + /* only one per file */ + if (FormatVersionChunkFound) goto fail; + /* plain AIFF shouldn't have */ + if (AIFF) goto fail; + FormatVersionChunkFound = 1; + + /* specific size */ + if (chunk_size != 4) goto fail; + + /* Version 1 of AIFF-C spec timestamp */ + if ((uint32_t)read_32bitBE(current_chunk+8,streamFile) != + 0xA2805140) goto fail; + break; + case 0x434F4D4D: /* COMM */ + /* only one per file */ + if (CommonChunkFound) goto fail; + CommonChunkFound = 1; + + channel_count = read_16bitBE(current_chunk+8,streamFile); + if (channel_count <= 0) goto fail; + + sample_count = (uint32_t)read_32bitBE(current_chunk+0xa,streamFile); + + sample_size = read_16bitBE(current_chunk+0xe,streamFile); + + sample_rate = read80bitSANE(current_chunk+0x10,streamFile); + + if (AIFC) { + switch (read_32bitBE(current_chunk+0x1a,streamFile)) { + case 0x53445832: /* SDX2 */ + coding_type = coding_SDX2; + interleave = 1; + break; + case 0x43424432: /* CBD2 */ + coding_type = coding_CBD2; + interleave = 1; + break; + case 0x41445034: /* ADP4 */ + coding_type = coding_DVI_IMA; + /* don't know how stereo DVI is laid out */ + if (channel_count != 1) break; + break; + default: + /* we should probably support uncompressed here */ + goto fail; + } + } else if (AIFF) { + switch (sample_size) { + case 8: + coding_type = coding_PCM8; + interleave = 1; + break; + case 16: + coding_type = coding_PCM16BE; + interleave = 2; + break; + /* 32 is a possibility, but we don't see it and I + * don't have a reader for it yet */ + default: + goto fail; + } + } + + /* we don't check the human-readable portion of AIFF-C*/ + + break; + case 0x53534E44: /* SSND */ + /* at most one per file */ + if (SoundDataChunkFound) goto fail; + SoundDataChunkFound = 1; + + start_offset = current_chunk + 16 + read_32bitBE(current_chunk+8,streamFile); + break; + case 0x4D41524B: /* MARK */ + if (MarkerChunkFound) goto fail; + MarkerChunkFound = 1; + MarkerChunkOffset = current_chunk; + break; + case 0x494E5354: /* INST */ + if (InstrumentChunkFound) goto fail; + InstrumentChunkFound = 1; + InstrumentChunkOffset = current_chunk; + break; + default: + /* spec says we can skip unrecognized chunks */ + break; + } + + current_chunk += 8+chunk_size; + } + } + + if (AIFC) { + if (!FormatVersionChunkFound || !CommonChunkFound || !SoundDataChunkFound) + goto fail; + } else if (AIFF) { + if (!CommonChunkFound || !SoundDataChunkFound) + goto fail; + } + + /* read loop points */ + if (InstrumentChunkFound && MarkerChunkFound) { + int start_marker; + int end_marker; + /* use the sustain loop */ + /* if playMode=ForwardLooping */ + if (read_16bitBE(InstrumentChunkOffset+16,streamFile) == 1) { + start_marker = read_16bitBE(InstrumentChunkOffset+18,streamFile); + end_marker = read_16bitBE(InstrumentChunkOffset+20,streamFile); + /* check for sustain markers != 0 (invalid marker no) */ + if (start_marker && end_marker) { + /* find start marker */ + loop_start = find_marker(streamFile,MarkerChunkOffset,start_marker); + loop_end = find_marker(streamFile,MarkerChunkOffset,end_marker); + + /* find_marker is type uint32_t as the spec says that's the type + * of the position value, but it returns a -1 on error, and the + * loop_start and loop_end variables are int32_t, so the error + * will become apparent. + * We shouldn't have a loop point that overflows an int32_t + * anyway. */ + loop_flag = 1; + if (loop_start==loop_end) loop_flag = 0; + } + } + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->coding_type = coding_type; + if (channel_count > 1) + vgmstream->layout_type = layout_interleave; + else + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = interleave; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + if (AIFC) + vgmstream->meta_type = meta_AIFC; + else if (AIFF) + vgmstream->meta_type = meta_AIFF; + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset+i*interleave; + } + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/aix.c b/Frameworks/vgmstream/vgmstream/src/meta/aix.c new file mode 100644 index 000000000..840af854a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/aix.c @@ -0,0 +1,417 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../util.h" + +typedef struct _AIXSTREAMFILE +{ + STREAMFILE sf; + STREAMFILE *real_file; + off_t start_physical_offset; + off_t current_physical_offset; + off_t current_logical_offset; + off_t current_block_size; + int stream_id; +} AIXSTREAMFILE; + +static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id); + +VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileAIX = NULL; + STREAMFILE * streamFileADX = NULL; + char filename[PATH_LIMIT]; + off_t *segment_offset = NULL; + int32_t *samples_in_segment = NULL; + int32_t sample_count; + + int loop_flag = 0; + int32_t loop_start_sample=0; + int32_t loop_end_sample=0; + + aix_codec_data *data = NULL; + + off_t first_AIXP; + off_t stream_list_offset; + off_t stream_list_end; + const int segment_list_entry_size = 0x10; + const off_t segment_list_offset = 0x20; + + int stream_count,channel_count,segment_count; + int sample_rate; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("aix",filename_extension(filename))) goto fail; + + if (read_32bitBE(0x0,streamFile) != 0x41495846 || /* "AIXF" */ + read_32bitBE(0x08,streamFile) != 0x01000014 || + read_32bitBE(0x0c,streamFile) != 0x00000800) + goto fail; + + first_AIXP = read_32bitBE(0x4,streamFile)+8; + segment_count = (uint16_t)read_16bitBE(0x18,streamFile); + stream_list_offset = segment_list_offset+segment_list_entry_size*segment_count+0x10; + + if (stream_list_offset >= first_AIXP) + goto fail; + if (segment_count < 1) + goto fail; + + sample_rate = read_32bitBE(stream_list_offset+8,streamFile); + if (!check_sample_rate(sample_rate)) + goto fail; + + samples_in_segment = calloc(segment_count,sizeof(int32_t)); + if (!samples_in_segment) + goto fail; + segment_offset = calloc(segment_count,sizeof(off_t)); + if (!segment_offset) + goto fail; + + for (i = 0; i < segment_count; i++) + { + segment_offset[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0,streamFile); + samples_in_segment[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x08,streamFile); + /*printf("samples_in_segment[%d]=%d\n",i,samples_in_segment[i]);*/ + /* all segments must have equal sample rate */ + if (read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) != sample_rate) + { + /* segments > 0 can have 0 sample rate (Ryu ga gotoku: Kenzan! tenkei_sng1.aix), + seems to indicate same sample rate as first */ + if (!(i > 0 && read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) == 0)) + goto fail; + } + } + + if (segment_offset[0] != first_AIXP) + goto fail; + + stream_count = (uint8_t)read_8bit(stream_list_offset,streamFile); + if (stream_count < 1) + goto fail; + stream_list_end = stream_list_offset + 0x8 + stream_count * 8; + + if (stream_list_end >= first_AIXP) + goto fail; + + channel_count = 0; + for (i = 0; i < stream_count; i++) + { + /* all streams must have same samplerate as segments */ + if (read_32bitBE(stream_list_offset+8+i*8,streamFile)!=sample_rate) + goto fail; + channel_count += read_8bit(stream_list_offset+8+i*8+4,streamFile); + } + + /* check for existence of segments */ + for (i = 0; i < segment_count; i++) + { + int j; + off_t AIXP_offset = segment_offset[i]; + for (j = 0; j < stream_count; j++) + { + if (read_32bitBE(AIXP_offset,streamFile)!=0x41495850) /* "AIXP" */ + goto fail; + if (read_8bit(AIXP_offset+8,streamFile)!=j) + goto fail; + AIXP_offset += read_32bitBE(AIXP_offset+4,streamFile)+8; + } + } + + /*streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.0375*2/32*18segment_count);*/ + streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.1*segment_count); + if (!streamFileAIX) goto fail; + + data = malloc(sizeof(aix_codec_data)); + if (!data) goto fail; + data->segment_count = segment_count; + data->stream_count = stream_count; + data->adxs = malloc(sizeof(STREAMFILE *)*segment_count*stream_count); + if (!data->adxs) goto fail; + for (i=0;iadxs[i] = NULL; + } + data->sample_counts = calloc(segment_count,sizeof(int32_t)); + if (!data->sample_counts) goto fail; + memcpy(data->sample_counts,samples_in_segment,segment_count*sizeof(int32_t)); + + /* for each segment */ + for (i = 0; i < segment_count; i++) + { + int j; + /* for each stream */ + for (j = 0; j < stream_count; j++) + { + VGMSTREAM *adx; + /*printf("try opening segment %d/%d stream %d/%d %x\n",i,segment_count,j,stream_count,segment_offset[i]);*/ + streamFileADX = open_aix_with_STREAMFILE(streamFileAIX,segment_offset[i],j); + if (!streamFileADX) goto fail; + adx = data->adxs[i*stream_count+j] = init_vgmstream_adx(streamFileADX); + if (!adx) + goto fail; + close_streamfile(streamFileADX); streamFileADX = NULL; + + if (adx->num_samples != data->sample_counts[i] || + adx->loop_flag != 0) + goto fail; + + /* save start things so we can restart for seeking/looping */ + /* copy the channels */ + memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels); + /* copy the whole VGMSTREAM */ + memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM)); + + } + } + + if (segment_count > 1) + { + loop_flag = 1; + } + + sample_count = 0; + for (i = 0; i < segment_count; i++) + { + sample_count += data->sample_counts[i]; + + if (i == 0) + loop_start_sample = sample_count; + if (i == 1) + loop_end_sample = sample_count; + } + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + + vgmstream->coding_type = data->adxs[0]->coding_type; + vgmstream->layout_type = layout_aix; + vgmstream->meta_type = meta_AIX; + + vgmstream->ch[0].streamfile = streamFileAIX; + data->current_segment = 0; + + vgmstream->codec_data = data; + free(segment_offset); + free(samples_in_segment); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileAIX) close_streamfile(streamFileAIX); + if (streamFileADX) close_streamfile(streamFileADX); + if (vgmstream) close_vgmstream(vgmstream); + if (samples_in_segment) free(samples_in_segment); + if (segment_offset) free(segment_offset); + if (data) { + if (data->adxs) + { + int i; + for (i=0;isegment_count*data->stream_count;i++) + if (data->adxs) + close_vgmstream(data->adxs[i]); + free(data->adxs); + } + if (data->sample_counts) + { + free(data->sample_counts); + } + free(data); + } + return NULL; +} +static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length) +{ + size_t sz = 0; + + /*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/ + while (length > 0) + { + int read_something = 0; + + /* read the beginning of the requested block, if we can */ + if (offset >= streamfile->current_logical_offset) + { + off_t to_read; + off_t length_available; + + length_available = + (streamfile->current_logical_offset+ + streamfile->current_block_size) - + offset; + + if (length < length_available) + { + to_read = length; + } + else + { + to_read = length_available; + } + + if (to_read > 0) + { + size_t bytes_read; + + bytes_read = read_streamfile(dest, + streamfile->current_physical_offset+0x10+ + (offset-streamfile->current_logical_offset), + to_read,streamfile->real_file); + + sz += bytes_read; + if (bytes_read != to_read) + { + /* an error which we will not attempt to handle here */ + return sz; + } + + read_something = 1; + + dest += bytes_read; + offset += bytes_read; + length -= bytes_read; + } + } + + if (!read_something) + { + /* couldn't read anything, must seek */ + int found_block = 0; + + /* as we have no memory we must start seeking from the beginning */ + if (offset < streamfile->current_logical_offset) + { + streamfile->current_logical_offset = 0; + streamfile->current_block_size = 0; + streamfile->current_physical_offset = + streamfile->start_physical_offset; + } + + /* seek ye forwards */ + while (!found_block) { + /*printf("seek looks at %x\n",streamfile->current_physical_offset);*/ + switch (read_32bitBE(streamfile->current_physical_offset, + streamfile->real_file)) + { + case 0x41495850: /* AIXP */ + if (read_8bit( + streamfile->current_physical_offset+8, + streamfile->real_file) == + streamfile->stream_id) + { + streamfile->current_block_size = + (uint16_t)read_16bitBE( + streamfile->current_physical_offset+0x0a, + streamfile->real_file); + + if (offset >= streamfile->current_logical_offset+ + streamfile->current_block_size) + { + streamfile->current_logical_offset += + streamfile->current_block_size; + } + else + { + found_block = 1; + } + } + + if (!found_block) + { + streamfile->current_physical_offset += + read_32bitBE( + streamfile->current_physical_offset+0x04, + streamfile->real_file + ) + 8; + } + + break; + case 0x41495846: /* AIXF */ + /* shouldn't ever see this */ + case 0x41495845: /* AIXE */ + /* shouldn't have reached the end o' the line... */ + default: + return sz; + break; + } /* end block/chunk type select */ + } /* end while !found_block */ + } /* end if !read_something */ + } /* end while length > 0 */ + + return sz; +} + +static void close_aix(AIXSTREAMFILE *streamfile) +{ + free(streamfile); + return; +} + +static size_t get_size_aix(AIXSTREAMFILE *streamfile) +{ + return 0; +} + +static size_t get_offset_aix(AIXSTREAMFILE *streamfile) +{ + return streamfile->current_logical_offset; +} + +static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length) +{ + strncpy(buffer,"ARBITRARY.ADX",length); + buffer[length-1]='\0'; +} + +static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize) +{ + AIXSTREAMFILE *newfile; + if (strcmp(filename,"ARBITRARY.ADX")) + return NULL; + + newfile = malloc(sizeof(AIXSTREAMFILE)); + if (!newfile) + return NULL; + memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE)); + return &newfile->sf; +} + +static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id) +{ + AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE)); + + if (!streamfile) + return NULL; + + /* success, set our pointers */ + + streamfile->sf.read = (void*)read_aix; + streamfile->sf.get_size = (void*)get_size_aix; + streamfile->sf.get_offset = (void*)get_offset_aix; + streamfile->sf.get_name = (void*)get_name_aix; + streamfile->sf.get_realname = (void*)get_name_aix; + streamfile->sf.open = (void*)open_aix_impl; + streamfile->sf.close = (void*)close_aix; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = NULL; + streamfile->sf.get_error_count = NULL; +#endif + + streamfile->real_file = file; + streamfile->current_physical_offset = + streamfile->start_physical_offset = start_offset; + streamfile->current_logical_offset = 0; + streamfile->current_block_size = 0; + streamfile->stream_id = stream_id; + + return &streamfile->sf; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/akb.c b/Frameworks/vgmstream/vgmstream/src/meta/akb.c new file mode 100644 index 000000000..d16e814d8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/akb.c @@ -0,0 +1,32 @@ +#include "../vgmstream.h" +#include "meta.h" + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) +VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + + size_t filesize; + uint32_t loop_start, loop_end; + + if ((uint32_t)read_32bitBE(0, streamFile) != 0x414b4220) goto fail; + + loop_start = read_32bitLE(0x14, streamFile); + loop_end = read_32bitLE(0x18, streamFile); + + filesize = get_streamfile_size( streamFile ); + + vgmstream = init_vgmstream_mp4_aac_offset( streamFile, 0x20, filesize - 0x20 ); + if ( !vgmstream ) goto fail; + + if ( loop_start || loop_end ) { + vgmstream->loop_flag = 1; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + } + + return vgmstream; + +fail: + return NULL; +} +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/apple_caff.c b/Frameworks/vgmstream/vgmstream/src/meta/apple_caff.c new file mode 100644 index 000000000..f2ab60d53 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/apple_caff.c @@ -0,0 +1,170 @@ +#include "meta.h" +#include "../util.h" + +/* Apple Core Audio Format */ + +VGMSTREAM * init_vgmstream_apple_caff(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t start_offset = 0; + off_t data_size = 0; + off_t sample_count = 0; + off_t interleave = 0; + int sample_rate = -1, unused_frames = 0; + int channel_count = 0; + + off_t file_length; + off_t chunk_offset = 8; + int found_desc = 0, found_pakt = 0, found_data = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("caf",filename_extension(filename))) goto fail; + + /* check "caff" id */ + if (read_32bitBE(0,streamFile)!=0x63616666) goto fail; + /* check version, flags */ + if (read_32bitBE(4,streamFile)!=0x00010000) goto fail; + + file_length = (off_t)get_streamfile_size(streamFile); + + while (chunk_offset < file_length) + { + /* high half of size (expect 0s) */ + if (read_32bitBE(chunk_offset+4,streamFile) != 0) goto fail; + + /* handle chunk type */ + switch (read_32bitBE(chunk_offset,streamFile)) + { + case 0x64657363: /* desc */ + found_desc = 1; + { + /* rather than put a convoluted conversion here for + portability, just look it up */ + uint32_t sratefloat = read_32bitBE(chunk_offset+0x0c, streamFile); + if (read_32bitBE(chunk_offset+0x10, streamFile) != 0) goto fail; + switch (sratefloat) + { + case 0x40D19400: + sample_rate = 18000; + break; + case 0x40D58880: + sample_rate = 22050; + break; + case 0x40DF4000: + sample_rate = 32000; + break; + case 0x40E58880: + sample_rate = 44100; + break; + case 0x40E77000: + sample_rate = 48000; + break; + default: + goto fail; + } + } + + { + uint32_t bytes_per_packet, frames_per_packet, channels_per_frame, bits_per_channel; + uint32_t codec_4cc = read_32bitBE(chunk_offset+0x14, streamFile); + /* only supporting ima4 for now */ + if (codec_4cc != 0x696d6134) goto fail; + + /* format flags */ + if (read_32bitBE(chunk_offset+0x18, streamFile) != 0) goto fail; + bytes_per_packet = read_32bitBE(chunk_offset+0x1c, streamFile); + frames_per_packet = read_32bitBE(chunk_offset+0x20, streamFile); + channels_per_frame = read_32bitBE(chunk_offset+0x24, streamFile); + bits_per_channel = read_32bitBE(chunk_offset+0x28, streamFile); + + interleave = bytes_per_packet / channels_per_frame; + channel_count = channels_per_frame; + if (channels_per_frame != 1 && channels_per_frame != 2) + goto fail; + /* ima4-specific */ + if (frames_per_packet != 64) goto fail; + if ((frames_per_packet / 2 + 2) * channels_per_frame != + bytes_per_packet) goto fail; + if (bits_per_channel != 0) goto fail; + } + break; + case 0x70616b74: /* pakt */ + found_pakt = 1; + /* 64-bit packet table size, 0 for constant bitrate */ + if ( + read_32bitBE(chunk_offset+0x0c,streamFile) != 0 || + read_32bitBE(chunk_offset+0x10,streamFile) != 0) goto fail; + /* high half of valid frames count */ + if (read_32bitBE(chunk_offset+0x14,streamFile) != 0) goto fail; + /* frame count */ + sample_count = read_32bitBE(chunk_offset+0x18,streamFile); + /* priming frames */ + if (read_32bitBE(chunk_offset+0x1c,streamFile) != 0) goto fail; + /* remainder (unused) frames */ + unused_frames = read_32bitBE(chunk_offset+0x20,streamFile); + break; + case 0x66726565: /* free */ + /* padding, ignore */ + break; + case 0x64617461: /* data */ + if (read_32bitBE(chunk_offset+12,streamFile) != 1) goto fail; + found_data = 1; + start_offset = chunk_offset + 16; + data_size = read_32bitBE(chunk_offset+8,streamFile) - 4; + break; + default: + goto fail; + } + + /* done with chunk */ + chunk_offset += 12 + read_32bitBE(chunk_offset+8,streamFile); + } + + if (!found_pakt || !found_desc || !found_data) goto fail; + if (start_offset == 0 || data_size == 0 || sample_count == 0 || + sample_rate == -1 || channel_count == 0) goto fail; + + /* ima4-specific */ + /* check for full packets */ + if (data_size % (interleave*channel_count) != 0) goto fail; + if ((sample_count+unused_frames)%((interleave-2)*2) != 0) goto fail; + /* check that all packets are accounted for */ + if (data_size/interleave/channel_count != + (sample_count+unused_frames)/((interleave-2)*2)) goto fail; + + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = sample_count; + /* ima4-specific */ + vgmstream->coding_type = coding_APPLE_IMA4; + if (channel_count == 2) + vgmstream->layout_type = layout_interleave; + else + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_CAFF; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].offset = + vgmstream->ch[i].channel_start_offset = + start_offset + interleave * i; + } + } + + return vgmstream; +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ast.c b/Frameworks/vgmstream/vgmstream/src/meta/ast.c new file mode 100644 index 000000000..fde881724 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ast.c @@ -0,0 +1,91 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type; + + int codec_number; + int channel_count; + int loop_flag; + + size_t max_block; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ast",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x5354524D || /* "STRM" */ + read_16bitBE(0xa,streamFile)!=0x10 || + /* check that file = header (0x40) + data */ + read_32bitBE(4,streamFile)+0x40!=get_streamfile_size(streamFile)) + goto fail; + + /* check for a first block */ + if (read_32bitBE(0x40,streamFile)!=0x424C434B) /* "BLCK" */ + goto fail; + + /* check type details */ + codec_number = read_16bitBE(8,streamFile); + loop_flag = read_16bitBE(0xe,streamFile); + channel_count = read_16bitBE(0xc,streamFile); + max_block = read_32bitBE(0x20,streamFile); + + switch (codec_number) { + case 0: + coding_type = coding_NGC_AFC; + break; + case 1: + coding_type = coding_PCM16BE; + break; + default: + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x14,streamFile); + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile); + + vgmstream->coding_type = coding_type; + vgmstream->layout_type = layout_ast_blocked; + vgmstream->meta_type = meta_AST; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename, + (i==0? + max_block+0x20-4: /* first buffer a bit bigger to + read block header without + inefficiency */ + max_block + ) + ); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* start me up */ + ast_block_update(0x40,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/baf.c b/Frameworks/vgmstream/vgmstream/src/meta/baf.c new file mode 100644 index 000000000..cbd573156 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/baf.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../util.h" + +/* .BAF - Bizarre Creations (Blur, James Bond 007: Blood Stone, etc) */ + +VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t WAVE_size,DATA_size; + off_t start_offset; + long sample_count; + + const int frame_size = 33; + const int frame_samples = 64; + int channels; + int loop_flag = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("baf",filename_extension(filename))) goto fail; + + /* check WAVE */ + if (read_32bitBE(0,streamFile) != 0x57415645) goto fail; + WAVE_size = read_32bitBE(4,streamFile); + if (WAVE_size != 0x4c) goto fail; + /* check for DATA after WAVE */ + if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) goto fail; + /* check that WAVE size is data size */ + DATA_size = read_32bitBE(0x30,streamFile); + if (read_32bitBE(WAVE_size+4,streamFile)-8 != DATA_size) goto fail; + + sample_count = read_32bitBE(0x44,streamFile); + + /* unsure how to detect channel count, so use a hack */ + channels = (long long)DATA_size / frame_size * frame_samples / sample_count; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = WAVE_size + 8; + vgmstream->sample_rate = read_32bitBE(0x40,streamFile); + vgmstream->num_samples = sample_count; + + vgmstream->coding_type = coding_BAF_ADPCM; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = frame_size; + vgmstream->meta_type = meta_BAF; + + /* open the file for reading by each channel */ + { + int i; + STREAMFILE *file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c new file mode 100644 index 000000000..2773a48eb --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bcstm.c @@ -0,0 +1,126 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type; + + off_t head_offset; + int codec_number; + int channel_count; + int loop_flag; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile, filename, sizeof(filename)); + if (strcasecmp("bcstm", filename_extension(filename))) + goto fail; + + + /* check header */ + if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ + goto fail; + if ((uint32_t)read_32bitBE(4, streamFile) != 0xFFFE4000) + goto fail; + + + + /* get head offset, check */ + head_offset = read_32bitLE(0x18, streamFile); + + if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */ + goto fail; + + + /* check type details */ + codec_number = read_8bit(head_offset + 0x20, streamFile); + loop_flag = read_8bit(head_offset + 0x21, streamFile); + channel_count = read_8bit(head_offset + 0x22, streamFile); + + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + break; + case 1: + coding_type = coding_PCM16BE; + break; + case 2: + coding_type = coding_NGC_DSP; + break; + default: + goto fail; + } + + if (channel_count < 1) goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitLE(head_offset + 0x2c, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitLE(head_offset + 0x24, streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_type; + if (channel_count == 1) + vgmstream->layout_type = layout_none; + else + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->meta_type = meta_CSTM; + + vgmstream->interleave_block_size = read_32bitLE(head_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitLE(head_offset + 0x44, streamFile); + + if (vgmstream->coding_type == coding_NGC_DSP) { + off_t coef_offset; + off_t coef_offset1; + off_t coef_offset2; + int i, j; + int coef_spacing = 0x2E; + + + coef_offset1 = read_32bitLE(head_offset + 0x1c, streamFile); + coef_offset = coef_offset1 + 0x40; + + + for (j = 0; jchannels; j++) { + for (i = 0; i<16; i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + } + } + } + + start_offset = read_32bitLE(0x30, streamFile) + 0x20; + + /* open the file for reading by each channel */ + { + int i; + for (i = 0; ilayout_type == layout_interleave_shortblock) + vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, + vgmstream->interleave_block_size); + else + vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename, + 0x1000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset = + vgmstream->ch[i].offset = + start_offset + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bgw.c b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c new file mode 100644 index 000000000..841d95d63 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bgw.c @@ -0,0 +1,140 @@ +#include "meta.h" +#include "../util.h" + +/* BGW (FF XI) */ +VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int32_t loop_start; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bgw",filename_extension(filename))) goto fail; + + /* "BGMStream" */ + if (read_32bitBE(0,streamFile) != 0x42474d53 || + read_32bitBE(4,streamFile) != 0x74726561 || + read_32bitBE(8,streamFile) != 0x6d000000 || + read_32bitBE(12,streamFile) != 0) goto fail; + + /* check file size with header value */ + if (read_32bitLE(0x10,streamFile) != get_streamfile_size(streamFile)) + goto fail; + + channel_count = read_8bit(0x2e,streamFile); + loop_start = read_32bitLE(0x1c,streamFile); + loop_flag = (loop_start > 0); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_FFXI; + vgmstream->num_samples = read_32bitLE(0x18,streamFile)*16; + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start-1)*16; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 9; + vgmstream->meta_type = meta_FFXI_BGW; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*9; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* .spw (SEWave, PlayOnline viewer for FFXI), very similar to bgw */ +VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int32_t loop_start; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("spw",filename_extension(filename))) goto fail; + + /* "SeWave" */ + if (read_32bitBE(0,streamFile) != 0x53655761 || + read_32bitBE(4,streamFile) != 0x76650000) goto fail; + + /* check file size with header value */ + if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile)) + goto fail; + + channel_count = read_8bit(0x2a,streamFile); + loop_start = read_32bitLE(0x18,streamFile); + loop_flag = (loop_start > 0); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x24,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_FFXI; + vgmstream->num_samples = read_32bitLE(0x14,streamFile)*16; + if (loop_flag) { + vgmstream->loop_start_sample = (loop_start-1)*16; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 9; + vgmstream->meta_type = meta_FFXI_SPW; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*9; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c new file mode 100644 index 000000000..de9a59eca --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/bnsf.c @@ -0,0 +1,202 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" +#include "../vgmstream.h" + +/* Namco Bandai's Bandai Namco Sound Format/File (BNSF) */ +/* similar to RIFX */ + +VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t file_size = -1; + uint32_t riff_size; + uint32_t bnsf_form; + enum { + form_IS14 = UINT32_C(0x49533134), /* IS14 */ + }; + + int channel_count = 0; + int sample_count = 0; + int sample_rate = 0; + int coding_type = -1; + off_t start_offset = -1; + + int loop_flag = 0; + off_t loop_start = -1; + off_t loop_end = -1; + uint32_t data_size = 0; + uint32_t block_size = 0; + uint32_t block_samples = 0; + + int FormatChunkFound = 0; + int DataChunkFound = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bnsf",filename_extension(filename))) + { + goto fail; + } + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */ + goto fail; + + /* check form */ + bnsf_form = read_32bitBE(8,streamFile); + switch (bnsf_form) + { +#ifdef VGM_USE_G7221 + case form_IS14: + break; +#endif + default: + goto fail; + } + + riff_size = read_32bitBE(4,streamFile); + file_size = get_streamfile_size(streamFile); + + /* check for tructated RIFF */ + if (file_size < riff_size+8) goto fail; + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xc; /* start with first chunk */ + + while (current_chunk < file_size && current_chunk < riff_size+8) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitBE(current_chunk+4,streamFile); + + if (current_chunk+8+chunk_size > file_size) goto fail; + + switch(chunk_type) { + case 0x73666d74: /* "sfmt" */ + /* only one per file */ + if (FormatChunkFound) goto fail; + FormatChunkFound = 1; + + sample_rate = read_32bitBE(current_chunk+0x0c,streamFile); + channel_count = read_16bitBE(current_chunk+0x0a,streamFile); + // read_32bitBE(current_chunk+0x10,streamFile); // ? + // read_32bitBE(current_chunk+0x14,streamFile); // ? + block_size = read_16bitBE(current_chunk+0x18,streamFile); + block_samples = read_16bitBE(current_chunk+0x1a,streamFile); + + /* I assume this is still the codec id, but as the codec is + specified by the BNSF "form" I've only seen this zero */ + switch ((uint16_t)read_16bitBE(current_chunk+0x8,streamFile)) { + case 0: + break; + default: + goto fail; + } + break; + case 0x73646174: /* sdat */ + /* at most one per file */ + if (DataChunkFound) goto fail; + DataChunkFound = 1; + + start_offset = current_chunk + 8; + data_size = chunk_size; + break; + case 0x6C6F6F70: /* loop */ + loop_flag = 1; + loop_start = + read_32bitBE(current_chunk+8, streamFile); + loop_end = + read_32bitBE(current_chunk+0xc,streamFile); + break; + default: + /* ignorance is bliss */ + break; + } + + current_chunk += 8+chunk_size; + } + } + + if (!FormatChunkFound || !DataChunkFound) goto fail; + + switch (bnsf_form) { +#ifdef VGM_USE_G7221 + case form_IS14: + coding_type = coding_G7221C; + sample_count = data_size/block_size*block_samples; + + break; +#endif + default: + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->coding_type = coding_type; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = block_size/channel_count; + + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + } + vgmstream->meta_type = meta_BNSF; + +#ifdef VGM_USE_G7221 + if (coding_G7221C == coding_type) + { + int i; + g7221_codec_data *data; + + /* one data structure per channel */ + data = malloc(sizeof(g7221_codec_data) * channel_count); + if (!data) + { + goto fail; + } + memset(data,0,sizeof(g7221_codec_data) * channel_count); + vgmstream->codec_data = data; + + for (i = 0; i < channel_count; i++) + { + /* Siren 14 == 14khz bandwidth */ + data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000); + if (!data[i].handle) + { + goto fail; /* close_vgmstream is able to clean up */ + } + } + } +#endif + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset+i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/brstm.c b/Frameworks/vgmstream/vgmstream/src/meta/brstm.c new file mode 100644 index 000000000..249999977 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/brstm.c @@ -0,0 +1,163 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type; + + off_t head_offset; + int codec_number; + int channel_count; + int loop_flag; + /* Certain Super Paper Mario tracks have a 44.1KHz sample rate in the + * header, but they should be played at 22.05KHz. We will make this + * correction if we see a file with a .brstmspm extension. */ + int spm_flag = 0; + /* Trauma Center Second Opinion has an odd, semi-corrupt header */ + int atlus_shrunken_head = 0; + + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("brstm",filename_extension(filename))) { + if (strcasecmp("brstmspm",filename_extension(filename))) goto fail; + else spm_flag = 1; + } + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x5253544D) /* "RSTM" */ + goto fail; + if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0100) + { + if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0001) + goto fail; + else + atlus_shrunken_head = 1; + } + + /* get head offset, check */ + head_offset = read_32bitBE(0x10,streamFile); + if (atlus_shrunken_head) + { + /* the HEAD chunk is where we would expect to find the offset of that + * chunk... */ + + if ((uint32_t)head_offset!=0x48454144 || read_32bitBE(0x14,streamFile) != 8) + goto fail; + + head_offset = -8; /* most of the normal Nintendo RSTM offsets work + with this assumption */ + } + else + { + if ((uint32_t)read_32bitBE(head_offset,streamFile)!=0x48454144) /* "HEAD" */ + goto fail; + } + + /* check type details */ + codec_number = read_8bit(head_offset+0x20,streamFile); + loop_flag = read_8bit(head_offset+0x21,streamFile); + channel_count = read_8bit(head_offset+0x22,streamFile); + + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + break; + case 1: + coding_type = coding_PCM16BE; + break; + case 2: + coding_type = coding_NGC_DSP; + break; + default: + goto fail; + } + + if (channel_count < 1) goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(head_offset+0x2c,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset+0x24,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitBE(head_offset+0x28,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_type; + if (channel_count==1) + vgmstream->layout_type = layout_none; + else + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->meta_type = meta_RSTM; + if (atlus_shrunken_head) + vgmstream->meta_type = meta_RSTM_shrunken; + + if (spm_flag&& vgmstream->sample_rate == 44100) { + vgmstream->meta_type = meta_RSTM_SPM; + vgmstream->sample_rate = 22050; + } + + vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile); + vgmstream->interleave_smallblock_size = read_32bitBE(head_offset+0x48,streamFile); + + if (vgmstream->coding_type == coding_NGC_DSP) { + off_t coef_offset; + off_t coef_offset1; + off_t coef_offset2; + int i,j; + int coef_spacing = 0x38; + + if (atlus_shrunken_head) + { + coef_offset = 0x50; + coef_spacing = 0x30; + } + else + { + coef_offset1=read_32bitBE(head_offset+0x1c,streamFile); + coef_offset2=read_32bitBE(head_offset+0x10+coef_offset1,streamFile); + coef_offset=coef_offset2+0x10; + } + + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i]=read_16bitBE(head_offset+coef_offset+j*coef_spacing+i*2,streamFile); + } + } + } + + start_offset = read_32bitBE(head_offset+0x30,streamFile); + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ilayout_type==layout_interleave_shortblock) + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + vgmstream->interleave_block_size); + else + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + 0x1000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/capdsp.c b/Frameworks/vgmstream/vgmstream/src/meta/capdsp.c new file mode 100644 index 000000000..774052f57 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/capdsp.c @@ -0,0 +1,68 @@ +#include "meta.h" +#include "../util.h" + +/* CAPDSP (found in Capcom games) */ +VGMSTREAM * init_vgmstream_capdsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("capdsp",filename_extension(filename))) goto fail; + + loop_flag = (read_32bitBE(0x14,streamFile) !=2); + channel_count = read_32bitBE(0x10,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x04,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile)/8/channel_count*14; + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)/8/channel_count*14; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x4000; + vgmstream->meta_type = meta_CAPDSP; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<8;i++) { + vgmstream->ch[0].adpcm_coef[i*2]=read_16bitBE(0x20+i*2,streamFile); + vgmstream->ch[0].adpcm_coef[i*2+1]=read_16bitBE(0x30+i*2,streamFile); + vgmstream->ch[1].adpcm_coef[i*2]=read_16bitBE(0x40+i*2,streamFile); + vgmstream->ch[1].adpcm_coef[i*2+1]=read_16bitBE(0x50+i*2,streamFile); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_asd.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_asd.c new file mode 100644 index 000000000..552eb7878 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_asd.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../util.h" + +/* ASD - found in Miss Moonlight (DC) */ +VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("asd",filename_extension(filename))) goto fail; + + /* We have no "Magic" words in this header format, so we have to do some, + other checks, it seems the samplecount is stored twice in the header, + we'll compare it... */ + if (read_32bitLE(0x0,streamFile) != read_32bitLE(0x4,streamFile)) + goto fail; + /* compare the frequency with the bitrate, if it doesn't match we'll close + the vgmstream... */ + if (read_32bitLE(0x10,streamFile)/read_32bitLE(0xC,streamFile) != (uint16_t)read_16bitLE(0xA,streamFile)*2) + goto fail; + + loop_flag = 0; + channel_count = read_16bitLE(0x0A,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = get_streamfile_size(streamFile) - read_32bitLE(0x0,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x0,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/2/channel_count; + } + + vgmstream->meta_type = meta_DC_ASD; + + if (vgmstream->channels == 1) { + vgmstream->layout_type = layout_none; + } else if (vgmstream->channels == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_dcsw_dcs.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_dcsw_dcs.c new file mode 100644 index 000000000..128c7a7d0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_dcsw_dcs.c @@ -0,0 +1,119 @@ +#include "meta.h" +#include "../util.h" + +/* WAV+DCS (DCSW+DCS) +2008-12-06 - manakoAT : Evil Twin - Cypriens Chronicles... +2008-12-07 - manakoAT : Added a function to read the Header file and for + retrieving the channels/frequency, Frequency starts + always at a "data" chunk - 0x0C bytes, Channels + always - 0x0E bytes... +2010-01-13 - manakoAT : Changed the 'Helper' extension from .wav to .dcws, to prevent conflicts */ + +VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileDCSW = NULL; + char filename[PATH_LIMIT]; + char filenameDCSW[260]; + int i; + int channel_count; + int loop_flag; + int frequency; + int dataBuffer = 0; + int Founddata = 0; + size_t file_size; + off_t current_chunk; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dcs",filename_extension(filename))) goto fail; + + /* Getting the Header file name... */ + strcpy(filenameDCSW,filename); + strcpy(filenameDCSW+strlen(filenameDCSW)-3,"dcsw"); + + /* Look if the Header file is present, else cancel vgmstream */ + streamFileDCSW = streamFile->open(streamFile,filenameDCSW,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileDCSW) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFileDCSW) != 0x52494646 || /* "RIFF" */ + read_32bitBE(0x08,streamFileDCSW) != 0x57415645 || /* "WAVE" */ + read_32bitBE(0x0C,streamFileDCSW) != 0x34582E76 || /* 0x34582E76 */ + read_32bitBE(0x3C,streamFileDCSW) != 0x406E616D) /* "@nam" */ + goto fail; + + /* scan file until we find a "data" string */ + file_size = get_streamfile_size(streamFileDCSW); + { + current_chunk = 0; + /* Start at 0 and loop until we reached the + file size, or until we found a "data string */ + while (!Founddata && current_chunk < file_size) { + dataBuffer = (read_32bitBE(current_chunk,streamFileDCSW)); + if (dataBuffer == 0x64617461) { /* "data" */ + /* if "data" string found, retrieve the needed infos */ + Founddata = 1; + /* We will cancel the search here if we have a match */ + break; + } + /* else we will increase the search offset by 1 */ + current_chunk = current_chunk + 1; + } + } + + if (Founddata == 0) { + goto fail; + } else if (Founddata == 1) { + channel_count = (uint16_t)read_16bitLE(current_chunk-0x0E,streamFileDCSW); + frequency = read_32bitLE(current_chunk-0x0C,streamFileDCSW); + } + + loop_flag = 0; + + /* Seems we're dealing with a vaild file+header, + now we can finally build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = frequency; + vgmstream->num_samples=(get_streamfile_size(streamFile))*2/channel_count; + + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile))*2/channel_count; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count > 1) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x4000; + } + + vgmstream->coding_type = coding_AICA; + vgmstream->meta_type = meta_DC_DCSW_DCS; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */ + } + } + + close_streamfile(streamFileDCSW); streamFileDCSW=NULL; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileDCSW) close_streamfile(streamFileDCSW); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c new file mode 100644 index 000000000..60df792a2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_idvi.c @@ -0,0 +1,71 @@ +#include "meta.h" +#include "../util.h" + +/* IDVI (Eldorado Gate Volume 1-7) */ +VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("idvi",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI." */ + goto fail; + + loop_flag = read_32bitLE(0x0C,streamFile); + channel_count = read_32bitLE(0x04,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + start_offset = 0x800; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_INT_DVI_IMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset); + } + vgmstream->meta_type = meta_DC_IDVI; + + /* Calculating the short block... */ + if (channel_count > 1) { + vgmstream->interleave_block_size = 0x400; + vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels; + vgmstream->layout_type = layout_interleave_shortblock; + } else { + vgmstream->layout_type = layout_none; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c new file mode 100644 index 000000000..abf9f663a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_kcey.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_kcey(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("kcey",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "DVI." */ + goto fail; + + loop_flag = (read_32bitBE(0x14,streamFile)!=0xFFFFFFFF); + channel_count = read_32bitBE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + start_offset = read_32bitBE(0x10,streamFile); + vgmstream->sample_rate = 37800; + vgmstream->coding_type = coding_EACS_IMA; + + vgmstream->num_samples = read_32bitBE(0x0C,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_KCEY; + vgmstream->get_high_nibble=1; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+(i*vgmstream->interleave_block_size); + vgmstream->ch[i].adpcm_history1_32=0; + vgmstream->ch[i].adpcm_step_index=0; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dc_str.c b/Frameworks/vgmstream/vgmstream/src/meta/dc_str.c new file mode 100644 index 000000000..9bac3c362 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dc_str.c @@ -0,0 +1,165 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* SEGA Stream Asset Builder... + this meta handles only V1 and V3... */ + +VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int interleave; + int channel_count; + int samples; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0xD5,streamFile) != 0x53656761) /* "Sega" */ + goto fail; + + interleave = read_32bitLE(0xC,streamFile); + if ((get_streamfile_size(streamFile)-0x800) != (read_32bitLE(0x10,streamFile) * + ((read_32bitLE(0x0,streamFile)*(read_32bitLE(0x18,streamFile))))*interleave)) + goto fail; + + + loop_flag = 0; /* (read_32bitLE(0x00,streamFile)!=0x00000000); */ + samples = read_32bitLE(0x08,streamFile); + channel_count = (read_32bitLE(0x0,streamFile))*(read_32bitLE(0x18,streamFile)); + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + /* fill in the vital statistics */ + switch (samples) { + case 4: + vgmstream->coding_type = coding_AICA; + vgmstream->num_samples = read_32bitLE(0x14,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile); + } + break; + case 16: + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x14,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile)/2/channel_count; + } + break; + default: + goto fail; +} + + + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + + if (vgmstream->channels == 1) { + vgmstream->layout_type = layout_none; + } else if (vgmstream->channels > 1) { + vgmstream->interleave_block_size = interleave; + vgmstream->layout_type = layout_interleave; + } + + vgmstream->meta_type = meta_DC_STR; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* This handles V2, not sure if it is really V2, cause the header is always + the same, not like in V1 and V3, only found in "102 Dalmatians - Puppies to the Rescue" + until now... */ + +VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check header */ + if ((read_32bitLE(0x00,streamFile) != 0x2)) + goto fail; + if ((read_32bitLE(0x10,streamFile) != 0x10000)) + goto fail; + if ((read_32bitLE(0x1C,streamFile) != 0x1F)) + goto fail; + + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x4,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0xC,streamFile); + vgmstream->meta_type = meta_DC_STR_V2; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/de2.c b/Frameworks/vgmstream/vgmstream/src/meta/de2.c new file mode 100644 index 000000000..83f004a7b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/de2.c @@ -0,0 +1,101 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Gurumin .de2 */ +/* A ways into the file we have a fake RIFF header wrapping MS ADPCM */ + +VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t riff_off; + int channel_count; + int sample_count; + int sample_rate; + off_t start_offset; + + int loop_flag = 0; + uint32_t data_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("de2",filename_extension(filename))) goto fail; + + /* still not sure what this is for, but consistently 0xb */ + if (read_32bitLE(0x04,streamFile)!=0xb) goto fail; + + /* legitimate! really! */ + riff_off = 0x10 + + (read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile)); + + /* check header */ + if ((uint32_t)read_32bitBE(riff_off+0,streamFile)!=0x52494646) /* "RIFF" */ + goto fail; + /* check for WAVE form */ + if ((uint32_t)read_32bitBE(riff_off+8,streamFile)!=0x57415645) /* "WAVE" */ + goto fail; + /* check for "fmt " */ + if ((uint32_t)read_32bitBE(riff_off+12,streamFile)!=0x666d7420) /* "fmt " */ + goto fail; + /* check for "data" */ + if ((uint32_t)read_32bitBE(riff_off+0x24,streamFile)!=0x64617461) /* "data" */ + goto fail; + /* check for bad fmt chunk size */ + if (read_32bitLE(riff_off+0x10,streamFile)!=0x12) goto fail; + + sample_rate = read_32bitLE(riff_off+0x18,streamFile); + + channel_count = read_16bitLE(riff_off+0x16,streamFile); + if (channel_count != 2) goto fail; + + /* PCM */ + if (read_16bitLE(riff_off+0x14,streamFile) != 1) goto fail; + + /* 16-bit */ + if (read_16bitLE(riff_off+0x20,streamFile) != 4 || + read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail; + + start_offset = riff_off + 0x2c; + data_size = read_32bitLE(riff_off+0x28,streamFile); + + sample_count = data_size/2/channel_count; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = sample_rate; + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_de2_blocked; + vgmstream->interleave_block_size = 0x800; + + vgmstream->meta_type = meta_DE2; + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + } + } + + /* start me up */ + de2_block_update(start_offset,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dmsg_segh.c b/Frameworks/vgmstream/vgmstream/src/meta/dmsg_segh.c new file mode 100644 index 000000000..5757ff1c8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dmsg_segh.c @@ -0,0 +1,110 @@ +#include "meta.h" +#include "../util.h" + +/* DMSG + found in: Nightcaster II - Equinox + 2010-01-05 (manakoAT): Seems it's a corrupted "SGT" file, but I'm not sure... + */ +VGMSTREAM * init_vgmstream_dmsg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int frequency; + int channel_count; + int dataBuffer = 0; + int Founddata = 0; + size_t file_size; + off_t current_chunk; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dmsg",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x444D5347) /* "DMSG" */ + goto fail; + if (read_32bitBE(0x0C,streamFile) != 0x73656768) /* "segh" */ + goto fail; + if (read_32bitBE(0x10,streamFile) != 0x38000000) /* "0x38" */ + goto fail; + + /* scan file until we find a "data" string */ + file_size = get_streamfile_size(streamFile); + { + current_chunk = 0; + /* Start at 0 and loop until we reached the + file size, or until we found a "data string */ + while (!Founddata && current_chunk < file_size) { + dataBuffer = (read_32bitBE(current_chunk,streamFile)); + if (dataBuffer == 0x64617461) { /* "data" */ + /* if "data" string found, retrieve the needed infos */ + Founddata = 1; + /* We will cancel the search here if we have a match */ + break; + } + /* else we will increase the search offset by 1 */ + current_chunk = current_chunk + 1; + } + } + + if (Founddata == 0) { + goto fail; + } else if (Founddata == 1) { + channel_count = (uint16_t)read_16bitLE(current_chunk-0x10,streamFile); + frequency = read_32bitLE(current_chunk-0xE,streamFile); + } + + loop_flag = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (Founddata == 0) { + goto fail; + } else if (Founddata == 1) { + start_offset = current_chunk+0x8; + vgmstream->channels = channel_count; + vgmstream->sample_rate = frequency; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (read_32bitLE(current_chunk+0x4,streamFile)/2/channel_count); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(current_chunk+0x4,streamFile)/2/channel_count); + } + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count > 1) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + vgmstream->meta_type = meta_DMSG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/dsp_bdsp.c b/Frameworks/vgmstream/vgmstream/src/meta/dsp_bdsp.c new file mode 100644 index 000000000..d71b7141b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/dsp_bdsp.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + int loop_flag; + int i; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bdsp",filename_extension(filename))) goto fail; + + channel_count = 2; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x8,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + +#if 0 + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x64,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x68,streamFile); + } +#endif + + + vgmstream->layout_type = layout_dsp_bdsp_blocked; + vgmstream->interleave_block_size = 0x8; + vgmstream->meta_type = meta_DSP_BDSP; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1C+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x7C+i*2,streamFile); + } + } + } + + /* Calc num_samples */ + start_offset = 0x0; + dsp_bdsp_block_update(start_offset,vgmstream); + vgmstream->num_samples=0; + + do + { + vgmstream->num_samples += vgmstream->current_block_size*14/8; + dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream); + } + while (vgmstream->next_block_offsetget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sth",filename_extension(filename))) goto fail; + + strcpy(filenameSTR,filename); + strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); + streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileSTR) goto fail; + + if (read_32bitBE(0x0,streamFile) != 0x0) + { + goto fail; + } + + if (read_32bitBE(0x4,streamFile) != 0x800) + { + goto fail; + } + + /* Not really channel_count, just 'included tracks * channels per track */ + loop_flag = (read_32bitBE(0xD8,streamFile) != 0xFFFFFFFF); + channel_count = (read_32bitBE(0x70,streamFile)) * (read_32bitBE(0x88,streamFile)); + + if (channel_count > 8) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x24,streamFile); + vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; + vgmstream->coding_type = coding_NGC_DSP; + + if(loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0xD8,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile); + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + if (channel_count == 2) + { + vgmstream->interleave_block_size=0x10000; + } + else + { + vgmstream->interleave_block_size=0x8000; + } + } + + vgmstream->meta_type = meta_NGC_DSP_STH_STR; + + /* open the file for reading */ + for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + + // COEFFS + for (j=0;jchannels;j++) + { + for (i=0;i<16;i++) + { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + + close_streamfile(streamFileSTR); streamFileSTR=NULL; + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileSTR) close_streamfile(streamFileSTR); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* + STH+STR + found in Taz Wanted (NGC), Cubix Robots for Everyone: Showdown (NGC) +*/ + +VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileSTR = NULL; + char filename[PATH_LIMIT]; + char filenameSTR[260]; + int i, j; + int channel_count; + int loop_flag; + off_t coef_table[8] = {0xDC,0x13C,0x19C,0x1FC,0x25C,0x2BC,0x31C,0x37C}; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sth",filename_extension(filename))) goto fail; + + strcpy(filenameSTR,filename); + strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); + streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileSTR) goto fail; + + if (read_32bitBE(0x0,streamFile) != 0x0) + { + goto fail; + } + + if (read_32bitBE(0x4,streamFile) != 0x900) + { + goto fail; + } + + /* Not really channel_count, just 'included tracks * channels per track */ + loop_flag = (read_32bitBE(0xB8,streamFile) != 0xFFFFFFFF); + channel_count = read_32bitBE(0x50,streamFile)*2; + + if (channel_count > 8) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x24,streamFile); + vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; + vgmstream->coding_type = coding_NGC_DSP; + + if(loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0xB8,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0xBC,streamFile); + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + if (channel_count == 2) + { + vgmstream->interleave_block_size=0x10000; + } + else + { + vgmstream->interleave_block_size=0x8000; + } + } + + vgmstream->meta_type = meta_NGC_DSP_STH_STR; + + /* open the file for reading */ + for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + + // COEFFS + for (j=0;jchannels;j++) + { + for (i=0;i<16;i++) + { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + + close_streamfile(streamFileSTR); streamFileSTR=NULL; + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileSTR) close_streamfile(streamFileSTR); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* + STH+STR + found in Tak and the Guardians of Gross (WII) +*/ + +VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileSTR = NULL; + char filename[PATH_LIMIT]; + char filenameSTR[260]; + int i, j; + int channel_count; + int loop_flag; + off_t coef_table[8] = {read_32bitBE(0x7C,streamFile),read_32bitBE(0x80,streamFile),read_32bitBE(0x84,streamFile),read_32bitBE(0x88,streamFile),read_32bitBE(0x8C,streamFile),read_32bitBE(0x90,streamFile),read_32bitBE(0x94,streamFile),read_32bitBE(0x98,streamFile)}; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sth",filename_extension(filename))) goto fail; + + strcpy(filenameSTR,filename); + strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); + streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileSTR) goto fail; + + if (read_32bitBE(0x0,streamFile) != 0x0) + { + goto fail; + } + + if ((read_32bitBE(0x4,streamFile) != 0x700) && + (read_32bitBE(0x4,streamFile) != 0x800)) + { + goto fail; + } + + /* Not really channel_count, just 'included tracks * channels per track */ + loop_flag = 0; + channel_count = read_32bitBE(0x70,streamFile); + + if (channel_count > 8) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x38,streamFile); + vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; + vgmstream->coding_type = coding_NGC_DSP; + + if(loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = 0; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + if (channel_count == 2 || channel_count == 4) + { + vgmstream->interleave_block_size=0x8000; + } + else + { + vgmstream->interleave_block_size=0x4000; + } + } + + vgmstream->meta_type = meta_NGC_DSP_STH_STR; + + /* open the file for reading */ + for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + + // COEFFS + for (j=0;jchannels;j++) + { + for (i=0;i<16;i++) + { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + + close_streamfile(streamFileSTR); streamFileSTR=NULL; + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileSTR) close_streamfile(streamFileSTR); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c new file mode 100644 index 000000000..0da2d047f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_header.c @@ -0,0 +1,308 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" +#include "../util.h" + +// Platform constants +#define EA_PC 0x00 +#define EA_PSX 0x01 +#define EA_PS2 0x05 +#define EA_GC 0x06 +#define EA_XBOX 0x07 +#define EA_X360 0x09 + +// Compression Version +#define EAXA_R1 0x01 +#define EAXA_R2 0x02 +#define EAXA_R3 0x03 + +// Compression Type +#define EA_VAG 0x01 +#define EA_EAXA 0x0A +#define EA_ADPCM 0x30 +#define EA_PCM_BE 0x07 +#define EA_PCM_LE 0x08 +#define EA_IMA 0x14 + +typedef struct { + int32_t num_samples; + int32_t sample_rate; + uint8_t channels; + uint8_t platform; + int32_t interleave; + uint8_t compression_type; + uint8_t compression_version; +} EA_STRUCT; + +uint32_t readPatch(STREAMFILE* streamFile, off_t* offset) { + + uint32_t result=0; + uint8_t byteCount; + + byteCount = read_8bit(*offset,streamFile); + (*offset)++; + + for(;byteCount>0;byteCount--) { + result <<=8; + result+=(uint8_t)read_8bit(*offset,streamFile); + (*offset)++; + } + return result; +} + +void Parse_Header(STREAMFILE* streamFile,EA_STRUCT* ea, off_t offset, int length) { + + uint8_t byteRead; + off_t begin_offset=offset; + + // default value ... + ea->channels=1; + ea->compression_type=0; + ea->compression_version=0x01; + ea->platform=EA_GC; + + if(read_32bitBE(offset, streamFile)==0x47535452) { // GSTR + ea->compression_version=0x03; + offset+=8; + ea->platform=6; + } else { + if(read_16bitBE(offset,streamFile)!=0x5054) // PT + offset+=4; + + ea->platform=(uint8_t)read_16bitLE(offset+2,streamFile); + offset+=4; + } + + do { + byteRead = read_8bit(offset++,streamFile); + + switch(byteRead) { + case 0xFF: + case 0xFE: + case 0xFC: + case 0xFD: + break; +#if 0 + // was added for My Sims Kingdom, apparently this is not the right + // way to do it (see NFS Most Wanted and Underground 2) + case 0x06: // + if (readPatch(streamFile, &offset) == 0x65) + ea->compression_type = EA_PCM_BE; + break; +#endif + case 0x80: // compression version + ea->compression_version = (uint8_t)readPatch(streamFile, &offset); + break; + case 0x82: // channels count + ea->channels = (uint8_t)readPatch(streamFile, &offset); + break; + case 0x83: // compression type + ea->compression_type = (uint8_t)readPatch(streamFile, &offset); + if(ea->compression_type==0x07) ea->compression_type=0x30; + break; + case 0x84: // sample frequency + ea->sample_rate = readPatch(streamFile,&offset); + break; + case 0x85: // samples count + ea->num_samples = readPatch(streamFile, &offset); + break; + case 0x8A: + offset+=4; + if(ea->compression_type==0) ea->compression_type=EA_PCM_LE; + break; + case 0x86: + case 0x87: + case 0x8C: + case 0x92: + case 0x9C: + case 0x9D: // unknown patch + readPatch(streamFile, &offset); + break; + case 0x88: // interleave + ea->interleave = readPatch(streamFile, &offset); + break; + case 0xA0: // compression type + ea->compression_type = (uint8_t)readPatch(streamFile, &offset); + break; + } + } while(offset-begin_offsetplatform==EA_PSX) + ea->compression_type=EA_VAG; + if(ea->compression_type==0) + ea->compression_type=EA_EAXA; +} + +VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + EA_STRUCT ea; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int header_length; + off_t start_offset; + int i; + + memset(&ea,0,sizeof(EA_STRUCT)); + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("strm",filename_extension(filename)) && + strcasecmp("xa",filename_extension(filename)) && + strcasecmp("sng",filename_extension(filename)) && + strcasecmp("asf",filename_extension(filename)) && + strcasecmp("str",filename_extension(filename)) && + strcasecmp("xsf",filename_extension(filename)) && + strcasecmp("eam",filename_extension(filename))) goto fail; + + /* check Header */ + if (read_32bitBE(0x00,streamFile) != 0x5343486C) // SCHl + goto fail; + + header_length = read_32bitLE(0x04,streamFile); + start_offset=8; + + if(header_length>0x100) goto fail; + + Parse_Header(streamFile,&ea,start_offset,header_length-8); + + /* unknown loop value for the moment */ + loop_flag = 0; + + channel_count=ea.channels; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->ea_platform=ea.platform; + + vgmstream->ea_compression_type=ea.compression_type; + vgmstream->ea_compression_version=ea.compression_version; + + // Set defaut sample rate if not define in the header + if(ea.sample_rate!=0) { + vgmstream->sample_rate = ea.sample_rate; + } else { + if(read_32bitBE(0x08,streamFile)==0x47535452) { // GSTR + vgmstream->sample_rate=44100; + } else { + switch(vgmstream->ea_platform) { + case EA_XBOX: + vgmstream->sample_rate=24000; + break; + case EA_X360: + vgmstream->sample_rate=44100; + break; + default: + vgmstream->sample_rate=22050; + } + } + } + + // Set default compression scheme if not define in the header + switch(vgmstream->ea_platform) { + case EA_X360: + vgmstream->ea_compression_version=0x03; + break; + } + + vgmstream->num_samples=ea.num_samples; + + switch(vgmstream->ea_compression_type) { + case EA_EAXA: + if(vgmstream->ea_compression_version==0x03) + vgmstream->meta_type=meta_EAXA_R3; + else { + // seems there's no EAXA R2 on PC + if(ea.platform==EA_PC) { + vgmstream->ea_compression_version=0x03; + vgmstream->meta_type=meta_EAXA_R3; + } else + vgmstream->meta_type=meta_EAXA_R2; + } + + vgmstream->coding_type=coding_EAXA; + vgmstream->layout_type=layout_ea_blocked; + if((vgmstream->ea_platform==EA_GC) || (vgmstream->ea_platform==EA_X360)) + vgmstream->ea_big_endian=1; + + break; + case EA_VAG: + vgmstream->meta_type=meta_EAXA_PSX; + vgmstream->coding_type=coding_PSX; + vgmstream->layout_type=layout_ea_blocked; + break; + case EA_PCM_LE: + vgmstream->meta_type=meta_EA_PCM; + vgmstream->coding_type=coding_PCM16LE_int; + vgmstream->layout_type=layout_ea_blocked; + break; + case EA_PCM_BE: + vgmstream->meta_type=meta_EA_PCM; + vgmstream->coding_type=coding_PCM16BE; + vgmstream->layout_type=layout_ea_blocked; + break; + case EA_ADPCM: + vgmstream->meta_type=meta_EA_ADPCM; + vgmstream->coding_type=coding_EA_ADPCM; + vgmstream->layout_type=layout_ea_blocked; + break; + case EA_IMA: + vgmstream->meta_type=meta_EA_IMA; + vgmstream->coding_type=coding_XBOX; + vgmstream->layout_type=layout_ea_blocked; + break; + } + + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + + // Special function for .EAM files ... + if(!strcasecmp("eam",filename_extension(filename))) { + + size_t file_length=get_streamfile_size(streamFile); + size_t block_length; + + vgmstream->next_block_offset=start_offset+header_length; + vgmstream->num_samples=0; + + // to initialize the block length + ea_block_update(start_offset+header_length,vgmstream); + block_length=vgmstream->next_block_offset-start_offset+header_length; + + do { + ea_block_update(vgmstream->next_block_offset,vgmstream); + if(vgmstream->coding_type==coding_PSX) + vgmstream->num_samples+=(int32_t)vgmstream->current_block_size/16*28; + else if (vgmstream->coding_type==coding_EA_ADPCM) + vgmstream->num_samples+=(int32_t)vgmstream->current_block_size; + else if (vgmstream->coding_type==coding_PCM16LE_int) + vgmstream->num_samples+=(int32_t)vgmstream->current_block_size/vgmstream->channels; + else + vgmstream->num_samples+=(int32_t)vgmstream->current_block_size*28; + } while(vgmstream->next_block_offset<(off_t)(file_length-block_length)); + } + + ea_block_update(start_offset+header_length,vgmstream); + + init_get_high_nibble(vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c b/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c new file mode 100644 index 000000000..d3eaa4029 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ea_old.c @@ -0,0 +1,162 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" + +typedef struct +{ + char szID[4]; + int dwSampleRate; + char bBits; + char bChannels; + char bCompression; + char bType; + int dwNumSamples; + int dwLoopStart; + int dwLoopLength; + int dwDataStart; + int dwUnknown; +} EACSHeader; + +VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + int loop_flag=0; + char little_endian=0; + off_t start_offset; + EACSHeader *ea_header = NULL; + int32_t samples_count=0; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("cnk",filename_extension(filename)) && + strcasecmp("as4",filename_extension(filename)) && + strcasecmp("asf",filename_extension(filename))) goto fail; + + ea_header=(EACSHeader *)malloc(sizeof(EACSHeader)); + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */ + goto fail; + + /* check if we are little or big endian */ + if ((uint32_t)read_32bitBE(4,streamFile)<0x40) + little_endian=1; + + /* check type details */ + start_offset = read_32bitLE(0x04,streamFile); + + if((uint32_t)read_32bitBE(0x08,streamFile)==0x45414353) { /* EACS */ + read_streamfile((uint8_t*)ea_header,0x08,sizeof(EACSHeader),streamFile); + loop_flag = 0; //(ea_header->dwLoopStart!=0); + channel_count = (ea_header->bChannels); + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + init_get_high_nibble(vgmstream); + + vgmstream->sample_rate = ea_header->dwSampleRate; + + if(ea_header->bCompression==0) { + vgmstream->coding_type = coding_PCM16LE_int; + if(ea_header->bBits==1) + vgmstream->coding_type = coding_PCM8_int; + } + else + vgmstream->coding_type = coding_EACS_IMA; + + vgmstream->layout_type = layout_eacs_blocked; + vgmstream->meta_type = meta_EACS_PC; + + if(little_endian) + vgmstream->meta_type = meta_EACS_SAT; + + } else { + channel_count=read_32bitLE(0x20,streamFile); + + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type=layout_eacs_blocked; + vgmstream->meta_type=meta_EACS_PSX; + } + + vgmstream->ea_platform=little_endian; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + // calc the samples length ... + if(little_endian) + vgmstream->next_block_offset=read_32bitBE(0x04,streamFile); + else + vgmstream->next_block_offset=read_32bitLE(0x04,streamFile); + + if(vgmstream->next_block_offset>0x30) { + vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader); + samples_count=(int32_t)vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream); + samples_count/=vgmstream->channels; + } + + do { + if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) { + ea_header->dwLoopStart=read_32bitLE(vgmstream->next_block_offset+0x08,vgmstream->ch[0].streamfile); + vgmstream->next_block_offset+=0x0C; + } + + if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E65) + break; + + eacs_block_update(vgmstream->next_block_offset,vgmstream); + samples_count+=vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream); + } while(vgmstream->next_block_offsetnext_block_offset=read_32bitBE(0x04,streamFile); + else + vgmstream->next_block_offset=read_32bitLE(0x04,streamFile); + + vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader); + + if(vgmstream->coding_type!=coding_PSX) + vgmstream->current_block_size-=8; + + if(vgmstream->coding_type==coding_PSX) + eacs_block_update(0x2C,vgmstream); + else + eacs_block_update(0x28,vgmstream); + + // re-allocate the sample count + vgmstream->num_samples=samples_count; + + if(loop_flag) { + vgmstream->loop_start_sample = ea_header->dwLoopStart; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if(ea_header) + free(ea_header); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if(ea_header) + free(ea_header); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/emff.c b/Frameworks/vgmstream/vgmstream/src/meta/emff.c new file mode 100644 index 000000000..10cb7645e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/emff.c @@ -0,0 +1,179 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* EMFF - Eidos Music File Format (PS2), +Legacy of Kain - Defiance, possibly more... */ +VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int frequency; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("emff",filename_extension(filename))) goto fail; + + /* do some checks on the file, cause we have no magic words to check the header... + it seems if 0x800 and 0x804 = 0 then the file has only audio, if 0x800 = 1 + it has a text section, if both are 1 it's video with a text section included... */ + if (read_32bitBE(0x800,streamFile) == 0x01000000 || /* "0x01000000" */ + read_32bitBE(0x804,streamFile) == 0x01000000) /* "0x01000000" */ + goto fail; + + frequency = read_32bitLE(0x0,streamFile); + channel_count = read_32bitLE(0xC,streamFile); + + if (frequency > 48000 || + channel_count > 8) { + goto fail; + } + + loop_flag = (read_32bitLE(0x4,streamFile) != 0xFFFFFFFF); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->sample_rate = frequency; + vgmstream->channels = channel_count; + vgmstream->coding_type = coding_PSX; + + vgmstream->layout_type = layout_emff_ps2_blocked; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_EMFF_PS2; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + } + } + + /* Calc num_samples */ + emff_ps2_block_update(start_offset,vgmstream); + vgmstream->num_samples = read_32bitLE(0x8,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x28,streamFile)-start_offset)*28/16/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x8,streamFile); + } + + return vgmstream; + +/* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* EMFF - Eidos Music File Format (NGC/WII), +found in Tomb Raider Legend/Anniversary/Underworld, possibly more... */ +VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int frequency; + int i; + int j; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("emff",filename_extension(filename))) goto fail; + + /* do some checks on the file, cause we have no magic words to check the header... + it seems if 0x800 and 0x804 = 0 then the file has only audio, if 0x800 = 1 + it has a text section, if both are 1 it's video with a text section included... */ + if (read_32bitBE(0x800,streamFile) == 0x00000001 || /* "0x00000001" */ + read_32bitBE(0x804,streamFile) == 0x00000001) /* "0x00000001" */ + goto fail; + + frequency = read_32bitBE(0x0,streamFile); + channel_count = read_32bitBE(0xC,streamFile); + + if (frequency > 48000 || + channel_count > 8) { + goto fail; + } + + loop_flag = (read_32bitBE(0x4,streamFile) != 0xFFFFFFFF); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->sample_rate = frequency; + vgmstream->channels = channel_count; + vgmstream->coding_type = coding_NGC_DSP; + + /* Retrieving coefs and loops, depending on the file layout... */ + /* Found in Tomb Raider - Legend for GameCube */ + if (read_32bitBE(0xC8,streamFile) > 0x0) { + off_t coef_table[8] = {0xC8,0xF6,0x124,0x152,0x180,0x1AE,0x1DC,0x20A}; + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + /* Found in Tomb Raider - Anniversary for WII */ + } else if (read_32bitBE(0xCC,streamFile) > 0x0) { + off_t coef_table[8] = {0xCC,0xFA,0x128,0x156,0x184,0x1B2,0x1E0,0x20E}; + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } +} + /* Found in Tomb Raider - Underworld for WII */ + } else if (read_32bitBE(0x2D0,streamFile) > 0x0) { + off_t coef_table[8] = {0x2D0,0x2FE,0x32C,0x35A,0x388,0x3B6,0x3E4,0x412}; + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } +} + + } else { + goto fail; + } + + vgmstream->layout_type = layout_emff_ngc_blocked; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_EMFF_NGC; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + } + } + + /* Calc num_samples */ + emff_ngc_block_update(start_offset,vgmstream); + vgmstream->num_samples = read_32bitBE(0x8,streamFile);; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x28,streamFile))*14/8/channel_count; + vgmstream->loop_end_sample = read_32bitBE(0x8,streamFile); + } + + return vgmstream; + +/* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/exakt_sc.c b/Frameworks/vgmstream/vgmstream/src/meta/exakt_sc.c new file mode 100644 index 000000000..59c05172e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/exakt_sc.c @@ -0,0 +1,54 @@ +#include "meta.h" +#include "../util.h" + +/* .SC - from Activision's EXAKT system, seen in Supercar Street Challenge */ + +VGMSTREAM * init_vgmstream_exakt_sc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t file_size; + + /* check extension, case insensitive */ + /* this is all we have to go on, SC is completely headerless */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sc",filename_extension(filename))) goto fail; + + file_size = get_streamfile_size(streamFile); + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = file_size / 2; + vgmstream->sample_rate = 48000; + + vgmstream->coding_type = coding_SASSC; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x100; + vgmstream->meta_type = meta_EXAKT_SC; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/excitebots.c b/Frameworks/vgmstream/vgmstream/src/meta/excitebots.c new file mode 100644 index 000000000..831145a04 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/excitebots.c @@ -0,0 +1,168 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* a few formats from Excitebots */ + +/* .sfx, some .sf0 - DSP and PCM */ +VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int coding_type; + + long body_size; + long header_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sfx",filename_extension(filename)) && + strcasecmp("sf0",filename_extension(filename))) + goto fail; + + /* check sizes */ + body_size = read_32bitLE(0x00,streamFile); + header_size = read_32bitLE(0x04,streamFile); + + if (body_size + header_size != get_streamfile_size(streamFile)) + goto fail; + + loop_flag = 0; + + switch (read_8bit(0x09,streamFile)) + { + case 0: + if (header_size != 0x20) + goto fail; + coding_type = coding_PCM16BE; + break; + case 1: + if (header_size != 0x80) + goto fail; + coding_type = coding_NGC_DSP; + loop_flag = 1; + break; + default: + goto fail; + } + + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = header_size; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_type; + + if (coding_NGC_DSP == coding_type) + { + vgmstream->num_samples = dsp_nibbles_to_samples(body_size*2); + + if (loop_flag) + { + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(0x30,streamFile)); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)); + } + } + else + { + vgmstream->num_samples = body_size / 2; + + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_EB_SFX; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[0].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + if (coding_NGC_DSP == coding_type) + { + int i; + for (i = 0; i < 16; i++) + { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* .sf0 - PCM (degenerate stereo .sfx?) */ +VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + long file_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sf0",filename_extension(filename))) + goto fail; + + /* no header, check file size and go on faith */ + file_size = get_streamfile_size(streamFile); + if (file_size % 0x8000) + goto fail; + + channel_count = 2; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->sample_rate = 32000; + vgmstream->num_samples = file_size / 4; + vgmstream->coding_type = coding_PCM16BE; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_EB_SF0; + vgmstream->interleave_block_size = 0x4000; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset = vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* don't know what to do about .sng and .sn0 */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ffw.c b/Frameworks/vgmstream/vgmstream/src/meta/ffw.c new file mode 100644 index 000000000..cc2d0a267 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ffw.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* FFW (from Freedom Fighters [NGC]) */ +VGMSTREAM * init_vgmstream_ffw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ffw",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x11C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x130; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10C,streamFile); + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10000; + } + + vgmstream->meta_type = meta_FFW; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/fsb.c b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c new file mode 100644 index 000000000..6d8795785 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/fsb.c @@ -0,0 +1,837 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* FSB1 */ +VGMSTREAM * init_vgmstream_fsb1(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + /* int fsb1_included_files; */ + int fsb1_format; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x46534231) /* "FSB1" */ + goto fail; + + /* "Check if the FSB is used as + conatiner or as single file" */ + if (read_32bitBE(0x04,streamFile) != 0x01000000) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* This will be tricky ;o) */ + fsb1_format = read_32bitBE(0x44,streamFile); + switch (fsb1_format) { + case 0x40008800: /* PS2 (Operation Genesis) */ + case 0x41008800: /* PS2 (Operation Genesis) */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->num_samples = (read_32bitLE(0x34,streamFile))*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile); + } + break; + default: + goto fail; + + } + /* fill in the vital statistics */ + start_offset = 0x50; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x38,streamFile); + vgmstream->meta_type = meta_FSB1; + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* FSB3.0 and FSB3.1 */ +VGMSTREAM * init_vgmstream_fsb3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int fsb_headerlen; + int channel_count; + int loop_flag = 0; + int FSBFlag = 0; + int i, c; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + + if (strcasecmp("fsb",filename_extension(filename))) + goto fail; + + /* check header for "FSB3" string */ + if (read_32bitBE(0x00,streamFile) != 0x46534233) + goto fail; + + /* "Check if the FSB is used as conatiner or as single file" */ + if (read_32bitLE(0x04,streamFile) != 0x1) + goto fail; + + /* Check if we're dealing with a FSB3.0 file */ + if ((read_32bitBE(0x10,streamFile) != 0x00000300) && + ((read_32bitBE(0x10,streamFile) != 0x01000300))) + goto fail; + + channel_count = read_16bitLE(0x56,streamFile); + fsb_headerlen = read_32bitLE(0x08,streamFile); + + FSBFlag = read_32bitLE(0x48,streamFile); + + if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) + loop_flag = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + start_offset = fsb_headerlen+0x18; + vgmstream->sample_rate = (read_32bitLE(0x4C, streamFile)); + + + // Get the Decoder + if (FSBFlag&0x00000100) + { // Ignore format and treat as RAW PCM + vgmstream->coding_type = coding_PCM16LE; + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + } + else if (FSBFlag&0x00400000) + { // XBOX IMA + vgmstream->coding_type = coding_XBOX; + vgmstream->layout_type = layout_none; + } + else if (FSBFlag&0x00800000) + { // PS2 ADPCM + vgmstream->coding_type = coding_PSX; + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + } + } + else if (FSBFlag&0x02000000) + { // Nintendo DSP + vgmstream->coding_type = coding_NGC_DSP; + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 2; + } + // read coeff(s), DSP only + for (c=0;cch[c].adpcm_coef[i]=read_16bitBE(0x68+c*0x2e +i*2,streamFile); + } + } + } + else goto fail; + + vgmstream->num_samples = read_32bitLE(0x38,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x40,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x44,streamFile); + } + + + if (read_32bitBE(0x10,streamFile) == 0x00000300) + { + vgmstream->meta_type = meta_FSB3_0; + } + else if (read_32bitBE(0x10,streamFile) == 0x01000300) + { + vgmstream->meta_type = meta_FSB3_1; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + if (vgmstream->coding_type == coding_XBOX) { + /* xbox interleaving is a little odd */ + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* FSB4 */ +VGMSTREAM * init_vgmstream_fsb4(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int fsb4_format; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename)) && + strcasecmp("wii",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x46534234) /* "FSB4" */ + goto fail; + + /* "Check if the FSB is used as + conatiner or as single file" */ + if (read_32bitBE(0x04,streamFile) != 0x01000000) + goto fail; + + if (read_32bitBE(0x60,streamFile) == 0x40008800 || + read_32bitBE(0x60,streamFile) == 0x40000802 || + read_32bitBE(0x60,streamFile) == 0x40100802 || + read_32bitBE(0x60,streamFile) == 0x000040A0 || + read_32bitBE(0x60,streamFile) == 0x40004020) { + loop_flag = 1; + } else { + loop_flag = 0; + } + +#if 0 + if (read_32bitBE(0x60,streamFile) != 0x20000882 && + read_32bitBE(0x60,streamFile) != 0x20100002 && + read_32bitBE(0x60,streamFile) != 0x20100882 && + read_32bitBE(0x60,streamFile) != 0x20100802 && + read_32bitBE(0x60,streamFile) != 0x20100082 && + read_32bitBE(0x60,streamFile) != 0x20000802) { + channel_count = 2; + } else { + channel_count = 1; + } +#endif + + channel_count = (uint16_t)read_16bitLE(0x6E,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x64,streamFile); + fsb4_format = read_32bitBE(0x60,streamFile); + switch (fsb4_format) { + /* PC Blade Kitten */ + case 0x40004020: + case 0x20004000: + case 0x00004020: + case 0x000040A0: + vgmstream->coding_type = coding_MS_IMA; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x24*vgmstream->channels; + vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/0x24/vgmstream->channels)*((0x24-4)*2); + //vgmstream->num_samples = read_32bitLE(0x50,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x5C,streamFile); + } + break; + /* PS2 (Spider Man - Web of Shadows), Speed Racer */ + case 0x40008800: + case 0x20008800: // Silent Hill: Shattered Memories + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->num_samples = (read_32bitLE(0x54,streamFile))*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); + } + break; + /* de Blob 2*/ + case 0x00000886: + /* WII (de Blob, Night at the Museum) */ + case 0x40000802: + case 0x40000882: + case 0x40100802: + case 0x40200802: + case 0x00000802: + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); + } + + if (read_32bitLE(0x14,streamFile)==0x20 || + read_32bitLE(0x14,streamFile)==0x22 || + read_32bitLE(0x14,streamFile)==0x00) + { + /* Night at the Museum */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 2; + } + else if (read_32bitLE(0x14,streamFile)==0x10 || + read_32bitLE(0x14,streamFile)==0x30) + { + /* de Blob, NatM sfx */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = read_32bitLE(0x54,streamFile)/channel_count; + } + else if (read_32bitLE(0x14,streamFile)==0x40) { + /* M. Night Shamylan The Last Airbender */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 2; + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); + } + } + else goto fail; + + vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/8/channel_count*14); + break; + + /* Night at the Museum */ + case 0x20000882: + case 0x20000802: + case 0x20100002: + case 0x20100882: + case 0x20100802: + case 0x20100082: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = (read_32bitLE(0x54,streamFile)/8/channel_count*14); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x50,streamFile); + } + break; + + /* Rocket Knight (PC) */ + case 0x10000000: /* Dead Space (iOS) */ + case 0x50210000: + case 0x30210000: + case 0x30011000: + case 0x20005000: + case 0x30011080: + case 0x30211000: + case 0x40005020: + case 0x20204000: + case 0x40204020: + case 0x50011000: + case 0x20205000: + case 0x30610080: + case 0x50210080: /* Another Century's Episode R (PS3) */ + case 0x50010800: /* Toy Story 3 (PS3) */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->num_samples = (read_32bitLE(0x5C,streamFile)); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x58,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x5C,streamFile); + } + break; + default: + goto fail; + } + + start_offset = read_32bitLE(0x08,streamFile)+0x30; + + vgmstream->meta_type = meta_FSB4; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int c,i; + for (c=0;cch[c].adpcm_coef[i] = + read_16bitBE(0x80+c*0x2e + i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + if (vgmstream->coding_type == coding_MS_IMA) { + // both IMA channels work with same bytes + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* FSB4 with "WAV" Header, found in "Deadly Creatures (WII)" + 16 byte "WAV" header which holds the filesize...*/ +VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + int fsb_headerlength; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00574156) /* 0x0\"WAV" */ + goto fail; + if (read_32bitBE(0x10,streamFile) != 0x46534234) /* "FSB4" */ + goto fail; + + channel_count = (uint16_t)read_16bitLE(0x7E,streamFile); + + if (channel_count > 2) { + goto fail; + } + + loop_flag = (read_32bitBE(0x70,streamFile) == 0x40000802); + fsb_headerlength = read_32bitLE(0x18,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = fsb_headerlength + 0x40; + vgmstream->sample_rate = read_32bitLE(0x74,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 0x2; + vgmstream->num_samples = (read_32bitLE(0x64,streamFile)/8/channel_count*14); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x60,streamFile); + } + + vgmstream->meta_type = meta_FSB4_WAV; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x90+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xBE + i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +// FSB3 & FSB4 MPEG TEST +VGMSTREAM * init_vgmstream_fsb_mpeg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count, channels, encoding, loop_flag, fsb_mainheader_len, fsb_subheader_len, FSBFlag; + long sample_rate = 0, num_samples = 0, rate; + uint16_t mp3ID; + +#ifdef VGM_USE_MPEG + mpeg_codec_data *mpeg_data = NULL; + coding_t mpeg_coding_type = coding_MPEG1_L3; +#endif + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) == 0x46534233) /* "FSB3" */ + { + fsb_mainheader_len = 0x18; + } + else if (read_32bitBE(0x00,streamFile) == 0x46534234) /* "FSB4" */ + { + fsb_mainheader_len = 0x30; + } + else + { + goto fail; + } + + fsb_subheader_len = read_16bitLE(fsb_mainheader_len,streamFile); + + /* "Check if the FSB is used as conatiner or as single file" */ + if (read_32bitBE(0x04,streamFile) != 0x01000000) + goto fail; + +#if 0 + /* Check channel count, multi-channel not supported and will be refused */ + if ((read_16bitLE(0x6E,streamFile) != 0x2) && + (read_16bitLE(0x6E,streamFile) != 0x1)) + goto fail; +#endif + + start_offset = fsb_mainheader_len+fsb_subheader_len+0x10; + + /* Check the MPEG Sync Header */ + mp3ID = read_16bitLE(start_offset,streamFile); + if (mp3ID&0x7FF != 0x7FF) + goto fail; + + channel_count = read_16bitLE(fsb_mainheader_len+0x3E,streamFile); + if (channel_count != 1 && channel_count != 2) + goto fail; + + FSBFlag = read_32bitLE(fsb_mainheader_len+0x30,streamFile); + if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) + loop_flag = 1; + + num_samples = (read_32bitLE(fsb_mainheader_len+0x2C,streamFile)); + +#ifdef VGM_USE_MPEG + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels + if (!mpeg_data) goto fail; + + //channel_count = channels; + sample_rate = rate; + +#else + // reject if no MPEG support + goto fail; +#endif + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->channels = channel_count; + + /* Still WIP */ + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(fsb_mainheader_len+0x28,streamFile); + vgmstream->loop_end_sample = read_32bitLE(fsb_mainheader_len+0x2C,streamFile); + } + vgmstream->meta_type = meta_FSB_MPEG; + +#ifdef VGM_USE_MPEG + /* NOTE: num_samples seems to be quite wrong for MPEG */ + vgmstream->codec_data = mpeg_data; + vgmstream->layout_type = layout_mpeg; + vgmstream->coding_type = mpeg_coding_type; +#else + // reject if no MPEG support + goto fail; +#endif + + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/960*1152; + vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/960*1152; + } +#endif + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + if(vgmstream->layout_type == layout_interleave) + { + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + +#ifdef VGM_USE_MPEG + else if(vgmstream->layout_type == layout_mpeg) { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); + vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; + } + + } +#endif + else { goto fail; } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: +#ifdef VGM_USE_MPEG + if (mpeg_data) { + mpg123_delete(mpeg_data->m); + free(mpeg_data); + + if (vgmstream) { + vgmstream->codec_data = NULL; + } + } +#endif + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +// FSB5 MPEG +VGMSTREAM * init_vgmstream_fsb5_mpeg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count, channels, encoding, loop_flag, fsb_mainheader_len, fsb_subheader_len, FSBFlag; + long sample_rate = 0, num_samples = 0, rate; + uint16_t mp3ID; + +#ifdef VGM_USE_MPEG + mpeg_codec_data *mpeg_data = NULL; + coding_t mpeg_coding_type = coding_MPEG1_L3; +#endif + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fsb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) == 0x46534235) /* "FSB5" */ + { + fsb_mainheader_len = 0x3C; + } + else + { + goto fail; + } + + //fsb_subheader_len = read_16bitLE(fsb_mainheader_len,streamFile); + + /* "Check if the FSB is used as conatiner or as single file" */ + if (read_32bitBE(0x04,streamFile) != 0x01000000) + goto fail; + +#if 0 + /* Check channel count, multi-channel not supported and will be refused */ + if ((read_16bitLE(0x6E,streamFile) != 0x2) && + (read_16bitLE(0x6E,streamFile) != 0x1)) + goto fail; +#endif + + start_offset = fsb_mainheader_len+fsb_subheader_len+0x10; + + /* Check the MPEG Sync Header */ + mp3ID = read_16bitLE(start_offset,streamFile); + if (mp3ID&0x7FF != 0x7FF) + goto fail; + + channel_count = read_16bitLE(fsb_mainheader_len+0x3E,streamFile); + if (channel_count != 1 && channel_count != 2) + goto fail; + + FSBFlag = read_32bitLE(fsb_mainheader_len+0x30,streamFile); + if (FSBFlag&0x2 || FSBFlag&0x4 || FSBFlag&0x6) + loop_flag = 1; + + num_samples = (read_32bitLE(fsb_mainheader_len+0x2C,streamFile)); + +#ifdef VGM_USE_MPEG + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels + if (!mpeg_data) goto fail; + + //channel_count = channels; + sample_rate = rate; + +#else + // reject if no MPEG support + goto fail; +#endif + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->channels = channel_count; + + /* Still WIP */ + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(fsb_mainheader_len+0x28,streamFile); + vgmstream->loop_end_sample = read_32bitLE(fsb_mainheader_len+0x2C,streamFile); + } + vgmstream->meta_type = meta_FSB_MPEG; + +#ifdef VGM_USE_MPEG + /* NOTE: num_samples seems to be quite wrong for MPEG */ + vgmstream->codec_data = mpeg_data; + vgmstream->layout_type = layout_mpeg; + vgmstream->coding_type = mpeg_coding_type; +#else + // reject if no MPEG support + goto fail; +#endif + + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/960*1152; + vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/960*1152; + } +#endif + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + if(vgmstream->layout_type == layout_interleave) + { + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + +#ifdef VGM_USE_MPEG + else if(vgmstream->layout_type == layout_mpeg) { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); + vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; + } + + } +#endif + else { goto fail; } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: +#ifdef VGM_USE_MPEG + if (mpeg_data) { + mpg123_delete(mpeg_data->m); + free(mpeg_data); + + if (vgmstream) { + vgmstream->codec_data = NULL; + } + } +#endif + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gca.c b/Frameworks/vgmstream/vgmstream/src/meta/gca.c new file mode 100644 index 000000000..f48f9014d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/gca.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* GCA (from Metal Slug Anthology [Wii]) */ +VGMSTREAM * init_vgmstream_gca(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count = 1; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gca",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x47434131) /* "GCA1" */ + goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x2A,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x26,streamFile)*7/8; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x26,streamFile)*7/8; + } + + /* We have no interleave, so we have no layout */ + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_GCA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + /*Retrieving the coef table */ + { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x04+i*2,streamFile); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gcsw.c b/Frameworks/vgmstream/vgmstream/src/meta/gcsw.c new file mode 100644 index 000000000..92690ec64 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/gcsw.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_gcsw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gcw",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x47435357) /* "GCSW" */ + goto fail; + + /* check type details */ + /* guess */ + loop_flag = read_32bitBE(0x1c,streamFile); + channel_count = read_32bitBE(0xc,streamFile); + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x10,streamFile); + vgmstream->sample_rate = read_32bitBE(0x8,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); + + vgmstream->coding_type = coding_PCM16BE; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_GCSW; + + vgmstream->interleave_block_size = 0x8000; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + 0x20+0x8000*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c new file mode 100644 index 000000000..83fbe5b29 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/genh.c @@ -0,0 +1,345 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" +#ifdef VGM_USE_MPEG +#include +#endif + +/* GENH is an artificial "generic" header for headerless streams */ + +VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + + int32_t channel_count; + int32_t interleave; + int32_t sample_rate; + int32_t loop_start; + int32_t loop_end; + int32_t start_offset; + int32_t header_size; + int32_t coef[2]; + int32_t coef_splitted[2]; + int32_t dsp_interleave_type; + int32_t coef_type; + + char filename[PATH_LIMIT]; + int coding; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("genh",filename_extension(filename))) goto fail; + + /* check header magic */ + if (read_32bitBE(0x0,streamFile) != 0x47454e48) goto fail; + + /* check channel count (needed for ADP/DTK check) */ + channel_count = read_32bitLE(0x4,streamFile); + if (channel_count < 1) goto fail; + + /* check format */ + /* 0 = PSX ADPCM */ + /* 1 = XBOX IMA ADPCM */ + /* 2 = NGC ADP/DTK ADPCM */ + /* 3 = 16bit big endian PCM */ + /* 4 = 16bit little endian PCM */ + /* 5 = 8bit PCM */ + /* 6 = SDX2 */ + /* 7 = DVI IMA */ + /* 8 = MPEG-1 Layer III, possibly also the MPEG-2 and 2.5 extensions */ + /* 9 = IMA */ + /* 10 = AICA ADPCM */ + /* 11 = MS ADPCM */ + /* 12 = NGC DSP */ + /* 13 = 8bit unsingned PCM */ + /* 14 = PSX ADPCM (bad flagged) */ + /* 15 = Microsoft IMA (MS ADPCM) + /* 16 = 8-bit PCM (unsigned) + /* 17 = Apple Quicktime 4-bit IMA ADPCM; + /* ... others to come */ + switch (read_32bitLE(0x18,streamFile)) { + case 0: + coding = coding_PSX; + break; + case 1: + coding = coding_XBOX; + break; + case 2: + coding = coding_NGC_DTK; + if (channel_count != 2) goto fail; + break; + case 3: + coding = coding_PCM16BE; + break; + case 4: + coding = coding_PCM16LE; + break; + case 5: + coding = coding_PCM8; + break; + case 6: + coding = coding_SDX2; + break; + case 7: + coding = coding_DVI_IMA; + break; +#ifdef VGM_USE_MPEG + case 8: + /* we say MPEG-1 L3 here, but later find out exactly which */ + coding = coding_MPEG1_L3; + break; +#endif + case 9: + coding = coding_IMA; + break; + case 10: + coding = coding_AICA; + break; + case 11: + coding = coding_MSADPCM; + break; + case 12: + coding = coding_NGC_DSP; + break; + case 13: + coding = coding_PCM8_U_int; + break; + case 14: + coding = coding_PSX_badflags; + break; + case 15: + coding = coding_MS_IMA; + break; + case 16: + coding = coding_PCM8_U; + break; + case 17: + coding = coding_APPLE_IMA4; + break; + default: + goto fail; + } + + start_offset = read_32bitLE(0x1C,streamFile); + header_size = read_32bitLE(0x20,streamFile); + + /* HACK to support old genh */ + if (header_size == 0) { + start_offset = 0x800; + header_size = 0x800; + } + + /* check for audio data start past header end */ + if (header_size > start_offset) goto fail; + + interleave = read_32bitLE(0x8,streamFile); + sample_rate = read_32bitLE(0xc,streamFile); + loop_start = read_32bitLE(0x10,streamFile); + loop_end = read_32bitLE(0x14,streamFile); + + coef[0] = read_32bitLE(0x24,streamFile); + coef[1] = read_32bitLE(0x28,streamFile); + dsp_interleave_type = read_32bitLE(0x2C,streamFile); + coef_type = read_32bitLE(0x30,streamFile); /* 0 - normal coefs + 1 - splitted coefs (16byte rows) */ + coef_splitted[0] = read_32bitLE(0x34,streamFile); + coef_splitted[1] = read_32bitLE(0x38,streamFile); + //if (coding == coding_XBOX && channel_count != 2) goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,(loop_start!=-1)); + if (!vgmstream) goto fail; + + /* fill in the vital information */ + + vgmstream->channels = channel_count; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = loop_end; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + vgmstream->loop_flag = (loop_start != -1); + + switch (coding) { + case coding_PCM8_U_int: + vgmstream->layout_type=layout_none; + break; + case coding_PCM16LE: + case coding_PCM16BE: + case coding_PCM8: + case coding_PCM8_U: + case coding_SDX2: + case coding_PSX: + case coding_PSX_badflags: + case coding_DVI_IMA: + case coding_IMA: + case coding_AICA: + case coding_APPLE_IMA4: + vgmstream->interleave_block_size = interleave; + if (channel_count > 1) + { + if (coding == coding_SDX2) { + coding = coding_SDX2_int; + vgmstream->coding_type = coding_SDX2_int; + } + if(vgmstream->interleave_block_size==0xffffffff) + vgmstream->layout_type=layout_none; + else { + vgmstream->layout_type = layout_interleave; + if(coding==coding_DVI_IMA) + coding=coding_INT_DVI_IMA; + if(coding==coding_IMA) + coding=coding_INT_IMA; + } + } else { + vgmstream->layout_type = layout_none; + } + break; + case coding_MS_IMA: + vgmstream->interleave_block_size = interleave; + vgmstream->layout_type = layout_none; + break; + case coding_MSADPCM: + if (channel_count != 2) goto fail; + vgmstream->interleave_block_size = interleave; + vgmstream->layout_type = layout_none; + break; + case coding_XBOX: + vgmstream->layout_type = layout_none; + break; + case coding_NGC_DTK: + vgmstream->layout_type = layout_dtk_interleave; + break; + case coding_NGC_DSP: + if (dsp_interleave_type == 0) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + } else if (dsp_interleave_type == 1) { + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = interleave; + } else if (dsp_interleave_type == 2) { + vgmstream->layout_type = layout_none; + } + break; + +#ifdef VGM_USE_MPEG + case coding_MPEG1_L3: + vgmstream->layout_type = layout_mpeg; + break; +#endif + } + + vgmstream->coding_type = coding; + vgmstream->meta_type = meta_GENH; + + /* open the file for reading by each channel */ + { + int i; + int j; + + STREAMFILE * chstreamfile = NULL; + + for (i=0;ich[i].adpcm_step_index = 0x7f; + } + if (vgmstream->layout_type == layout_interleave) { + if (interleave >= 512) { + chstreamfile = + streamFile->open(streamFile,filename,interleave); + } else { + if (!chstreamfile) + chstreamfile = + streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + } + chstart_offset = + start_offset+vgmstream->interleave_block_size*i; + } else { + chstreamfile = + streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + } + break; + case coding_XBOX: + case coding_MSADPCM: + case coding_MS_IMA: + /* xbox's "interleave" is a lie, all channels start at same + * offset */ + chstreamfile = + streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + break; + case coding_NGC_DTK: + if (!chstreamfile) + chstreamfile = + streamFile->open(streamFile,filename,32*0x400); + break; + case coding_NGC_DSP: + if (!chstreamfile) + chstreamfile = + streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (coef_type == 0) { + for (j=0;j<16;j++) { + vgmstream->ch[i].adpcm_coef[j] = read_16bitBE(coef[i]+j*2,streamFile); + } + } else if (coef_type == 1) { + for (j=0;j<8;j++) { + vgmstream->ch[i].adpcm_coef[j*2]=read_16bitBE(coef[i]+j*2,streamFile); + vgmstream->ch[i].adpcm_coef[j*2+1]=read_16bitBE(coef_splitted[i]+j*2,streamFile); + } + } + chstart_offset =start_offset+vgmstream->interleave_block_size*i; + break; + +#ifdef VGM_USE_MPEG + case coding_MPEG1_L3: + if (!chstreamfile) + chstreamfile = + streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); + break; +#endif + } + + if (!chstreamfile) goto fail; + + vgmstream->ch[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=chstart_offset; + } + } + +#ifdef VGM_USE_MPEG + if (coding == coding_MPEG1_L3) { + vgmstream->codec_data = init_mpeg_codec_data(vgmstream->ch[0].streamfile, start_offset, vgmstream->sample_rate, vgmstream->channels, &(vgmstream->coding_type), NULL, NULL); + if (!vgmstream->codec_data) goto fail; + } +#endif + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c b/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c new file mode 100644 index 000000000..b54ce2c71 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/gh3_bar.c @@ -0,0 +1,182 @@ +#include "meta.h" + +// Guitar Hero III Mobile .bar + +enum {BAR_KEY_LENGTH = 16}; + +// don't know if this is unique, but seems accurate +static const uint8_t bar_key[BAR_KEY_LENGTH] = + {0xbd,0x14,0x0e,0x0a,0x91,0xeb,0xaa,0xf6, + 0x11,0x44,0x17,0xc2,0x1c,0xe4,0x66,0x80}; + +typedef struct _BARSTREAM +{ + STREAMFILE sf; + STREAMFILE *real_file; +} BARSTREAM; + +STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file); + +VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + // don't close, this is just the source streamFile wrapped + STREAMFILE* streamFileBAR = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + off_t ch2_start_offset; + int loop_flag; + int channel_count; + long file_size; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bar",filename_extension(filename))) goto fail; + + /* decryption wrapper for header reading */ + streamFileBAR = wrap_bar_STREAMFILE(streamFile); + if (!streamFileBAR) goto fail; + + file_size = get_streamfile_size(streamFileBAR); + + /* check header */ + if (read_32bitBE(0x00,streamFileBAR) != 0x11000100 || + read_32bitBE(0x04,streamFileBAR) != 0x01000200) goto fail; + if (read_32bitLE(0x50,streamFileBAR) != file_size) goto fail; + + start_offset = read_32bitLE(0x18,streamFileBAR); + if (0x54 != start_offset) goto fail; + ch2_start_offset = read_32bitLE(0x48,streamFileBAR); + if (ch2_start_offset >= file_size) goto fail; + + /* build the VGMSTREAM */ + channel_count = 2; + loop_flag = 0; + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = 11025; + vgmstream->coding_type = coding_IMA; + vgmstream->num_samples = (file_size-ch2_start_offset)*2; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_GH3_BAR; + + { + STREAMFILE *file1, *file2; + file1 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file1) goto fail; + file2 = streamFileBAR->open(streamFileBAR,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file2) + { + close_streamfile(file1); + goto fail; + } + vgmstream->ch[0].streamfile = file1; + vgmstream->ch[1].streamfile = file2; + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=ch2_start_offset; + } + + // discard our decrypt wrapper, without closing the original streamfile + free(streamFileBAR); + + return vgmstream; +fail: + if (streamFileBAR) + free(streamFileBAR); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +static size_t read_bar(BARSTREAM *streamFile, uint8_t *dest, off_t offset, size_t length) +{ + off_t i; + size_t read_length = + streamFile->real_file->read(streamFile->real_file, dest, offset, length); + + for (i = 0; i < read_length; i++) + { + dest[i] = dest[i] ^ bar_key[(i+offset)%BAR_KEY_LENGTH]; + } + + return read_length; +} + +static size_t get_size_bar(BARSTREAM *streamFile) +{ + return streamFile->real_file->get_size(streamFile->real_file); +} + +static size_t get_offset_bar(BARSTREAM *streamFile) +{ + return streamFile->real_file->get_offset(streamFile->real_file); +} + +static void get_name_bar(BARSTREAM *streamFile, char *name, size_t length) +{ + return streamFile->real_file->get_name(streamFile->real_file, name, length); +} + +static void get_realname_bar(BARSTREAM *streamFile, char *name, size_t length) +{ + return streamFile->real_file->get_realname(streamFile->real_file, name, length); +} + +STREAMFILE *open_bar(BARSTREAM *streamFile, const char * const filename, size_t buffersize) +{ + STREAMFILE *newfile = streamFile->real_file->open( + streamFile->real_file,filename,buffersize); + if (!newfile) + return NULL; + + return wrap_bar_STREAMFILE(newfile); +} + +static void close_bar(BARSTREAM *streamFile) +{ + streamFile->real_file->close(streamFile->real_file); + free(streamFile); + return; +} + +#ifdef PROFILE_STREAMFILE +size_t get_bytes_read_bar(BARSTREAM *streamFile) +{ + return streamFile->real_file->get_bytes_read(streamFile->real_file); +} + +int (*get_error_count)(BARSTREAM *streamFile) +{ + return streamFile->real_file->get_error_count(streamFile->real_file); +} +#endif + +STREAMFILE *wrap_bar_STREAMFILE(STREAMFILE *file) +{ + BARSTREAM *streamfile = malloc(sizeof(BARSTREAM)); + + if (!streamfile) + return NULL; + + memset(streamfile, 0, sizeof(BARSTREAM)); + + streamfile->sf.read = (void*)read_bar; + streamfile->sf.get_size = (void*)get_size_bar; + streamfile->sf.get_offset = (void*)get_offset_bar; + streamfile->sf.get_name = (void*)get_name_bar; + streamfile->sf.get_realname = (void*)get_realname_bar; + streamfile->sf.open = (void*)open_bar; + streamfile->sf.close = (void*)close_bar; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = get_bytes_read_bar; + streamfile->sf.get_error_count = get_error_count_bar; +#endif + + streamfile->real_file = file; + + return &streamfile->sf; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c new file mode 100644 index 000000000..6847b88c5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/gsp_gsb.c @@ -0,0 +1,112 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* GSP+GSB - 2008-11-28 - manakoAT +Super Swing Golf 1 & 2 (WII) */ +VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileGSP = NULL; + char filename[PATH_LIMIT]; + char filenameGSP[260]; + int channel_count; + int loop_flag; + int header_len; + int i; + off_t coef1_start; + off_t coef2_start; + off_t start_offset; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gsb",filename_extension(filename))) goto fail; + + + strcpy(filenameGSP,filename); + strcpy(filenameGSP+strlen(filenameGSP)-3,"gsp"); + + streamFileGSP = streamFile->open(streamFile,filenameGSP,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileGSP) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFileGSP) != 0x47534E44) /* "GSND" */ + goto fail; + + channel_count = (uint16_t)read_16bitBE(0x3A,streamFileGSP); + loop_flag = (read_32bitBE(0x64,streamFileGSP) != 0xFFFFFFFF); + header_len = read_32bitBE(0x1C,streamFileGSP); + + coef1_start = header_len-0x4C; + coef2_start = header_len-0x1C; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x34,streamFileGSP); + vgmstream->coding_type = coding_NGC_DSP; + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x64,streamFileGSP); + vgmstream->loop_end_sample = read_32bitBE(0x68,streamFileGSP); + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_gsb_blocked; + } else if (channel_count > 1) { + vgmstream->layout_type = layout_gsb_blocked; + vgmstream->interleave_block_size = read_32bitBE(header_len-0x64,streamFileGSP); + } + + vgmstream->meta_type = meta_GSP_GSB; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFileGSP); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFileGSP); + } + } + } + + /* Calc num_samples */ + start_offset = 0x0; + gsb_block_update(start_offset,vgmstream); + vgmstream->num_samples=0; + + do { + + vgmstream->num_samples += vgmstream->current_block_size*14/8; + gsb_block_update(vgmstream->next_block_offset,vgmstream); + } while (vgmstream->next_block_offsetget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("hps",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x2048414C || /* " HAL" */ + read_32bitBE(4,streamFile)!=0x50535400) /* "PST\0" */ + goto fail; + + /* details */ + channel_count = read_32bitBE(0xc,streamFile); + max_block = read_32bitBE(0x10,streamFile)/channel_count; + + if (channel_count != 1 && channel_count != 2) goto fail; + + /* yay for redundancy, gives us something to test */ + samples_l = dsp_nibbles_to_samples(read_32bitBE(0x18,streamFile))+1; + if (channel_count == 2) { + samples_r = dsp_nibbles_to_samples(read_32bitBE(0x50,streamFile))+1; + + if (samples_l != samples_r) goto fail; + } + + /* + * looping info is implicit in the "next block" field of the final + * block, so we have to find that + */ + { + off_t offset = 0x80, last_offset = 0; + off_t loop_offset; + + /* determine if there is a loop */ + while (offset > last_offset) { + last_offset = offset; + offset = read_32bitBE(offset+8,streamFile); + } + if (offset < 0) loop_flag = 0; + else { + /* one more pass to determine start sample */ + int32_t start_nibble = 0; + loop_flag = 1; + + loop_offset = offset; + offset = 0x80; + while (offset != loop_offset) { + start_nibble += read_32bitBE(offset,streamFile); + offset = read_32bitBE(offset+8,streamFile); + } + + start_sample = dsp_nibbles_to_samples(start_nibble); + } + + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = samples_l; + vgmstream->sample_rate = read_32bitBE(8,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + if (loop_flag) { + vgmstream->loop_start_sample = start_sample; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_halpst_blocked; + vgmstream->meta_type = meta_HALPST; + + /* load decode coefs */ + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); + if (channel_count == 2) + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x58+i*2,streamFile); + } + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename, + (i==0? + max_block+0x20: /* first buffer a bit bigger to + read block header without + inefficiency */ + max_block + ) + ); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* start me up */ + halpst_block_update(0x80,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/his.c b/Frameworks/vgmstream/vgmstream/src/meta/his.c new file mode 100644 index 000000000..63e2b2c2b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/his.c @@ -0,0 +1,112 @@ +#include "meta.h" +#include "../util.h" + +/* Her Interactive Sound .his (Nancy Drew) */ +/* A somewhat transformed RIFF WAVE */ + +VGMSTREAM * init_vgmstream_his(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + int loop_flag = 0; + int bps = 0; + off_t start_offset; + const uint8_t header_magic_expected[0x16] = "Her Interactive Sound\x1a"; + uint8_t header_magic[0x16]; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("his",filename_extension(filename))) goto fail; + + /* check header magic */ + if (0x16 != streamFile->read(streamFile, header_magic, 0, 0x16)) goto fail; + if (memcmp(header_magic_expected, header_magic, 0x16)) goto fail; + + /* data chunk label */ + if (0x64617461 != read_32bitBE(0x24,streamFile)) goto fail; + + start_offset = 0x2c; + + channel_count = read_16bitLE(0x16,streamFile); + + /* 8-bit or 16-bit expected */ + switch (read_16bitLE(0x22,streamFile)) + { + case 8: + bps = 1; + break; + case 16: + bps = 2; + break; + default: + goto fail; + } + + /* check bytes per frame */ + if (read_16bitLE(0x20,streamFile) != channel_count*bps) goto fail; + + /* check size */ + /* file size -8 */ + if ((read_32bitLE(0x1c,streamFile)+8) != get_streamfile_size(streamFile)) + goto fail; + /* data chunk size, assume it occupies the rest of the file */ + //if ((read_32bitLE(0x28,streamFile)+start_offset) != get_streamfile_size(streamFile)) + // goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitLE(0x28,streamFile) / channel_count / bps; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + + vgmstream->meta_type = meta_HIS; + vgmstream->layout_type = layout_none; + if (bps == 2) + { + vgmstream->coding_type = coding_PCM16LE; + if (channel_count == 2) + { + vgmstream->coding_type = coding_PCM16LE_int; + vgmstream->interleave_block_size = 2; + } + } + else // bps == 1 + { + vgmstream->coding_type = coding_PCM8_U; + if (channel_count == 2) + { + vgmstream->coding_type = coding_PCM8_U_int; + vgmstream->interleave_block_size = 1; + } + } + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[0].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + if (channel_count == 2) + { + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[1].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[1].offset=start_offset + vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/idsp.c b/Frameworks/vgmstream/vgmstream/src/meta/idsp.c new file mode 100644 index 000000000..a5f2ad9a6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/idsp.c @@ -0,0 +1,267 @@ +#include "meta.h" +#include "../util.h" + +/* "idsp/IDSP" + Soul Calibur Legends (Wii) + Sky Crawlers: Innocent Aces (Wii) +*/ +VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + int i, j; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("idsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x69647370 || /* "idsp" */ + read_32bitBE(0xBC,streamFile) != 0x49445350) /* IDSP */ + goto fail; + + loop_flag = read_32bitBE(0x20,streamFile); + channel_count = read_32bitBE(0xC4,streamFile); + + if (channel_count > 8) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = (channel_count * 0x60) + 0x100; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0xC8,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0x14,streamFile))*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0xD0,streamFile)); + vgmstream->loop_end_sample = (read_32bitBE(0xD4,streamFile)); + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + if (read_32bitBE(0xD8,streamFile) == 0) + { + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = (get_streamfile_size(streamFile)-start_offset)/2; + } + else if (read_32bitBE(0xD8,streamFile) > 0) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0xD8,streamFile); + } + } + + vgmstream->meta_type = meta_IDSP; + + { + if (vgmstream->coding_type == coding_NGC_DSP) { + off_t coef_table[8] = {0x118,0x178,0x1D8,0x238,0x298,0x2F8,0x358,0x3B8}; + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* IDSP (Mario Strikers Charged) + - Single "IDSP" header... */ +VGMSTREAM * init_vgmstream_idsp3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 1; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("idsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x49445350) /* IDSP */ + goto fail; + + channel_count = read_32bitBE(0x24,streamFile); + + if (channel_count > 8) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = (channel_count*0x60)+0xC; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x14,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile)); + } + + vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile); + vgmstream->interleave_smallblock_size = ((vgmstream->num_samples/7*8)%(vgmstream->interleave_block_size)/vgmstream->channels); + vgmstream->layout_type = layout_interleave_shortblock; + + vgmstream->meta_type = meta_IDSP; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x28+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x88+i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* IDSP (Defender NGC) */ +VGMSTREAM * init_vgmstream_idsp4(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("idsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x49445350) /* "IDSP" */ + goto fail; + + channel_count = read_32bitBE(0x0C,streamFile); + + if (channel_count > 2) // Refuse everything else for now + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x70; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x08,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x04,streamFile)/channel_count/8*14; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/channel_count/8*14; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile); + } + + vgmstream->meta_type = meta_IDSP; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x14+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x42+i*2,streamFile); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ios_psnd.c b/Frameworks/vgmstream/vgmstream/src/meta/ios_psnd.c new file mode 100644 index 000000000..c8d5e6014 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ios_psnd.c @@ -0,0 +1,76 @@ +#include "meta.h" +#include "../util.h" + +/* PSND (from Crash Bandicoot Nitro Kart 2 (iOS) */ +VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("psnd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x50534E44) /* "PSND" */ + goto fail; + + if (read_16bitBE(0xC,streamFile)==0x2256){ + loop_flag = 1; + } + else { + loop_flag = 0; + } + channel_count = read_8bit(0xE,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + + if (read_16bitBE(0xC,streamFile)==0x44AC){ + vgmstream->sample_rate = 44100; + } + else { + vgmstream->sample_rate = read_16bitLE(0xC,streamFile); + } + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (read_32bitLE(0x4,streamFile)-8)/4; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_IOS_PSND; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ish_isd.c b/Frameworks/vgmstream/vgmstream/src/meta/ish_isd.c new file mode 100644 index 000000000..7078a093a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ish_isd.c @@ -0,0 +1,91 @@ +#include "meta.h" +#include "../util.h" + +/* +ISH+ISD +*/ + +VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileISH = NULL; + char filename[PATH_LIMIT]; + char filenameISH[260]; + int i; + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("isd",filename_extension(filename))) goto fail; + + strcpy(filenameISH,filename); + strcpy(filenameISH+strlen(filenameISH)-3,"ish"); + + streamFileISH = streamFile->open(streamFile,filenameISH,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileISH) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFileISH) != 0x495F5346) /* "I_SF" */ + goto fail; + + channel_count = read_32bitBE(0x14,streamFileISH); + loop_flag = (read_32bitBE(0x1C,streamFileISH) !=0); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x08,streamFileISH); + vgmstream->num_samples=read_32bitBE(0x0C,streamFileISH); + vgmstream->coding_type = coding_NGC_DSP; + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x20,streamFileISH)*14/8/channel_count; + vgmstream->loop_end_sample = read_32bitBE(0x24,streamFileISH)*14/8/channel_count; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x18,streamFileISH); + } + + vgmstream->meta_type = meta_ISH_ISD; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFileISH); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x80+i*2,streamFileISH); + } + } + } + + close_streamfile(streamFileISH); streamFileISH=NULL; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileISH) close_streamfile(streamFileISH); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c b/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c new file mode 100644 index 000000000..6c215828e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ivaud.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* ivaud (from GTA IV (PC)) */ +VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + + char filename[PATH_LIMIT]; + off_t start_offset; + off_t block_table_offset; + int block_count; + int loop_flag = 0; + int channel_count; + int i; + + + /* at this time, i only check for extension */ + /* i'll make further checks later */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ivaud",filename_extension(filename))) goto fail; + + /* multiple sounds .ivaud files are not implemented */ + /* only used for voices & sfx */ + if(read_32bitLE(0x10,streamFile)!=0) + goto fail; + + /* never looped and allways 2 channels */ + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + block_table_offset = read_32bitLE(0,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(block_table_offset + 0x04,streamFile); + vgmstream->coding_type = coding_INT_IMA; + + vgmstream->layout_type = layout_ivaud_blocked; + vgmstream->meta_type = meta_PC_IVAUD; + + /* open the file for reading */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x2000); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* Calc num_samples */ + start_offset = read_32bitLE(0x2C,streamFile); + block_count = read_32bitLE(0x08,streamFile); + vgmstream->next_block_offset = read_32bitLE(0x2C,streamFile); + + // to avoid troubles with "extra" samples + vgmstream->num_samples=((read_32bitLE(0x60,streamFile)/2)*2); + + ivaud_block_update(start_offset,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ivb.c b/Frameworks/vgmstream/vgmstream/src/meta/ivb.c new file mode 100644 index 000000000..19c835833 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ivb.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../util.h" + +/* a simple PS2 ADPCM format seen in Langrisser 3 */ +VGMSTREAM * init_vgmstream_ivb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + off_t stream_length; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ivb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x42564949) /* "BVII", probably */ + goto fail; /* supposed to be "IIVB"*/ + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x8,streamFile); /* big endian? */ + vgmstream->coding_type = coding_PSX; + stream_length = read_32bitLE(0x04,streamFile); + start_offset = 0x10; + vgmstream->num_samples = stream_length*28/16; + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PS2_IVB; + + /* open the file for reading */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+stream_length*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/kraw.c b/Frameworks/vgmstream/vgmstream/src/meta/kraw.c new file mode 100644 index 000000000..2fd4123ef --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/kraw.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* KRAW (from Geometry Wars - Galaxies) */ +VGMSTREAM * init_vgmstream_kraw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("kraw",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x6B524157) /* "kRAW" */ + goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x8; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0x04,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x04,streamFile)/2/channel_count; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_KRAW; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/lsf.c b/Frameworks/vgmstream/vgmstream/src/meta/lsf.c new file mode 100644 index 000000000..0f7ef2e32 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/lsf.c @@ -0,0 +1,59 @@ +#include "meta.h" +#include "../util.h" + +/* .lsf - Fastlane Street Racing (iPhone) */ +/* "!n1nj4n" */ + +VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t file_size; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("lsf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0, streamFile) != 0x216E316E || // "!n1n" + read_32bitBE(0x4, streamFile) != 0x6A346E00) // "j4n\0" + goto fail; + + /* check size */ + file_size = get_streamfile_size(streamFile); + if (read_32bitLE(0xC, streamFile) + 0x10 != file_size) + goto fail; + + start_offset = 0x10; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(1,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = (file_size-0x10)/0x1c*0x1b*2; + vgmstream->sample_rate = read_32bitLE(0x8, streamFile); + + vgmstream->coding_type = coding_LSF; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_LSF_N1NJ4N; + + /* open the file for reading */ + { + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mattel_hyperscan.c b/Frameworks/vgmstream/vgmstream/src/meta/mattel_hyperscan.c new file mode 100644 index 000000000..1601be8f0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mattel_hyperscan.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* Mattel Hyperscan, +- Place all metas for this console here (there are just 5 games) */ +VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bvg",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4B564147) /* "KVAG" */ + goto fail; + + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0xE; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x8,streamFile); + vgmstream->coding_type = coding_DVI_IMA; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)*2; + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x08,streamFile)-1)*28; + vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-1)*28; + } +#endif + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_HYPERSCAN_KVAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c new file mode 100644 index 000000000..bf0588eca --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/maxis_xa.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* Maxis XA - found in 'Sim City 3000' */ +VGMSTREAM * init_vgmstream_maxis_xa(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa",filename_extension(filename))) goto fail; + + /* check header */ + if ((read_32bitBE(0x00,streamFile) != 0x58414900)&& /* "XAI\0" */ + (read_32bitBE(0x00,streamFile) != 0x58414A00)) /* "XAJ\0" */ + goto fail; + + loop_flag = 0; + channel_count = read_16bitLE(0xA,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x18; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_MAXIS_ADPCM; + vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2/channel_count; + + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14; + } + + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_MAXIS_XA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset=start_offset+i; + vgmstream->ch[i].offset=0; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h new file mode 100644 index 000000000..6fe1d1217 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/meta.h @@ -0,0 +1,633 @@ +#ifndef _META_H +#define _META_H + +#include "../vgmstream.h" + +VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_afc(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_gcsw(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_halpst(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_stm(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_mpdsp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_rsf(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_int(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_exst(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_mic(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_raw(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_psx_gms(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_str(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_amts(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_stma(STREAMFILE *streamFile); + +#ifdef VGM_USE_VORBIS +VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile); + +typedef struct { + int loop_flag; + int32_t loop_start; + int loop_length_found; + int32_t loop_length; + int loop_end_found; + int32_t loop_end; + meta_t meta_type; + layout_t layout_type; + + // XOR setup with a single byte (SCD) + unsigned char scd_xor; + off_t scd_xor_len; +} vgm_vorbis_info_t; + +VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf); + +VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile); +#endif + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) +VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); + +VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile); +#endif + +VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_bmdx(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_wsi(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_aifc(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_str_snds(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE * streamFile); + +#ifdef VGM_USE_MPEG +VGMSTREAM * init_vgmstream_ahx(STREAMFILE * streamFile); +#endif + +VGMSTREAM * init_vgmstream_ivb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_svs(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_riff(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rifx(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xnbm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_nwa(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_eacs(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xss(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sl3(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_hgc1(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_aus(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rws(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_fsb1(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_fsb3(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_fsb4(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_fsb_mpeg(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rwx(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xwb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xwb2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xa30(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musc(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v004(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v005(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v006(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v010(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_musx_v201(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_leg(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_filp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ikm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sfs(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_dvi(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_bg00(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_kcey(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_acm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_kces(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_dxh(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_psw(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_tec(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_enth(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sdt(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_aix(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_capdsp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_xmu(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_sat_sap(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_rnd(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_kraw(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE * streamFile); + +//VGMSTREAM * init_vgmstream_idsp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_idsp2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_idsp3(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_idsp4(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sadl(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_ccc(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd2vag(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd2pcmb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd3pcm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd4pcmb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd4pcm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd4radp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd4vag(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd6vag(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_bgw(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_spw(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_seg(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_str_asr(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_gca(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_spt_spd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ydsp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_msvp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_ssm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_vgs(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_emff_ps2(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_emff_ngc(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_sts(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_p2bt(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_gbts(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_sng(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ngc_ffcc_str(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_nds_swav(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_vsf(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_str(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_zsd(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_RedSpark(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_wsd(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_sps(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile); + +VGMSTREAM * init_vgmstream_rsd3vag(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_lps(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_naomi_adpcm(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd3pcmb(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_rsd3gadp(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_sd9(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_2dx9(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ps2_vgv(STREAMFILE * streamFile); + +VGMSTREAM * init_vgmstream_ngc_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); + +VGMSTREAM * init_vgmstream_sab(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_exakt_sc(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_wii_was(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_stx(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_stm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_myspd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_his(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_ast(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dmsg(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_aaap(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_konami(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_ster(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_bnsf(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_s14_sss(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_smpl(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_xiii(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_cabelas(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_lpcm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_xau(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_gh3_bar(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ffw(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_nst_dsp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_baf(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_nub_vag(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_past(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_sgh_sgb(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ngca(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_spm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_iab(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_vawx(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_pc_snds(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_wmus(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_bos_adp(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_eb_sfx(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_eb_sf0(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_sgx(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_mtaf(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_tun(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_wpd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_sgd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_mn_str(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_mss(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_2pfs(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ubi_ckd(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_ps2_vbk(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_otm(STREAMFILE* streamFile); + +VGMSTREAM * init_vgmstream_bcstm(STREAMFILE* streamFile); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c b/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c new file mode 100644 index 000000000..833c17431 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mn_str.c @@ -0,0 +1,78 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_mn_str(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int bitspersample; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mnstr",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x50,streamFile); + bitspersample = read_32bitLE(0x58,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x20,streamFile)+0x48; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x54,streamFile); + + switch (bitspersample) { + case 0x10: + vgmstream->coding_type = coding_PCM16LE; + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->interleave_block_size = 0x2; + vgmstream->layout_type = layout_interleave; + } + break; + case 0x4: + if (read_32bitLE(0x20,streamFile) == 0x24) + { + vgmstream->interleave_block_size = 0x800; + vgmstream->layout_type = layout_none; + } + } + + vgmstream->num_samples = read_32bitLE(0x4C,streamFile); + + //vgmstream->layout_type = layout_interleave; + //vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_MN_STR; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mp4.c b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c new file mode 100644 index 000000000..20fd73c2d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mp4.c @@ -0,0 +1,163 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../util.h" + +#ifdef VGM_USE_MP4V2 +void* mp4_file_open( const char* name, MP4FileMode mode ) +{ + char * endptr; +#ifdef _MSC_VER + unsigned __int64 ptr = _strtoui64( name, &endptr, 16 ); +#else + unsigned long ptr = strtoul( name, &endptr, 16 ); +#endif + return (void*) ptr; +} + +int mp4_file_seek( void* handle, int64_t pos ) +{ + mp4_streamfile * file = ( mp4_streamfile * ) handle; + if ( pos > file->size ) pos = file->size; + pos += file->start; + file->offset = pos; + return 0; +} + +int mp4_file_get_size( void* handle, int64_t* size ) +{ + mp4_streamfile * file = ( mp4_streamfile * ) handle; + *size = file->size; + return 0; +} + +int mp4_file_read( void* handle, void* buffer, int64_t size, int64_t* nin, int64_t maxChunkSize ) +{ + mp4_streamfile * file = ( mp4_streamfile * ) handle; + int64_t max_size = file->size - file->offset - file->start; + if ( size > max_size ) size = max_size; + if ( size > 0 ) + { + *nin = read_streamfile( (uint8_t *) buffer, file->offset, size, file->streamfile ); + file->offset += *nin; + } + else + { + *nin = 0; + return 1; + } + return 0; +} + +int mp4_file_write( void* handle, const void* buffer, int64_t size, int64_t* nout, int64_t maxChunkSize ) +{ + return 1; +} + +int mp4_file_close( void* handle ) +{ + return 0; +} + +MP4FileProvider mp4_file_provider = { mp4_file_open, mp4_file_seek, mp4_file_get_size, mp4_file_read, mp4_file_write, mp4_file_close }; + +#ifdef VGM_USE_FDKAAC +VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size); + +VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE *streamFile) { + return init_vgmstream_mp4_aac_offset( streamFile, 0, streamFile->get_size(streamFile) ); +} + +VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size) { + VGMSTREAM * vgmstream = NULL; + + char filename[PATH_LIMIT]; + + mp4_aac_codec_data * aac_file = ( mp4_aac_codec_data * ) calloc(1, sizeof(mp4_aac_codec_data)); + + CStreamInfo * stream_info; + + uint8_t * buffer = NULL; + uint32_t buffer_size; + UINT ubuffer_size, bytes_valid; + + if ( !aac_file ) goto fail; + + aac_file->if_file.streamfile = streamFile; + aac_file->if_file.start = start; + aac_file->if_file.offset = start; + aac_file->if_file.size = size; + + /* Big ol' kludge! */ + sprintf( filename, "%p", &aac_file->if_file ); + aac_file->h_mp4file = MP4ReadProvider( filename, &mp4_file_provider ); + if ( !aac_file->h_mp4file ) goto fail; + + if ( MP4GetNumberOfTracks(aac_file->h_mp4file, MP4_AUDIO_TRACK_TYPE, '\000') != 1 ) goto fail; + + aac_file->track_id = MP4FindTrackId( aac_file->h_mp4file, 0, MP4_AUDIO_TRACK_TYPE, '\000' ); + + aac_file->h_aacdecoder = aacDecoder_Open( TT_MP4_RAW, 1 ); + if ( !aac_file->h_aacdecoder ) goto fail; + + aacDecoder_SetParam( aac_file->h_aacdecoder, AAC_PCM_OUTPUT_CHANNELS, 2 ); + + MP4GetTrackESConfiguration( aac_file->h_mp4file, aac_file->track_id, (uint8_t**)(&buffer), (uint32_t*)(&buffer_size)); + + ubuffer_size = buffer_size; + if ( aacDecoder_ConfigRaw( aac_file->h_aacdecoder, &buffer, &ubuffer_size ) ) goto fail; + + free( buffer ); buffer = NULL; + + aac_file->sampleId = 1; + aac_file->numSamples = MP4GetTrackNumberOfSamples( aac_file->h_mp4file, aac_file->track_id ); + + if (!MP4ReadSample(aac_file->h_mp4file, aac_file->track_id, aac_file->sampleId, (uint8_t**)(&buffer), (uint32_t*)(&buffer_size), 0, 0, 0, 0)) goto fail; + + ubuffer_size = buffer_size; + bytes_valid = buffer_size; + if ( aacDecoder_Fill( aac_file->h_aacdecoder, &buffer, &ubuffer_size, &bytes_valid ) || bytes_valid ) goto fail; + if ( aacDecoder_DecodeFrame( aac_file->h_aacdecoder, aac_file->sample_buffer, ( (6) * (2048)*4 ), 0 ) ) goto fail; + + free( buffer ); buffer = NULL; + + aac_file->sample_ptr = 0; + + stream_info = aacDecoder_GetStreamInfo( aac_file->h_aacdecoder ); + + aac_file->samples_per_frame = stream_info->frameSize; + aac_file->samples_discard = 0; + + streamFile->get_name( streamFile, filename, sizeof(filename) ); + + aac_file->if_file.streamfile = streamFile->open(streamFile, filename, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!aac_file->if_file.streamfile) goto fail; + + vgmstream = allocate_vgmstream( stream_info->numChannels, 1 ); + if (!vgmstream) goto fail; + + vgmstream->loop_flag = 0; + + vgmstream->codec_data = aac_file; + + vgmstream->channels = stream_info->numChannels; + vgmstream->sample_rate = stream_info->sampleRate; + + vgmstream->num_samples = stream_info->frameSize * aac_file->numSamples; + + vgmstream->coding_type = coding_MP4_AAC; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_MP4; + + return vgmstream; + +fail: + if ( buffer ) free( buffer ); + if ( aac_file ) { + if ( aac_file->h_aacdecoder ) aacDecoder_Close( aac_file->h_aacdecoder ); + if ( aac_file->h_mp4file ) MP4Close( aac_file->h_mp4file, 0 ); + free( aac_file ); + } + return NULL; +} +#endif +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/msvp.c b/Frameworks/vgmstream/vgmstream/src/meta/msvp.c new file mode 100644 index 000000000..687344e89 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/msvp.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +/* MSVP (from PoPcap Hits Vol. 1) */ +VGMSTREAM * init_vgmstream_msvp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("msvp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D535670) /* "MSVp" */ + goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile))*28/16/channel_count; + } + +/* Just to be sure that there comes a 2 channel file */ + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; /* Unknown for now */ + } + + vgmstream->meta_type = meta_MSVP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c b/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c new file mode 100644 index 000000000..7bd10a8b6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/mus_acm.c @@ -0,0 +1,360 @@ +#include "../vgmstream.h" +#include "meta.h" +#include "../util.h" +#include "../streamfile.h" +#include "../coding/acm_decoder.h" +#include +#include +#include + +#ifdef WIN32 +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +#define NAME_LENGTH 260 + +int exists(char *filename, STREAMFILE *streamfile) { + STREAMFILE * temp = + streamfile->open(streamfile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!temp) return 0; + + close_streamfile(temp); + return 1; +} + +/* needs the name of a file in the directory to test, as all we can do reliably is attempt to open a file */ +int find_directory_name(char *name_base, char *dir_name, int subdir_name_size, char *subdir_name, char *name, char *file_name, STREAMFILE *streamfile) { + /* find directory name */ + { + char temp_dir_name[NAME_LENGTH]; + + subdir_name[0]='\0'; + concatn(subdir_name_size,subdir_name,name_base); + + if (strlen(subdir_name) >= subdir_name_size-2) goto fail; + subdir_name[strlen(subdir_name)+1]='\0'; + subdir_name[strlen(subdir_name)]=DIRSEP; + + temp_dir_name[0]='\0'; + concatn(sizeof(temp_dir_name),temp_dir_name,dir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,subdir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,name_base); + concatn(sizeof(temp_dir_name),temp_dir_name,name); + concatn(sizeof(temp_dir_name),temp_dir_name,".ACM"); + + if (!exists(temp_dir_name,streamfile)) { + int i; + /* try all lowercase */ + for (i=strlen(subdir_name)-1;i>=0;i--) { + subdir_name[i]=tolower(subdir_name[i]); + } + temp_dir_name[0]='\0'; + concatn(sizeof(temp_dir_name),temp_dir_name,dir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,subdir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,name_base); + concatn(sizeof(temp_dir_name),temp_dir_name,name); + concatn(sizeof(temp_dir_name),temp_dir_name,".ACM"); + + if (!exists(temp_dir_name,streamfile)) { + /* try first uppercase */ + subdir_name[0]=toupper(subdir_name[0]); + temp_dir_name[0]='\0'; + concatn(sizeof(temp_dir_name),temp_dir_name,dir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,subdir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,name_base); + concatn(sizeof(temp_dir_name),temp_dir_name,name); + concatn(sizeof(temp_dir_name),temp_dir_name,".ACM"); + if (!exists(temp_dir_name,streamfile)) { + /* try also 3rd uppercase */ + subdir_name[2]=toupper(subdir_name[2]); + temp_dir_name[0]='\0'; + concatn(sizeof(temp_dir_name),temp_dir_name,dir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,subdir_name); + concatn(sizeof(temp_dir_name),temp_dir_name,name_base); + concatn(sizeof(temp_dir_name),temp_dir_name,name); + concatn(sizeof(temp_dir_name),temp_dir_name,".ACM"); + + if (!exists(temp_dir_name,streamfile)) { + /* ah well, disaster has befallen your party */ + goto fail; + } + } + } + } + } + + return 0; + +fail: + return 1; +} + +/* MUS playlist for InterPlay ACM */ +VGMSTREAM * init_vgmstream_mus_acm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + ACMStream *acm_stream = NULL; + mus_acm_codec_data *data = NULL; + + char filename[NAME_LENGTH]; + char line_buffer[NAME_LENGTH]; + char * end_ptr; + char name_base[NAME_LENGTH]; + char (*names)[NAME_LENGTH] = NULL; + char dir_name[NAME_LENGTH]; + char subdir_name[NAME_LENGTH]; + + int i; + int loop_flag = 0; + int channel_count; + int file_count; + size_t line_bytes; + int whole_line_read = 0; + off_t mus_offset = 0; + + int loop_end_index = -1; + int loop_start_index = -1; + int32_t loop_start_samples = -1; + int32_t loop_end_samples = -1; + + int32_t total_samples = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mus",filename_extension(filename))) goto fail; + + /* read file name base */ + line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer, + mus_offset, streamFile, &whole_line_read); + if (!whole_line_read) goto fail; + mus_offset += line_bytes; + memcpy(name_base,line_buffer,sizeof(name_base)); + + /* uppercase name_base */ + { + int i; + for (i=0;name_base[i];i++) name_base[i]=toupper(name_base[i]); + } + + /*printf("name base: %s\n",name_base);*/ + + /* read track entry count */ + line_bytes = get_streamfile_dos_line(sizeof(line_buffer),line_buffer, + mus_offset, streamFile, &whole_line_read); + if (!whole_line_read) goto fail; + if (line_buffer[0] == '\0') goto fail; + mus_offset += line_bytes; + file_count = strtol(line_buffer,&end_ptr,10); + /* didn't parse whole line as an integer (optional opening whitespace) */ + if (*end_ptr != '\0') goto fail; + + /*printf("entries: %d\n",file_count);*/ + + names = calloc(file_count,sizeof(names[0])); + if (!names) goto fail; + + dir_name[0]='\0'; + concatn(sizeof(dir_name),dir_name,filename); + + { + /* find directory name for the directory contianing the MUS */ + char * last_slash; + last_slash = strrchr(dir_name,DIRSEP); + if (last_slash != NULL) { + /* trim off the file name */ + last_slash[1]='\0'; + } else { + /* no dir name? annihilate! */ + dir_name[0] = '\0'; + } + } + + /* can't do this until we have a file name */ + subdir_name[0]='\0'; + + /* parse each entry */ + { + char name[NAME_LENGTH]; + char loop_name_base_temp[NAME_LENGTH]; + char loop_name_temp[NAME_LENGTH]; + char loop_name_base[NAME_LENGTH]; + char loop_name[NAME_LENGTH]; + for (i=0;i= 2 && loop_name_base_temp[0] != '@') + { + int j; + memcpy(loop_name,loop_name_base_temp,sizeof(loop_name)); + memcpy(loop_name_base,name_base,sizeof(loop_name_base)); + for (j=0;loop_name[j];j++) loop_name[j]=toupper(loop_name[j]); + for (j=0;loop_name_base[j];j++) loop_name_base[j]=toupper(loop_name_base[j]); + /* loop back entry */ + loop_end_index = i; + } + else + { + /* normal entry, ignoring the @TAG for now */ + } + + { + /* uppercase */ + int j; + for (j=0;jfiles = calloc(file_count,sizeof(ACMStream *)); + if (!data->files) { + free(data); data = NULL; + goto fail; + } + + /* open each file... */ + for (i=0;ifiles[i]=acm_stream; + + if (i==loop_start_index) loop_start_samples = total_samples; + if (i==loop_end_index) loop_end_samples = total_samples; + + total_samples += acm_stream->total_values / acm_stream->info.channels; + + if (i>0) { + if (acm_stream->info.channels != data->files[0]->info.channels || + acm_stream->info.rate != data->files[0]->info.rate) goto fail; + } + } + + if (i==loop_end_index) loop_end_samples = total_samples; + + channel_count = data->files[0]->info.channels; + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = data->files[0]->info.rate; + vgmstream->coding_type = coding_ACM; + vgmstream->num_samples = total_samples; + vgmstream->loop_start_sample = loop_start_samples; + vgmstream->loop_end_sample = loop_end_samples; + vgmstream->layout_type = layout_mus_acm; + vgmstream->meta_type = meta_MUS_ACM; + + data->file_count = file_count; + data->current_file = 0; + data->loop_start_file = loop_start_index; + data->loop_end_file = loop_end_index; + /*data->end_file = -1;*/ + + vgmstream->codec_data = data; + + free(names); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (data) { + int i; + for (i=0;ifile_count;i++) { + if (data->files[i]) { + acm_close(data->files[i]); + data->files[i] = NULL; + } + } + } + if (names) free(names); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/musc.c b/Frameworks/vgmstream/vgmstream/src/meta/musc.c new file mode 100644 index 000000000..c0483a7ee --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/musc.c @@ -0,0 +1,73 @@ +#include "meta.h" +#include "../util.h" + +/* MUSC (near all Spyro games and many other using this) */ +VGMSTREAM * init_vgmstream_musc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mus",filename_extension(filename)) && + strcasecmp("musc",filename_extension(filename))) + goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x4D555343) /* MUSC */ + goto fail; + + /* check file size */ + if ((read_32bitLE(0x10,streamFile)+read_32bitLE(0x14,streamFile)) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + start_offset = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t) read_16bitLE(0x06,streamFile); + + vgmstream->num_samples = read_32bitLE(0x14,streamFile)/channel_count/16*28; + +#if 0 + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x14,streamFile))*28/16/channel_count; + } +#endif + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2; + vgmstream->meta_type = meta_MUSC; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/musx.c b/Frameworks/vgmstream/vgmstream/src/meta/musx.c new file mode 100644 index 000000000..e174b4b2c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/musx.c @@ -0,0 +1,525 @@ +#include "meta.h" +#include "../util.h" + + +/* MUSX (Version 004) --------------------------------------->*/ +VGMSTREAM * init_vgmstream_musx_v004(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x04000000) /* "0x04000000" */ + goto fail; + + loop_flag = (read_32bitLE(0x840,streamFile) != 0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + switch (read_32bitBE(0x10,streamFile)) + { + case 0x5053325F: /* PS2_ */ + start_offset = read_32bitLE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; // PS2 ADPCM + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))/16/channel_count*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))/16/channel_count*28; + vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))/16/channel_count*28; + } + break; + case 0x47435F5F: /* GC__ */ + start_offset = read_32bitBE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_DAT4_IMA; // Eurocom DAT4 4-bit IMA ADPCM + vgmstream->num_samples = (read_32bitBE(0x2C,streamFile))/16/channel_count*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitBE(0x890,streamFile))/16/channel_count*28; + vgmstream->loop_end_sample = (read_32bitBE(0x89C,streamFile))/16/channel_count*28; + } + break; + case 0x58425F5F: /* XB__ */ + start_offset = read_32bitLE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_DAT4_IMA; // Eurocom DAT4 4-bit IMA ADPCM + vgmstream->num_samples = (read_32bitLE(0x2C,streamFile))/16/channel_count*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))/16/channel_count*28; + vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))/16/channel_count*28; + } + break; + default: + goto fail; + } + + vgmstream->meta_type = meta_MUSX_V004; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +/* <--------------------------------------- MUSX (Version 004) */ + + +/* MUSX (Version 005) --------------------------------------->*/ +VGMSTREAM * init_vgmstream_musx_v005(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x05000000) /* "0x04000000" */ + goto fail; + + loop_flag = (read_32bitLE(0x840,streamFile) != 0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + switch (read_32bitBE(0x10,streamFile)) + { + case 0x47435F5F: /* GC__ */ + start_offset = read_32bitBE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_DAT4_IMA; // Eurocom DAT4 4-bit IMA ADPCM + vgmstream->num_samples = (read_32bitBE(0x2C,streamFile))/16/channel_count*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitBE(0x890,streamFile))/16/channel_count*28; + vgmstream->loop_end_sample = (read_32bitBE(0x89C,streamFile))/16/channel_count*28; + } + break; + default: + goto fail; + } + + vgmstream->meta_type = meta_MUSX_V005; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +/* <--------------------------------------- MUSX (Version 005) */ + + + +/* MUSX (Version 006) ---------------------------------------> */ +VGMSTREAM * init_vgmstream_musx_v006(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + + if (read_32bitBE(0x08,streamFile) != 0x06000000) /* "0x06000000" */ + goto fail; + + loop_flag = (read_32bitLE(0x840,streamFile)!=0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + switch (read_32bitBE(0x10,streamFile)) + { + case 0x5053325F: /* PS2_ */ + start_offset = read_32bitLE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V006; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*28/16/channel_count; + } + break; + case 0x47435F5F: /* GC__ */ + start_offset = read_32bitBE(0x28,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_DAT4_IMA; + vgmstream->num_samples = (read_32bitBE(0x2C,streamFile))*28/16/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + vgmstream->meta_type = meta_MUSX_V006; + if (loop_flag) + { + vgmstream->loop_start_sample = (read_32bitBE(0x890,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitBE(0x89C,streamFile))*28/16/channel_count; + } + break; + default: + goto fail; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +/* <--------------------------------------- MUSX (Version 006) */ + + +/* MUSX (Version 010) --------------------------------------->*/ +/* WII_ in Dead Space: Extraction */ +VGMSTREAM * init_vgmstream_musx_v010(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int musx_type; /* determining the decoder by strings like "PS2_", "GC__" and so on */ + //int musx_version; /* 0x08 provides a "version" byte */ + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + if (read_32bitBE(0x800,streamFile) == 0x53424E4B) /* "SBNK", */ // SoundBank, refuse + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x0A000000) /* "0x0A000000" */ + goto fail; + + loop_flag = ((read_32bitLE(0x34,streamFile)!=0x00000000) && + (read_32bitLE(0x34,streamFile)!=0xABABABAB)); + channel_count = 2; + + musx_type=(read_32bitBE(0x10,streamFile)); + + if (musx_type == 0x5749495F && /* WII_ */ + (read_16bitBE(0x40,streamFile) == 0x4441) && /* DA */ + (read_8bit(0x42,streamFile) == 0x54)) /* T */ + { + channel_count = read_32bitLE(0x48,streamFile); + loop_flag = (read_32bitLE(0x64,streamFile) != -1); + } + if (musx_type == 0x5053335F && /* PS3_ */ + (read_16bitBE(0x40,streamFile) == 0x4441) && /* DA */ + (read_8bit(0x42,streamFile) == 0x54)) /* T */ + { + channel_count = read_32bitLE(0x48,streamFile); + loop_flag = (read_32bitLE(0x64,streamFile) != -1); + } + if (0x58455F5F == musx_type) /* XE__ */ + { + loop_flag = 0; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + switch (musx_type) { + case 0x5053325F: /* PS2_ */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x40,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V010; + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x40,streamFile); + } + break; + case 0x5053505F: /* PSP_ */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32768; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0xC,streamFile))*28/32; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V010; + break; + case 0x5053335F: /* PS3_ */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->coding_type = coding_DAT4_IMA; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + vgmstream->meta_type = meta_MUSX_V010; + + if (read_32bitBE(0x40,streamFile)==0x44415438){ + vgmstream->num_samples = read_32bitLE(0x60,streamFile); + vgmstream->sample_rate = read_32bitLE(0x4C,streamFile); + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x64,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x60,streamFile); + } + } + else { + vgmstream->sample_rate = 44100; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/2/(0x20)*((0x20-4)*2); + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x40,streamFile); + } + } + break; + case 0x5749495F: /* WII_ */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x4C,streamFile); + switch (read_32bitBE(0x40,streamFile)) + { + case 0x44415434: /* DAT4 */ + case 0x44415438: /* DAT8 */ + vgmstream->coding_type = coding_DAT4_IMA; + break; + default: + goto fail; + } + vgmstream->num_samples = read_32bitLE(0x60,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + vgmstream->meta_type = meta_MUSX_V010; + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x64,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x60,streamFile); + } + + break; + case 0x58455F5F: /* XE__ */ + start_offset = 0x800; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_DAT4_IMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/2/(0x20)*((0x20-4)*2); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20; + vgmstream->meta_type = meta_MUSX_V010; + + break; + default: + goto fail; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +/* <--------------------------------------- MUSX (Version 010) */ + + +/* MUSX (Version 201) --------------------------------------->*/ +VGMSTREAM * init_vgmstream_musx_v201(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + //int musx_version; /* 0x08 provides a "version" byte */ + int loop_flag; + int channel_count; + int loop_detect; + int loop_offsets; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("musx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D555358) /* "MUSX" */ + goto fail; + if ((read_32bitBE(0x08,streamFile) != 0xC9000000) && + (read_32bitLE(0x08,streamFile) != 0xC9000000)) /* "0xC9000000" */ + goto fail; + + channel_count = 2; + + loop_detect = read_32bitBE(0x800,streamFile); + switch (loop_detect) { + case 0x02000000: + loop_offsets = 0x8E0; + break; + case 0x03000000: + loop_offsets = 0x880; + break; + case 0x04000000: + loop_offsets = 0x8B4; + break; + case 0x05000000: + loop_offsets = 0x8E8; + break; + case 0x06000000: + loop_offsets = 0x91C; + break; + default: + goto fail; + } + + loop_flag = (read_32bitLE(loop_offsets+0x04,streamFile) !=0x00000000); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(loop_offsets,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(loop_offsets+0x10,streamFile)*28/16/channel_count; + vgmstream->loop_end_sample = read_32bitLE(loop_offsets,streamFile)*28/16/channel_count; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x80; + vgmstream->meta_type = meta_MUSX_V201; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +/* <--------------------------------------- MUSX (Version 201) */ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/myspd.c b/Frameworks/vgmstream/vgmstream/src/meta/myspd.c new file mode 100644 index 000000000..cfcb6d444 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/myspd.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../util.h" + +/* U-Sing (Wii) .myspd */ + +VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + int loop_flag = 0; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("myspd",filename_extension(filename))) goto fail; + + channel_count = 2; + start_offset = 0x20; + + /* check size */ + if ((read_32bitBE(0x0,streamFile)*channel_count+start_offset) != get_streamfile_size(streamFile)) + goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x0,streamFile) * 2; + vgmstream->sample_rate = read_32bitBE(0x4,streamFile); + + vgmstream->coding_type = coding_IMA; + vgmstream->meta_type = meta_MYSPD; + vgmstream->layout_type = layout_none; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[0].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[1].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[1].offset=start_offset + read_32bitBE(0x0,streamFile); + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/naomi_adpcm.c b/Frameworks/vgmstream/vgmstream/src/meta/naomi_adpcm.c new file mode 100644 index 000000000..7ca6ec969 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/naomi_adpcm.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../util.h" + +/* ADPCM (from NAOMI/NAOMI2 Arcade games) */ +VGMSTREAM * init_vgmstream_naomi_adpcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("adpcm",filename_extension(filename))) goto fail; + +#if 0 + /* check header */ + if ((read_32bitBE(0x00,streamFile) != 0x41445043) || /* "ADPC" */ + (read_32bitBE(0x04,streamFile) != 0x41445043)) /* "M_v0" */ + goto fail; +#endif + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_AICA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile) * 0x80; + vgmstream->meta_type = meta_NAOMI_ADPCM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */ + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c b/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c new file mode 100644 index 000000000..d8d683cd5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/naomi_spsd.c @@ -0,0 +1,88 @@ +#include "meta.h" +#include "../util.h" + +/* SPSD (Guilty Gear X [NAOMI GD-ROM]) */ +VGMSTREAM * init_vgmstream_naomi_spsd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int coding; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("spsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53505344) /* "SPSD" */ + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile); + + switch (read_8bit(0x8,streamFile)) + { + case 0x01: + coding = coding_PCM8; + break; + case 0x03: + coding = coding_AICA; + break; + default: + goto fail; + } + + vgmstream->coding_type = coding; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile); + +#if 0 + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); + } +#endif + + vgmstream->interleave_block_size = 0x2000; + if (channel_count > 1) { + vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels; + vgmstream->layout_type = layout_interleave_shortblock; + } else { + vgmstream->layout_type = layout_none; + } + + vgmstream->meta_type = meta_NAOMI_SPSD; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */ + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c new file mode 100644 index 000000000..7774f6d8c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_hwas.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* HWAS (found in Spider-Man 3, Tony Hawk's Downhill Jam, possibly more...) */ +VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("hwas",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x73617768) /* "sawh" */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x0C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x200; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_INT_IMA; + vgmstream->num_samples = read_32bitLE(0x14,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile); + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; // Not sure if there are stereo files + } + + vgmstream->meta_type = meta_NDS_HWAS; + + /* open the file for reading by each channel */ + + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c new file mode 100644 index 000000000..c38e9d649 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_rrds.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* bxaimc - 2009-03-05 + - RRDS - found in Ridge Racer DS */ + +VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + int loop_flag; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rrds",filename_extension(filename))) goto fail; + + /* check size */ + if ((read_32bitLE(0x0,streamFile)+0x18) != get_streamfile_size(streamFile)) + goto fail; + + /* check type details */ + loop_flag = (read_32bitLE(0x14,streamFile) != 0); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x1c; + vgmstream->num_samples = (read_32bitLE(0x0,streamFile)-start_offset) / channel_count * 2; + vgmstream->sample_rate = read_32bitLE(0x8,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x14,streamFile)-start_offset) / channel_count * 2; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->coding_type = coding_IMA; + vgmstream->meta_type = meta_NDS_RRDS; + vgmstream->layout_type = layout_none; + + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[0].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + /* one NDS IMA header for whole stream */ + vgmstream->ch[0].adpcm_history1_16 = read_16bitLE(0x18,streamFile); + vgmstream->ch[0].adpcm_step_index = read_16bitLE(0x1a,streamFile); + if (vgmstream->ch[0].adpcm_step_index < 0 || vgmstream->ch[0].adpcm_step_index > 88) goto fail; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_sad.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_sad.c new file mode 100644 index 000000000..b49f91d4f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_sad.c @@ -0,0 +1,110 @@ +#include "meta.h" +#include "../util.h" + +/* sadl (only the Professor Layton interleaved IMA version) */ +VGMSTREAM * init_vgmstream_sadl(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + int coding_type; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sad",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x7361646c) /* "sadl" */ + goto fail; + + /* check file size */ + if (read_32bitLE(0x40,streamFile) != get_streamfile_size(streamFile) ) + goto fail; + + /* check coding type */ + switch (read_8bit(0x33,streamFile)&0xf0) + { + case 0x70: + coding_type = coding_INT_IMA; + break; + case 0xb0: + coding_type = coding_NDS_PROCYON; + break; + default: + goto fail; + } + + loop_flag = read_8bit(0x31,streamFile); + channel_count = read_8bit(0x32,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x100; + vgmstream->channels = channel_count; + + switch (read_8bit(0x33,streamFile) & 6) + { + case 4: + vgmstream->sample_rate = 32728; + break; + case 2: + vgmstream->sample_rate = 16364; + break; + default: + goto fail; + } + + vgmstream->coding_type = coding_type; + + if (coding_type == coding_INT_IMA) + vgmstream->num_samples = + (read_32bitLE(0x40,streamFile)-start_offset)/channel_count*2; + else if (coding_type == coding_NDS_PROCYON) + vgmstream->num_samples = + (read_32bitLE(0x40,streamFile)-start_offset)/channel_count/16*30; + + vgmstream->interleave_block_size=0x10; + + if (loop_flag) + { + if (coding_type == coding_INT_IMA) + vgmstream->loop_start_sample = (read_32bitLE(0x54,streamFile)-start_offset)/channel_count*2; + else + vgmstream->loop_start_sample = (read_32bitLE(0x54,streamFile)-start_offset)/channel_count/16*30; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if (channel_count > 1) + vgmstream->layout_type = layout_interleave; + else + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_SADL; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c new file mode 100644 index 000000000..749072037 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_strm.c @@ -0,0 +1,171 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_nds_strm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type; + + int codec_number; + int channel_count; + int loop_flag; + + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("strm",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x5354524D) /* STRM */ + goto fail; + if ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFFFE0001 && /* Old Header Check */ + ((uint32_t)read_32bitBE(0x04,streamFile)!=0xFEFF0001)) /* Some newer games have a new flag */ + goto fail; + + + + /* check for HEAD section */ + if ((uint32_t)read_32bitBE(0x10,streamFile)!=0x48454144 && /* "HEAD" */ + (uint32_t)read_32bitLE(0x14,streamFile)!=0x50) /* 0x50-sized head is all I've seen */ + goto fail; + + /* check type details */ + codec_number = read_8bit(0x18,streamFile); + loop_flag = read_8bit(0x19,streamFile); + channel_count = read_8bit(0x1a,streamFile); + + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + break; + case 1: + coding_type = coding_PCM16LE; + break; + case 2: + coding_type = coding_NDS_IMA; + break; + default: + goto fail; + } + + /* TODO: only mono and stereo supported */ + if (channel_count < 1 || channel_count > 2) goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitLE(0x24,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1c,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_type; + vgmstream->meta_type = meta_STRM; + + vgmstream->interleave_block_size = read_32bitLE(0x30,streamFile); + vgmstream->interleave_smallblock_size = read_32bitLE(0x38,streamFile); + + if (coding_type==coding_PCM8 || coding_type==coding_PCM16LE) + vgmstream->layout_type = layout_none; + else + vgmstream->layout_type = layout_interleave_shortblock; + + start_offset = read_32bitLE(0x28,streamFile); + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ilayout_type==layout_interleave_shortblock) + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + vgmstream->interleave_block_size); + else + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + 0x1000); + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* STRM (from Final Fantasy Tactics A2 - Fuuketsu no Grimoire) */ +VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("strm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* RIFF */ + read_32bitBE(0x08,streamFile) != 0x494D4120) /* "IMA " */ + goto fail; + + loop_flag = (read_32bitLE(0x20,streamFile) !=0); + channel_count = read_32bitLE(0x24,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x2C; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_INT_IMA; + vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x20,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x28,streamFile); + } + + vgmstream->interleave_block_size = 0x80; + vgmstream->interleave_smallblock_size = (vgmstream->loop_end_sample)%((vgmstream->loop_end_sample)/vgmstream->interleave_block_size); + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->meta_type = meta_NDS_STRM_FFTA2; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nds_swav.c b/Frameworks/vgmstream/vgmstream/src/meta/nds_swav.c new file mode 100644 index 000000000..b3ded8736 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nds_swav.c @@ -0,0 +1,127 @@ +#include "meta.h" +#include "../util.h" + +/* 28.01.2009 - bxaimc : + SWAV - found in Asphalt Urban GT & Asphalt Urban GT 2 */ +VGMSTREAM * init_vgmstream_nds_swav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int codec_number; + int channel_count; + int loop_flag; + coding_t coding_type; + off_t start_offset; + int bits_per_sample; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("swav",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0x00,streamFile)!=0x53574156) /* SWAV */ + goto fail; + + /* check for DATA section */ + if ((uint32_t)read_32bitBE(0x10,streamFile)!=0x44415441) /* "DATA" */ + goto fail; + + /* check type details */ + codec_number = read_8bit(0x18,streamFile); + loop_flag = read_8bit(0x19,streamFile); + + channel_count = 1; + if (get_streamfile_size(streamFile) != read_32bitLE(0x8,streamFile)) + { + if (get_streamfile_size(streamFile) != + (read_32bitLE(0x8,streamFile) - 0x24) * 2 + 0x24) + goto fail; + + channel_count = 2; + } + + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + bits_per_sample = 8; + break; + case 1: + coding_type = coding_PCM16LE; + bits_per_sample = 16; + break; + case 2: + coding_type = coding_INT_IMA; + bits_per_sample = 4; + break; + default: + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x24; + vgmstream->num_samples = + (read_32bitLE(0x14,streamFile) - 0x14) * 8 / bits_per_sample; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x1A,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = + (uint16_t)read_16bitLE(0x1E,streamFile) * 32 / bits_per_sample; + vgmstream->loop_end_sample = + read_32bitLE(0x20,streamFile) * 32 / bits_per_sample + + vgmstream->loop_start_sample; + } + + if (coding_type == coding_INT_IMA) { + /* handle IMA frame header */ + vgmstream->loop_start_sample -= 32 / bits_per_sample; + vgmstream->loop_end_sample -= 32 / bits_per_sample; + vgmstream->num_samples -= 32 / bits_per_sample; + + { + int i; + for (i=0; ich[i].adpcm_history1_32 = + read_16bitLE(start_offset + 0 + 4*i, streamFile); + vgmstream->ch[i].adpcm_step_index = + read_16bitLE(start_offset + 2 + 4*i, streamFile); + } + } + + start_offset += 4 * channel_count; + } + + vgmstream->coding_type = coding_type; + vgmstream->meta_type = meta_NDS_SWAV; + if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 1; + } else { + vgmstream->layout_type = layout_none; + } + + /* open the file for reading by each channel */ + + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c new file mode 100644 index 000000000..613ffcfe2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_adpdtk.c @@ -0,0 +1,53 @@ +#include +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * chstreamfile; + char filename[PATH_LIMIT]; + + size_t file_size; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("adp",filename_extension(filename)) && + strcasecmp("dtk",filename_extension(filename))) goto fail; + + /* file size is the only way to determine sample count */ + file_size = get_streamfile_size(streamFile); + + /* .adp files have no header, so all we can do is look for a valid first frame */ + if (read_8bit(0,streamFile)!=read_8bit(2,streamFile) || read_8bit(1,streamFile)!=read_8bit(3,streamFile)) goto fail; + + /* Hopefully we haven't falsely detected something else... */ + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,0); /* always stereo, no loop */ + if (!vgmstream) goto fail; + + vgmstream->num_samples = file_size/32*28; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_NGC_DTK; + vgmstream->layout_type = layout_dtk_interleave; + vgmstream->meta_type = meta_NGC_ADPDTK; + + /* locality is such that two streamfiles is silly */ + chstreamfile = streamFile->open(streamFile,filename,32*0x400); + if (!chstreamfile) goto fail; + + for (i=0;i<2;i++) { + vgmstream->ch[i].channel_start_offset = + vgmstream->ch[i].offset = 0; + + vgmstream->ch[i].streamfile = chstreamfile; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_bh2pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_bh2pcm.c new file mode 100644 index 000000000..9fe0d3f77 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_bh2pcm.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../util.h" + +/* BH2PCM (from Bio Hazard 2) */ +VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count; + int format_detect; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bh2pcm",filename_extension(filename))) goto fail; + +#if 0 + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00000000) + goto fail; +#endif + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + format_detect=read_32bitLE(0x00,streamFile); + switch (format_detect) { + case 1: + start_offset = 0x20; + channel_count = 2; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile); + } + break; + case 0: + start_offset = 0x20; + channel_count = 1; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile); + vgmstream->layout_type = layout_none; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); + } + break; + default: + goto fail; + } + + vgmstream->coding_type = coding_PCM16BE; + vgmstream->meta_type = meta_NGC_BH2PCM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_bo2.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_bo2.c new file mode 100644 index 000000000..74ee379f1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_bo2.c @@ -0,0 +1,100 @@ +#include "meta.h" +#include "../util.h" + +/* BO2 (Blood Omen 2 NGC) */ +VGMSTREAM * init_vgmstream_ngc_bo2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channels; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bo2",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x0) /* "IDSP" */ + goto fail; + + switch (read_32bitBE(0x10,streamFile)) + { + case 0x0: + channels = 1; + break; + case 0x1: + channels = 2; + break; + default: + goto fail; + } + + if ((get_streamfile_size(streamFile)) < ((read_32bitBE(0x0C,streamFile)/14*8*channels)+0x800)) + { + goto fail; + } + + channel_count = channels; + loop_flag = (read_32bitBE(0x08,streamFile) != 0xFFFFFFFF); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x04,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x08,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile); + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x400; + } + + vgmstream->meta_type = meta_NGC_BO2; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x24+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x52+i*2,streamFile); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_caf.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_caf.c new file mode 100644 index 000000000..fce124882 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_caf.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + // Calculate sample length ... + int32_t num_of_samples=0; + int32_t block_count=0; + + uint32_t loop_start=-1; + + off_t offset=0; + off_t next_block; + off_t file_length; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("cfn",filename_extension(filename))) goto fail; + + /* Check "CAF " ID */ + if (read_32bitBE(0,streamFile)!=0x43414620) goto fail; + + // Calculate sample length ... + file_length=(off_t)get_streamfile_size(streamFile); + + do { + next_block=read_32bitBE(offset+0x04,streamFile); + num_of_samples+=read_32bitBE(offset+0x14,streamFile)/8*14; + + if(read_32bitBE(offset+0x20,streamFile)==read_32bitBE(offset+0x08,streamFile)) { + loop_start=num_of_samples-read_32bitBE(offset+0x14,streamFile)/8*14; + } + offset+=next_block; + block_count++; + } while(offsetchannels=2; + vgmstream->sample_rate=32000; + vgmstream->num_samples=num_of_samples; + + if(loop_start!=-1) { + vgmstream->loop_start_sample=loop_start; + vgmstream->loop_end_sample=num_of_samples; + } + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_caf_blocked; + vgmstream->meta_type = meta_CFN; + + /* open the file for reading by each channel */ + { + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + caf_block_update(0,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_konami.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_konami.c new file mode 100644 index 000000000..4096a6c9f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_konami.c @@ -0,0 +1,78 @@ +#include "meta.h" +#include "../util.h" + +/* DSP + Teenage Mutant Ninja Turtles 2 (NGC) +*/ +VGMSTREAM * init_vgmstream_ngc_dsp_konami(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int i, j; + off_t ch1_start; + off_t ch2_start; + off_t coef_table[2] = {0x90, 0xD0}; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) + goto fail; + + /* check header */ + if ((read_32bitBE(0x00,streamFile)+0x800) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = (read_32bitBE(0x10,streamFile) != 0x0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x04,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0x00,streamFile)/channel_count/8*14); + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x14,streamFile)/channel_count/8*14); + vgmstream->loop_end_sample = (read_32bitBE(0x00,streamFile)/channel_count/8*14); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x100; + vgmstream->meta_type = meta_NGC_DSP_KONAMI; + + ch1_start = 0x800; + ch2_start = 0x800 + vgmstream->interleave_block_size; + + // COEFFS + { + for (j=0;jchannels;j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); + } + } + } + + /* open the file for reading */ + /* Channel 1 */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + /* Channel 1 */ + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c new file mode 100644 index 000000000..373088b43 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_mpds.c @@ -0,0 +1,99 @@ +#include "meta.h" +#include "../util.h" + +/* MPDS - found in Big Air Freestyle, Terminator 3 (no coeffs), etc */ +VGMSTREAM * init_vgmstream_ngc_dsp_mpds(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int ch1_start=-1, ch2_start=-1; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D504453) /* "MPDS" */ + goto fail; + /* Version byte ??? */ + if (read_32bitBE(0x04,streamFile) != 0x00010000) /* "0x10000" */ + goto fail; + /* compare sample count with body size */ + if (((read_32bitBE(0x08,streamFile)/7*8)) != (read_32bitBE(0x0C,streamFile))) + goto fail; + + channel_count = read_32bitBE(0x14,streamFile); + + if (channel_count > 2) + { + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + ch1_start = 0x80; + } + else if (channel_count == 2) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x18,streamFile); + ch1_start = 0x80; + ch2_start = 0x80 + vgmstream->interleave_block_size; + } + else + { + goto fail; + } + + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x08,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); + } + + vgmstream->meta_type = meta_NGC_DSP_MPDS; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x24+i*2,streamFile); + + if (channel_count == 2) + { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x4C+i*2,streamFile); + } + } + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + vgmstream->ch[0].channel_start_offset = + vgmstream->ch[0].offset=ch1_start; + + if (channel_count == 2) + { + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) goto fail; + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset=ch2_start; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c new file mode 100644 index 000000000..81f13724d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_std.c @@ -0,0 +1,2464 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" +#include "../util.h" + +/* If these variables are packed properly in the struct (one after another) + * then this is actually how they are laid out in the file, albeit big-endian */ + +struct dsp_header { + uint32_t sample_count; + uint32_t nibble_count; + uint32_t sample_rate; + uint16_t loop_flag; + uint16_t format; + uint32_t loop_start_offset; + uint32_t loop_end_offset; + uint32_t ca; + int16_t coef[16]; /* really 8x2 */ + uint16_t gain; + uint16_t initial_ps; + int16_t initial_hist1; + int16_t initial_hist2; + uint16_t loop_ps; + int16_t loop_hist1; + int16_t loop_hist2; +}; + +/* nonzero on failure */ +static int read_dsp_header(struct dsp_header *header, off_t offset, STREAMFILE *file) { + int i; + uint8_t buf[0x4a]; /* usually padded out to 0x60 */ + if (read_streamfile(buf, offset, 0x4a, file) != 0x4a) return 1; + + header->sample_count = + get_32bitBE(buf+0x00); + header->nibble_count = + get_32bitBE(buf+0x04); + header->sample_rate = + get_32bitBE(buf+0x08); + header->loop_flag = + get_16bitBE(buf+0x0c); + header->format = + get_16bitBE(buf+0x0e); + header->loop_start_offset = + get_32bitBE(buf+0x10); + header->loop_end_offset = + get_32bitBE(buf+0x14); + header->ca = + get_32bitBE(buf+0x18); + for (i=0; i < 16; i++) + header->coef[i] = + get_16bitBE(buf+0x1c+i*2); + header->gain = + get_16bitBE(buf+0x3c); + header->initial_ps = + get_16bitBE(buf+0x3e); + header->initial_hist1 = + get_16bitBE(buf+0x40); + header->initial_hist2 = + get_16bitBE(buf+0x42); + header->loop_ps = + get_16bitBE(buf+0x44); + header->loop_hist1 = + get_16bitBE(buf+0x46); + header->loop_hist2 = + get_16bitBE(buf+0x48); + + return 0; +} + +/* the standard .dsp, as generated by DSPADPCM.exe */ + +VGMSTREAM * init_vgmstream_ngc_dsp_std(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct dsp_header header; + const off_t start_offset = 0x60; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + if (read_dsp_header(&header, 0, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (header.format || header.gain) + goto fail; + + /* Check for a matching second header. If we find one and it checks + * out thoroughly, we're probably not dealing with a genuine mono DSP. + * In many cases these will pass all the other checks, including the + * predictor/scale check if the first byte is 0 */ + { + struct dsp_header header2; + + read_dsp_header(&header2, 0x60, streamFile); + + if (header.sample_count == header2.sample_count && + header.nibble_count == header2.nibble_count && + header.sample_rate == header2.sample_rate && + header.loop_flag == header2.loop_flag) goto fail; + } + + if (header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = header.loop_start_offset/16*8; + if (header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + } + + /* compare num_samples with nibble count */ + /* + fprintf(stderr,"num samples (literal): %d\n",read_32bitBE(0,streamFile)); + fprintf(stderr,"num samples (nibbles): %d\n",dsp_nibbles_to_samples(read_32bitBE(4,streamFile))); + */ + + /* build the VGMSTREAM */ + + + vgmstream = allocate_vgmstream(1,header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = header.sample_count; + vgmstream->sample_rate = header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + header.loop_end_offset)+1; + + /* don't know why, but it does happen*/ + if (vgmstream->loop_end_sample > vgmstream->num_samples) + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_STD; + + /* coeffs */ + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = header.coef[i]; + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* Some very simple stereo variants of standard dsp just use the standard header + * twice and add interleave, or just concatenate the channels. We'll support + * them all here. + * Note that Cstr isn't here, despite using the form of the standard header, + * because its loop values are wacky. */ + +/* .stm + * Used in Paper Mario 2, Fire Emblem: Path of Radiance, Cubivore + * I suspected that this was an Intelligent Systems format, but its use in + * Cubivore calls that into question. */ +VGMSTREAM * init_vgmstream_ngc_dsp_stm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct dsp_header ch0_header, ch1_header; + int i; + int stm_header_sample_rate; + int channel_count; + const off_t start_offset = 0x100; + off_t first_channel_size; + off_t second_channel_start; + + /* check extension, case insensitive */ + /* to avoid collision with Scream Tracker 2 Modules, also ending in .stm + * and supported by default in Winamp, it was policy in the old days to + * rename these files to .dsp */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("stm",filename_extension(filename)) && + strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check intro magic */ + if (read_16bitBE(0, streamFile) != 0x0200) goto fail; + + channel_count = read_32bitBE(4, streamFile); + /* only stereo and mono are known */ + if (channel_count != 1 && channel_count != 2) goto fail; + + first_channel_size = read_32bitBE(8, streamFile); + /* this is bad rounding, wastes space, but it looks like that's what's + * used */ + second_channel_start = ((start_offset+first_channel_size)+0x20)/0x20*0x20; + + /* an additional check */ + stm_header_sample_rate = (uint16_t)read_16bitBE(2, streamFile); + + /* read the DSP headers */ + if (read_dsp_header(&ch0_header, 0x40, streamFile)) goto fail; + if (channel_count == 2) { + if (read_dsp_header(&ch1_header, 0xa0, streamFile)) goto fail; + } + + /* checks for fist channel */ + { + if (ch0_header.sample_rate != stm_header_sample_rate) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + } + } + + + /* checks for second channel */ + if (channel_count == 2) { + if (ch1_header.sample_rate != stm_header_sample_rate) goto fail; + + /* check for agreement with first channel header */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + /* check initial predictor/scale */ + if (ch1_header.initial_ps != (uint8_t)read_8bit(second_channel_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch1_header.format || ch1_header.gain) + goto fail; + + if (ch1_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch1_header.loop_start_offset/16*8; + /*printf("loop_start_offset=%x\nloop_ps=%x\nloop_off=%x\n",ch1_header.loop_start_offset,ch1_header.loop_ps,second_channel_start+loop_off);*/ + if (ch1_header.loop_ps != (uint8_t)read_8bit(second_channel_start+loop_off,streamFile)) + goto fail; + } + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count, ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + /* don't know why, but it does happen*/ + if (vgmstream->loop_end_sample > vgmstream->num_samples) + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_STM; + + /* coeffs */ + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + + if (channel_count == 2) { + /* coeffs */ + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + } + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + if (channel_count == 2) { + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=second_channel_start; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* mpdsp: looks like a standard .dsp header, but the data is actually + * interleaved stereo + * The files originally had a .dsp extension, we rename them to .mpdsp so we + * can catch this. + */ + +VGMSTREAM * init_vgmstream_ngc_mpdsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct dsp_header header; + const off_t start_offset = 0x60; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mpdsp",filename_extension(filename))) goto fail; + + if (read_dsp_header(&header, 0, streamFile)) goto fail; + + /* none have loop flag set, save us from loop code that involves them */ + if (header.loop_flag) goto fail; + + /* check initial predictor/scale */ + if (header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (header.format || header.gain) + goto fail; + + /* build the VGMSTREAM */ + + + /* no loop flag, but they do loop */ + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = header.sample_count/2; + vgmstream->sample_rate = header.sample_rate; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0xf000; + vgmstream->meta_type = meta_DSP_MPDSP; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = header.initial_hist2; + + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* str: a very simple header format with implicit loop values + * it's allways in interleaved stereo format + */ +VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + const off_t start_offset = 0x60; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* always 0xFAAF0001 @ offset 0 */ + if (read_32bitBE(0x00,streamFile)!=0xFAAF0001) goto fail; + + /* build the VGMSTREAM */ + /* always loop & stereo */ + vgmstream = allocate_vgmstream(2,1); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x08,streamFile); + vgmstream->sample_rate = read_32bitBE(0x04,streamFile); + + /* always loop to the beginning */ + vgmstream->loop_start_sample=0; + vgmstream->loop_end_sample=vgmstream->num_samples; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile); + vgmstream->meta_type = meta_DSP_STR; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+(i*2),streamFile); + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x30+(i*2),streamFile); + } + + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* a bunch of formats that are identical except for file extension, + * but have different interleaves */ + +VGMSTREAM * init_vgmstream_ngc_dsp_std_int(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + const off_t start_offset = 0xc0; + off_t interleave; + int meta_type; + + struct dsp_header ch0_header,ch1_header; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strlen(filename) > 7 && !strcasecmp("_lr.dsp",filename+strlen(filename)-7)) { + /* Bomberman Jetters */ + interleave = 0x14180; + meta_type = meta_DSP_JETTERS; + } else if (!strcasecmp("mss",filename_extension(filename))) { + interleave = 0x1000; + meta_type = meta_DSP_MSS; + } else if (!strcasecmp("gcm",filename_extension(filename))) { + interleave = 0x8000; + meta_type = meta_DSP_GCM; + } else goto fail; + + if (read_dsp_header(&ch0_header, 0, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, 0x60, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_type; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* sadb - .SAD files, two standard DSP headers */ +VGMSTREAM * init_vgmstream_sadb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t start_offset; + off_t interleave; + + struct dsp_header ch0_header,ch1_header; + int i; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sad",filename_extension(filename))) goto fail; + + /* check header magic */ + if (read_32bitBE(0x0,streamFile) != 0x73616462) goto fail; /* "sadb" */ + + channel_count = read_8bit(0x32, streamFile); + if (channel_count != 1 && channel_count != 2) goto fail; + + if (read_dsp_header(&ch0_header, 0x80, streamFile)) goto fail; + if (channel_count == 2 && read_dsp_header(&ch1_header, 0xe0, streamFile)) goto fail; + + start_offset = read_32bitBE(0x48,streamFile); + interleave = 16; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + if (channel_count == 2 && ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + (channel_count == 2 &&(ch1_header.format || ch1_header.gain))) + goto fail; + + /* check for agreement */ + if ( channel_count == 2 &&( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + )) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/8/channel_count*8; + loop_off = (loop_off/interleave*interleave*channel_count) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (channel_count == 2 && + ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = channel_count == 2 ? layout_interleave : layout_none; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_SADB; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + if (channel_count == 2) + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (channel_count == 2) { + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + } + + if (!vgmstream->ch[0].streamfile) goto fail; + /* open the file for reading */ + for (i=0;ich[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* AMTS - .amts files */ +VGMSTREAM * init_vgmstream_amts(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t start_offset; + off_t interleave; + int channel_count; + + struct dsp_header ch0_header,ch1_header; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("amts",filename_extension(filename))) goto fail; + + /* check header magic */ + if (read_32bitBE(0x0,streamFile) != 0x414D5453) goto fail; /* "sadb" */ + + channel_count=read_32bitBE(0x14,streamFile); + start_offset = 0x800; + interleave = read_32bitBE(0x08,streamFile); + + if (read_dsp_header(&ch0_header, 0x20, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + + if(channel_count==2) { + if (read_dsp_header(&ch1_header, 0x80, streamFile)) goto fail; + + if (ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } + + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_AMTS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if(channel_count==2) { + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + } + + if (!vgmstream->ch[0].streamfile) goto fail; + /* open the file for reading */ + for (i=0;ich[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* .wsi as found in Alone in the Dark for Wii */ +/* These appear to be standard .dsp, but interleaved in a blocked format */ + +VGMSTREAM * init_vgmstream_wsi(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header header[2]; + off_t start_offset[2]; + + int channel_count; + size_t est_block_size = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wsi",filename_extension(filename))) goto fail; + + /* I don't know if this is actually the channel count, or a block type + for the first block. Won't know until I see a mono .wsi */ + channel_count = read_32bitBE(0x04,streamFile); + + /* I've only allocated two headers, and I want to be alerted if a mono + .wsi shows up */ + if (channel_count != 2) goto fail; + + /* check for consistent block headers */ + { + off_t check_offset; + off_t block_size_has_been; + int i; + + check_offset = read_32bitBE(0x0,streamFile); + if (check_offset < 8) goto fail; + + block_size_has_been = check_offset; + + /* check 4 blocks, to get an idea */ + for (i=0;i<4*channel_count;i++) { + off_t block_size; + block_size = read_32bitBE(check_offset,streamFile); + + /* expect at least the block header */ + if (block_size < 0x10) goto fail; + + /* expect the channel numbers to alternate */ + if (i%channel_count+1 != read_32bitBE(check_offset+8,streamFile)) goto fail; + + /* expect every block in a set of channels to have the same size */ + if (i%channel_count==0) block_size_has_been = block_size; + else if (block_size != block_size_has_been) goto fail; + + /* get an estimate of block size for buffer sizing */ + if (block_size > est_block_size) est_block_size = block_size; + + check_offset += block_size; + } + } + + /* look at DSP headers */ + + { + off_t check_offset; + int i; + + check_offset = read_32bitBE(0x0,streamFile); + + for (i=0;inum_samples = header[0].sample_count/14*14; + vgmstream->sample_rate = header[0].sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + header[0].loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + header[0].loop_end_offset)+1; + + /* don't know why, but it does happen*/ + 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_wsi_blocked; + vgmstream->meta_type = meta_DSP_WSI; + + /* coeffs */ + { + int i,j; + for (j=0;jch[j].adpcm_coef[i] = header[j].coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[j].adpcm_history1_16 = header[j].initial_hist1; + vgmstream->ch[j].adpcm_history2_16 = header[j].initial_hist2; + } + } + + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,est_block_size*4); + + if (!vgmstream->ch[0].streamfile) goto fail; + + wsi_block_update(read_32bitBE(0,streamFile),vgmstream); + + { + int i; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset[i]; + } + + } + + /* first block isn't full of musics */ + vgmstream->current_block_size -= 0x60; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* SWD (found in Conflict - Desert Storm 1 & 2 */ +VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + off_t interleave; + + struct dsp_header ch0_header, ch1_header; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("swd",filename_extension(filename))) goto fail; + + if (read_dsp_header(&ch0_header, 0x08, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, 0x68, streamFile)) goto fail; + + /* check header magic */ + if (read_32bitBE(0x00,streamFile) != 0x505346D1) /* PSF\0xD1 */ + goto fail; + + start_offset = 0xC8; + interleave = 0x8; + +#if 0 + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; +#endif + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + +#if 0 + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } +#endif + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_NGC_SWD; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + + if (!vgmstream->ch[0].streamfile) goto fail; + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* IDSP .gcm files, two standard DSP headers */ +/* found in: Lego Batman (Wii) + Lego Indiana Jones - The Original Adventures (Wii) + Lego Indiana Jones 2 - The Adventure Continues (Wii) + Lego Star Wars - The Complete Saga (Wii) + The Chronicles of Narnia - Prince Caspian (Wii) */ +VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + off_t interleave; + struct dsp_header ch0_header,ch1_header; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if ((strcasecmp("gcm",filename_extension(filename))) && + (strcasecmp("idsp",filename_extension(filename)))) + goto fail; + + /* check header magic */ + if (read_32bitBE(0x0,streamFile) != 0x49445350) goto fail; /* "IDSP" */ + + /* different versions? */ + if (read_32bitBE(0x4, streamFile) == 1 && + read_32bitBE(0x8, streamFile) == 0xc8) + { + if (read_dsp_header(&ch0_header, 0x10, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, 0x70, streamFile)) goto fail; + + start_offset = 0xd0; + } + else if (read_32bitBE(0x4, streamFile) == 2 && + read_32bitBE(0x8, streamFile) == 0xd2) + { + if (read_dsp_header(&ch0_header, 0x20, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, 0x80, streamFile)) goto fail; + + start_offset = 0xe0; + } + else goto fail; + + interleave = read_32bitBE(0xc, streamFile); + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + /* TODO: adjust for interleave? */ + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_WII_IDSP; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + vgmstream->ch[1].streamfile = vgmstream->ch[0].streamfile; + + if (!vgmstream->ch[0].streamfile) goto fail; + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* .wsd files, two DSP files stuck together */ +/* found in Phantom Brave Wii */ +VGMSTREAM * init_vgmstream_wii_wsd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t channel_1_start, channel_2_start, channel_1_size, channel_2_size; + + struct dsp_header ch0_header,ch1_header; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wsd",filename_extension(filename))) goto fail; + + /* read .wsd header */ + channel_1_start = read_32bitBE(0x0,streamFile); + channel_2_start = read_32bitBE(0x4,streamFile); + channel_1_size = read_32bitBE(0x8,streamFile); + channel_2_size = read_32bitBE(0xc,streamFile); + + /* check header */ + if (channel_1_size != channel_2_size) goto fail; + if (channel_1_start != 0x20) goto fail; + if (channel_1_size < 0x20 || channel_2_size < 0x20) goto fail; + if (channel_1_start + channel_1_size > channel_2_start) goto fail; + if (channel_2_start + channel_2_size > get_streamfile_size(streamFile)) + goto fail; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, channel_1_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, channel_2_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != + (uint8_t)read_8bit(channel_1_start + 0x60, streamFile)) + goto fail; + + if (ch1_header.initial_ps != + (uint8_t)read_8bit(channel_2_start + 0x60, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + if (ch0_header.loop_ps != + (uint8_t)read_8bit(channel_1_start+0x60+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != + (uint8_t)read_8bit(channel_2_start+0x60+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_WII_WSD; + + /* coeffs */ + { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset = + vgmstream->ch[0].offset=channel_1_start+0x60; + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset=channel_2_start+0x60; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* .ddsp files, two DSP files stuck together, without additional header */ +VGMSTREAM * init_vgmstream_dsp_ddsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t channel_1_start, channel_2_start, channel_1_size, channel_2_size; + + struct dsp_header ch0_header,ch1_header; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ddsp",filename_extension(filename))) goto fail; + + /* read .wsd header */ + channel_1_start = 0; + channel_2_start = (get_streamfile_size(streamFile)/2); + channel_1_size = (get_streamfile_size(streamFile)/2)-0x60; + channel_2_size = (get_streamfile_size(streamFile)/2)-0x60; + + /* check header */ + if (channel_1_size != channel_2_size) goto fail; + if (channel_1_start != 0x0) goto fail; + if (channel_1_size < 0x20 || channel_2_size < 0x20) goto fail; + if (channel_1_start + channel_1_size > channel_2_start) goto fail; + if (channel_2_start + channel_2_size > get_streamfile_size(streamFile)) + goto fail; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, channel_1_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, channel_2_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != + (uint8_t)read_8bit(channel_1_start + 0x60, streamFile)) + goto fail; + + if (ch1_header.initial_ps != + (uint8_t)read_8bit(channel_2_start + 0x60, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + if (ch0_header.loop_ps != + (uint8_t)read_8bit(channel_1_start+0x60+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != + (uint8_t)read_8bit(channel_2_start+0x60+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_DDSP; + + /* coeffs */ + { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset = + vgmstream->ch[0].offset=channel_1_start+0x60; + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset=channel_2_start+0x60; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* .was files, DSP file(s), with additional iSWS header */ +VGMSTREAM * init_vgmstream_wii_was(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if ((strcasecmp("dsp",filename_extension(filename))) && + (strcasecmp("isws",filename_extension(filename))) && + (strcasecmp("was",filename_extension(filename)))) + goto fail; + + /* read iSWS header */ + if (read_32bitBE(0x0,streamFile) != 0x69535753) + goto fail; + + channel_count = read_32bitBE(0x08,streamFile); + + if (channel_count == 1) + { + + ch1_header_start = 0x20; + ch1_start = 0x80; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(1,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_WII_WAS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + } + else if (channel_count == 2) + { + + + ch1_header_start = 0x20; + ch2_header_start = 0x80; + ch1_start = 0xE0; + ch2_start = 0xE0 + (read_32bitBE(0x10,streamFile)); + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x10,streamFile); + vgmstream->meta_type = meta_WII_WAS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + } + else + { + goto fail; + } + + return vgmstream; + + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* .str found in Micro Machines, Superman: Shadow of Apokolips */ +VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) + goto fail; + + channel_count = 2; + + ch1_header_start = 0x00; + ch2_header_start = 0x80; + ch1_start = 0x800; + ch2_start = 0x4800; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x4000; + vgmstream->meta_type = meta_DSP_STR_IG; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* .dsp found in: Speed Challenge - Jacques Villeneuve's Racing Vision (NGC) + XIII (NGC) + always 2 channels, and an interleave of 0x8 */ +VGMSTREAM * init_vgmstream_dsp_xiii(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) + goto fail; + + channel_count = 2; + + ch1_header_start = 0x00; + ch2_header_start = 0x60; + ch1_start = 0xC0; + ch2_start = 0xC8; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + //ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = 0x0; //ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,ch1_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = 0x0; //dsp_nibbles_to_samples(ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8; + vgmstream->meta_type = meta_DSP_XIII; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* .ndp found in Vertigo (WII) */ +VGMSTREAM * init_vgmstream_wii_ndp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ndp",filename_extension(filename))) + goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x4E445000) /* NDP */ + goto fail; + + /* check size */ + if ((read_32bitLE(0x8,streamFile)+0x18 != get_streamfile_size(streamFile))) /* NDP */ + goto fail; + + channel_count = (read_16bitLE(0x10,streamFile) != 2); + + ch1_header_start = 0x18; + ch2_header_start = 0x78; + ch1_start = 0xD8; + ch2_start = 0xDC; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave_byte; + vgmstream->interleave_block_size = 0x4; + vgmstream->meta_type = meta_WII_NDP; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* found in "Cabelas" games, always stereo, looped and an interleave of 0x10 bytes */ +VGMSTREAM * init_vgmstream_dsp_cabelas(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) + goto fail; + + channel_count = 2; + + ch1_header_start = 0x00; + ch2_header_start = 0x60; + ch1_start = 0xC0; + ch2_start = 0xD0; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,1); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = dsp_nibbles_to_samples(ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_DSP_CABELAS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* dual dsp header with additional "AAAp" header, found in Vexx (NGC) and Turok: Evolution (NGC) */ +VGMSTREAM * init_vgmstream_ngc_dsp_aaap(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) + goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x41414170) /* AAAp */ + goto fail; + + channel_count = (uint16_t)read_16bitBE(0x6,streamFile); + + ch1_header_start = 0x08; + ch2_header_start = 0x68; + ch1_start = 0xC8; + ch2_start = ch1_start + (uint16_t)read_16bitBE(0x4,streamFile); + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = ch2_start-ch1_start; + vgmstream->meta_type = meta_NGC_DSP_AAAP; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* .dspw files, two DSP files stuck together */ +/* found in Sengoku Basara 3 Wii */ +VGMSTREAM * init_vgmstream_dsp_dspw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t channel_1_start, channel_2_start; + + struct dsp_header ch0_header,ch1_header; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dspw",filename_extension(filename))) goto fail; + + if (read_32bitBE(0x0,streamFile) != 0x44535057) // DSPW + goto fail; + + /* read .dspw header */ + channel_1_start = 0x20; + channel_2_start = (get_streamfile_size(streamFile)/2)+0x10; + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, channel_1_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, channel_2_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != + (uint8_t)read_8bit(channel_1_start + 0x60, streamFile)) + goto fail; + + if (ch1_header.initial_ps != + (uint8_t)read_8bit(channel_2_start + 0x60, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain || + ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + if (ch0_header.loop_ps != + (uint8_t)read_8bit(channel_1_start+0x60+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != + (uint8_t)read_8bit(channel_2_start+0x60+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_DSPW; + + /* coeffs */ + { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset = + vgmstream->ch[0].offset=channel_1_start+0x60; + vgmstream->ch[1].channel_start_offset = + vgmstream->ch[1].offset=channel_2_start+0x60; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* dual dsp header with additional "iadp" header, found in Dr. Muto (NGC) */ +VGMSTREAM * init_vgmstream_ngc_dsp_iadp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + struct dsp_header ch0_header,ch1_header; + off_t ch1_header_start, ch2_header_start, ch1_start, ch2_start; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("iadp",filename_extension(filename))) + goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x69616470) /* iadp */ + goto fail; + + channel_count = read_32bitBE(0x4,streamFile); + + if (channel_count != 0x2) + goto fail; + + + ch1_header_start = 0x20; + ch2_header_start = 0x80; + ch1_start = read_32bitBE(0x1C,streamFile); + ch2_start = ch1_start + read_32bitBE(0x8,streamFile); + + /* get DSP headers */ + if (read_dsp_header(&ch0_header, ch1_header_start, streamFile)) goto fail; + if (read_dsp_header(&ch1_header, ch2_header_start, streamFile)) goto fail; + + /* check initial predictor/scale */ + if (ch0_header.initial_ps != (uint8_t)read_8bit(ch1_start, streamFile)) + goto fail; + if (ch1_header.initial_ps != (uint8_t)read_8bit(ch2_start, streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (ch0_header.format || ch0_header.gain) + goto fail; + if (ch1_header.format || ch1_header.gain) + goto fail; + + /* check for agreement */ + if ( + ch0_header.sample_count != ch1_header.sample_count || + ch0_header.nibble_count != ch1_header.nibble_count || + ch0_header.sample_rate != ch1_header.sample_rate || + ch0_header.loop_flag != ch1_header.loop_flag || + ch0_header.loop_start_offset != ch1_header.loop_start_offset || + ch0_header.loop_end_offset != ch1_header.loop_end_offset + ) goto fail; + + if (ch0_header.loop_flag) + { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + + if (ch0_header.loop_ps != (uint8_t)read_8bit(ch1_start+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(ch2_start+loop_off,streamFile)) + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,ch0_header.loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = ch0_header.sample_count; + vgmstream->sample_rate = ch0_header.sample_rate; + + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->interleave_block_size = read_32bitBE(0x8,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_NGC_DSP_IADP; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = ch0_header.coef[i]; + vgmstream->ch[1].adpcm_coef[i] = ch1_header.coef[i]; + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = ch0_header.initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = ch0_header.initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = ch1_header.initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = ch1_header.initial_hist2; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) + goto fail; + vgmstream->ch[0].channel_start_offset = vgmstream->ch[0].offset=ch1_start; + + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[1].streamfile) + goto fail; + vgmstream->ch[1].channel_start_offset = vgmstream->ch[1].offset=ch2_start; + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} \ No newline at end of file diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c new file mode 100644 index 000000000..76de70baf --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_dsp_ygo.c @@ -0,0 +1,74 @@ +#include "meta.h" +#include "../util.h" + +/* .dsp found in: + Hikaru No Go 3 (NGC) + Yu-Gi-Oh! The Falsebound Kingdom (NGC) + + 2010-01-31 - added loop stuff and some header checks... +*/ + +VGMSTREAM * init_vgmstream_dsp_ygo(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check file size with size given in header */ + if ((read_32bitBE(0x0,streamFile)+0xE0) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = (uint16_t)(read_16bitBE(0x2C,streamFile) != 0x0); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0xE0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x28,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x20,streamFile); + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_YGO; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile)*14/16); + vgmstream->loop_end_sample = (read_32bitBE(0x34,streamFile)*14/16); + } + + // read coef stuff + { + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_ffcc_str.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ffcc_str.c new file mode 100644 index 000000000..ac875b1e1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ffcc_str.c @@ -0,0 +1,85 @@ +#include "meta.h" +#include "../util.h" + +/* STR (Final Fantasy: Crystal Chronicles) */ +VGMSTREAM * init_vgmstream_ngc_ffcc_str(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53545200 || /* "STR\0" */ + read_32bitBE(0x08,streamFile) != get_streamfile_size(streamFile) || + read_32bitBE(0x10,streamFile) != -1) /* this might be loop point */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitBE(0x18,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x1000; + vgmstream->channels = channel_count; + if (read_32bitBE(0x14,streamFile)==0) + vgmstream->sample_rate = 32000; + else + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)*14; + + if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1000; + } + else + { + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x1000; + } + vgmstream->meta_type = meta_FFCC_STR; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int c; + for (c=0;cch[c].adpcm_coef[i] = read_16bitBE(0x20 + c * 0x2e + i * 2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_gcub.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_gcub.c new file mode 100644 index 000000000..929fde3a8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_gcub.c @@ -0,0 +1,103 @@ +#include "meta.h" +#include "../util.h" + +/* GCUB - found in 'Sega Soccer Slam' */ +VGMSTREAM * init_vgmstream_ngc_gcub(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gcub",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x47437562) /* "GCub" */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitBE(0x04,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (read_32bitBE(0x60,streamFile) == 0x47437878) /* "GCxx" */ + { + start_offset = 0x88; + } + else + { + start_offset = 0x60; + } + + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x08,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14; + } + + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; // read_32bitBE(0x04,streamFile); + } + + vgmstream->meta_type = meta_NGC_GCUB; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x30+i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + /* The first channel */ + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + /* The second channel */ + if (channel_count == 2) { + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=start_offset+vgmstream->interleave_block_size; + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_lps.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_lps.c new file mode 100644 index 000000000..6957a782f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_lps.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* LPS (found in Rave Master (Groove Adventure Rave)(GC) */ +VGMSTREAM * init_vgmstream_ngc_lps(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("lps",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x8,streamFile) != 0x10000000) + goto fail; + + loop_flag = read_32bitBE(0x30,streamFile); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x60; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x28,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0x34,streamFile))/16*14; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x30,streamFile))/16*14; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_NGC_LPS; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); + } + } + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_nst_dsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_nst_dsp.c new file mode 100644 index 000000000..98f8deb45 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_nst_dsp.c @@ -0,0 +1,89 @@ +#include "meta.h" +#include "../util.h" + +/* DSP (Animaniacs: The Great Edgar Hunt) */ +// NOTE: The second dsp header is just a dummy, both channels +// use the same coef table (0x20) + +VGMSTREAM * init_vgmstream_ngc_nst_dsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != read_32bitBE(0x54,streamFile)) + goto fail; + if (read_32bitBE(0x4,streamFile) != read_32bitBE(0x58,streamFile)) + goto fail; + if (read_32bitBE(0x8,streamFile) != read_32bitBE(0x5C,streamFile)) + goto fail; + if (read_32bitBE(0xC,streamFile) != read_32bitBE(0x60,streamFile)) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0xAC; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x14,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x8,streamFile); + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = 0; + } +#endif + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_NGC_NST_DSP; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c new file mode 100644 index 000000000..8417c74d3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_pdt.c @@ -0,0 +1,101 @@ +#include "meta.h" +#include "../util.h" + +/* PDT - Custom Generated File (Mario Party) */ +VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + int second_channel_start = -1; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pdt",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x50445420) /* "PDT " */ + goto fail; + if (read_32bitBE(0x04,streamFile) != 0x44535020) /* "DSP " */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x48454144) /* "HEAD " */ + goto fail; + if (read_16bitBE(0x0C,streamFile) != 0x4552) /* "ER " */ + goto fail; + + loop_flag = (read_32bitBE(0x1C,streamFile)!=2); + channel_count = (uint16_t)(read_16bitLE(0x0E,streamFile)); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x14,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + + 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; + } + second_channel_start = (get_streamfile_size(streamFile)+start_offset)/2; + } + else + { + goto fail; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_NGC_PDT; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x50+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[0].channel_start_offset=start_offset; + if (channel_count == 2) { + if (second_channel_start == -1) goto fail; + vgmstream->ch[1].channel_start_offset=second_channel_start; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c new file mode 100644 index 000000000..7f5610c32 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_sck_dsp.c @@ -0,0 +1,98 @@ +#include "meta.h" +#include "../util.h" + +/* + SCK+DSP + 2009-08-25 - manakoAT : Scorpion King (NGC)... +*/ + +VGMSTREAM * init_vgmstream_ngc_sck_dsp(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileDSP = NULL; + char filename[PATH_LIMIT]; + char filenameDSP[260]; + + int i; + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sck",filename_extension(filename))) goto fail; + + + strcpy(filenameDSP,filename); + strcpy(filenameDSP+strlen(filenameDSP)-3,"dsp"); + + streamFileDSP = streamFile->open(streamFile,filenameDSP,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (read_32bitBE(0x5C,streamFile) != 0x60A94000) + goto fail; + + if (!streamFile) goto fail; + + channel_count = 2; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x18,streamFile); + vgmstream->num_samples=read_32bitBE(0x14,streamFile)/8/channel_count*14; + vgmstream->coding_type = coding_NGC_DSP; + + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x10,streamFile)/8/channel_count*14; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size=read_32bitBE(0xC,streamFile); + } + + + + vgmstream->meta_type = meta_NGC_SCK_DSP; + + /* open the file for reading */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFileDSP,filenameDSP,0x8000); + vgmstream->ch[i].offset = 0; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x2C+i*2,streamFile); + } + } + } + + + close_streamfile(streamFileDSP); streamFileDSP=NULL; + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileDSP) close_streamfile(streamFileDSP); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_ssm.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ssm.c new file mode 100644 index 000000000..fa82d3627 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ssm.c @@ -0,0 +1,96 @@ +#include "meta.h" +#include "../util.h" + +/* SSM (Golden Gashbell Full Power GC) */ +VGMSTREAM * init_vgmstream_ngc_ssm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + int coef1_start; + int coef2_start; + int second_channel_start; + + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ssm",filename_extension(filename))) + goto fail; + + /* check header */ +#if 0 + if (read_32bitBE(0x00,streamFile) != 0x0) + goto fail; +#endif + + loop_flag = (uint32_t)read_16bitBE(0x18,streamFile); + channel_count = read_32bitBE(0x10,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitBE(0x0,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x14,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x04,streamFile)*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x24,streamFile)*14/8/channel_count; + vgmstream->loop_end_sample = read_32bitBE(0x20,streamFile)*14/8/channel_count; + } + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_NGC_SSM; + + /* Retrieveing the coef tables and the start of the second channel*/ + coef1_start = 0x28; + coef2_start = 0x68; + second_channel_start = (read_32bitBE(0x04,streamFile)/2)+start_offset; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile); + } + } + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + /* The first channel */ + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + /* The second channel */ + if (channel_count == 2) { + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=second_channel_start; + } + } + + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_tydsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_tydsp.c new file mode 100644 index 000000000..37f3a6037 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_tydsp.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../util.h" + +/* TYDSP (Ty - The Tasmanian Tiger) */ +VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tydsp",filename_extension(filename))) goto fail; + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitBE(0x08,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t)(read_16bitBE(0x6C,streamFile)); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x00,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x00,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile); + vgmstream->meta_type = meta_NGC_TYDSP; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3E +i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_waa_wac_wad_wam.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_waa_wac_wad_wam.c new file mode 100644 index 000000000..c8f4905dd --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_waa_wac_wad_wam.c @@ -0,0 +1,182 @@ +#include "meta.h" +#include "../util.h" +/* +const short wad_coef[16][2] = +{ + {0x4002,0x2003}, + {0x2016,0xc600}, + {0xC600,0x98ab}, + {0x96bf,0x29c5}, + {0x2003,0x0081}, + {0x0e00,0x2004}, + {0x8e01,0xc500}, + {0x70bf,0x8128}, + {0x288e,0xc600}, + {0x016e,0x0e5b}, + {0xbe20,0x2003}, + {0x03c6,0xc600}, + {0x0048,0xe85a}, + {0xbe28,0x28c6}, + {0xc600,0x00F6}, + {0xbeab,0x5520} +};*/ +const short wad_coef[16] = +{ + 0x04ab, 0xfced, + 0x0789, 0xfedf, + 0x09a2, 0xfae5, + 0x0c90, 0xfac1, + 0x084d, 0xfaa4, + 0x0982, 0xfdf7, + 0x0af6, 0xfafa, + 0x0be6, 0xfbf5 +}; + + +/* WAC - WAD - WAM (Beyond Good & Evil GC/PS2) */ +/* Note: A "Flat Layout" has no interleave */ +VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int i; + off_t start_offset; + int loop_flag; + int channel_count; + int coef1_start; + int coef2_start; + int second_channel_start = -1; + + // Check file extensions + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("waa",filename_extension(filename)) && + strcasecmp("wac",filename_extension(filename)) && + strcasecmp("wad",filename_extension(filename)) && + strcasecmp("wam",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52494646 || /* "RIFF" */ + read_32bitBE(0x08,streamFile) != 0x57415645 || /* "WAVE" */ + read_32bitBE(0x0C,streamFile) != 0x666D7420 || /* "fmt\0x20" */ + read_32bitBE(0x10,streamFile) != 0x12000000) /* "0x12000000" */ + goto fail; + + /* files don't contain looping information, + so the looping is not done depending on extension. + wam and waa contain ambient sounds and music, so often they contain + looped music. Change extension to wac or wad to make the sound non-looping. + */ + loop_flag = strcasecmp("wac",filename_extension(filename)) && + strcasecmp("wad",filename_extension(filename)); + channel_count = (uint16_t)read_16bitLE(0x16,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* Check what encoder is needed */ + //FIXME: //PC version uses pcm, but which encoder? + + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + vgmstream->meta_type = meta_WAA_WAC_WAD_WAM; + vgmstream->layout_type = layout_none; + + switch((uint16_t)read_16bitLE(0x14,streamFile)) { + case 0x0069: // XBOX IMA ADPCM + start_offset = 0x2E; + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/36/channel_count*64; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/36/channel_count*64; + } + break; + case 0xFFFF: // PS2 ADPCM + start_offset = 0x2E; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))/16*28/channel_count; + } + second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+start_offset; + break; + case 0xFFFE: // GameCube/WII DSP + start_offset = 0x5C; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x2A,streamFile))*14/8/channel_count; + } + if(read_16bitLE(0x24,streamFile)==0x00)//is a wii file with no coeff table + { + //FIXME: WII version of WAM/WAD/WAC need some coeff table from somewhere + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = wad_coef[i]; + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = wad_coef[i]; + } + goto fail; + } + else + { + second_channel_start = (read_32bitLE(0x2A,streamFile)/2)+0x8A; + /* Retrieveing the coef tables */ + coef1_start = 0x2E; + coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C; + + { + int i; + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1_start+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2_start+i*2,streamFile); + } + } + } + break; + default: + goto fail; + } + + + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + if (vgmstream->coding_type == coding_XBOX) { + /* xbox interleaving is a little odd */ + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[0].channel_start_offset=start_offset; + if (channel_count == 2) { + if (second_channel_start == -1) goto fail; + vgmstream->ch[1].channel_start_offset=second_channel_start; + } + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + } + } + + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngc_ymf.c b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ymf.c new file mode 100644 index 000000000..9fad79ecb --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngc_ymf.c @@ -0,0 +1,77 @@ +#include "meta.h" +#include "../util.h" + +/* YMF (WWE WrestleMania X8) */ +VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ymf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00000180) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x180; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0xA8,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0xDC,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x20000; + vgmstream->meta_type = meta_NGC_YMF; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0xAE +i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x10E +i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ngca.c b/Frameworks/vgmstream/vgmstream/src/meta/ngca.c new file mode 100644 index 000000000..271be64ec --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ngca.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../util.h" + +/* NGCA (from GoldenEye 007) */ +VGMSTREAM * init_vgmstream_ngca(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ngca",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4E474341) /* "NGCA" */ + goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (((read_32bitBE(0x4,streamFile))/2) - 1) / 8 * 14; + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_NGCA; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0xC+i*2,streamFile); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nub.c b/Frameworks/vgmstream/vgmstream/src/meta/nub.c new file mode 100644 index 000000000..5a86426a4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nub.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +/* Stuff from NUB archives */ + +/* VAG (from Ridge Racer 7) */ +VGMSTREAM * init_vgmstream_nub_vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vag",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x76616700) /* "vag" */ + goto fail; + + if (read_32bitBE(0x30,streamFile)==0x3F800000) + loop_flag = 1; + else + loop_flag = 0; + + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0xC0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0xBC,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x14,streamFile)*28/32*2; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x20,streamFile)*28/32*2; + vgmstream->loop_end_sample = read_32bitBE(0x24,streamFile)*28/32*2; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_NUB_VAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/nwa.c b/Frameworks/vgmstream/vgmstream/src/meta/nwa.c new file mode 100644 index 000000000..d3f809935 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/nwa.c @@ -0,0 +1,358 @@ +#include "meta.h" +#include "../util.h" +#include "../coding/nwa_decoder.h" +#include +#include + +#ifdef WIN32 +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +/* NWA - Visual Art's streams */ + +VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int i; + int channel_count; + int loop_flag = 0; + int32_t loop_start_sample = 0; + int32_t loop_end_sample = 0; + int nwainfo_ini_found = 0; + int gameexe_ini_found = 0; + int just_pcm = 0; + int comp_level = -2; + nwa_codec_data *data = NULL; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("nwa",filename_extension(filename))) goto fail; + + channel_count = read_16bitLE(0x00,streamFile); + if (channel_count != 1 && channel_count != 2) goto fail; + + /* check if we're using raw pcm */ + if ( + read_32bitLE(0x08,streamFile)==-1 || /* compression level */ + read_32bitLE(0x10,streamFile)==0 || /* block count */ + read_32bitLE(0x18,streamFile)==0 || /* compressed data size */ + read_32bitLE(0x20,streamFile)==0 || /* block size */ + read_32bitLE(0x24,streamFile)==0 /* restsize */ + ) + { + just_pcm = 1; + } + else + { + comp_level = read_32bitLE(0x08,streamFile); + + data = malloc(sizeof(nwa_codec_data)); + if (!data) goto fail; + + data->nwa = open_nwa(streamFile,filename); + if (!data->nwa) goto fail; + } + + /* try to locate NWAINFO.INI in the same directory */ + { + char ininame[260]; + char * ini_lastslash; + char namebase_array[260]; + char *namebase; + STREAMFILE *inistreamfile; + + /* here we assume that the "special encoding" does not affect + * the directory separator */ + strncpy(ininame,filename,sizeof(ininame)); + ininame[sizeof(ininame)-1]='\0'; /* a pox on the stdlib! */ + + streamFile->get_realname(streamFile,namebase_array,sizeof(namebase_array)); + + ini_lastslash = strrchr(ininame,DIRSEP); + if (!ini_lastslash) { + strncpy(ininame,"NWAINFO.INI",sizeof(ininame)); + namebase = namebase_array; + } else { + strncpy(ini_lastslash+1,"NWAINFO.INI", + sizeof(ininame)-(ini_lastslash+1-ininame)); + namebase = strrchr(namebase_array,DIRSEP)+1; + } + ininame[sizeof(ininame)-1]='\0'; /* curse you, strncpy! */ + + inistreamfile = streamFile->open(streamFile,ininame,4096); + + if (inistreamfile) { + /* ini found, try to find our name */ + const char * ext; + int length; + int found; + off_t offset; + off_t file_size; + off_t found_off = -1; + + nwainfo_ini_found = 1; + + ext = filename_extension(namebase); + length = ext-1-namebase; + file_size = get_streamfile_size(inistreamfile); + + for (found = 0, offset = 0; !found && offset 0) loop_flag = 1; + } + } /* if found file name in INI */ + + close_streamfile(inistreamfile); + } /* if opened INI ok */ + } /* INI block */ + + /* try to locate Gameexe.ini in the same directory */ + { + char ininame[260]; + char * ini_lastslash; + char namebase_array[260]; + char * namebase; + STREAMFILE *inistreamfile; + + strncpy(ininame,filename,sizeof(ininame)); + ininame[sizeof(ininame)-1]='\0'; /* a pox on the stdlib! */ + + streamFile->get_realname(streamFile,namebase_array,sizeof(namebase_array)); + + ini_lastslash = strrchr(ininame,DIRSEP); + if (!ini_lastslash) { + strncpy(ininame,"Gameexe.ini",sizeof(ininame)); + namebase = namebase_array; + } else { + strncpy(ini_lastslash+1,"Gameexe.ini", + sizeof(ininame)-(ini_lastslash+1-ininame)); + namebase = strrchr(namebase_array,DIRSEP)+1; + } + ininame[sizeof(ininame)-1]='\0'; /* curse you, strncpy! */ + + inistreamfile = streamFile->open(streamFile,ininame,4096); + + if (inistreamfile) { + /* ini found, try to find our name */ + const char * ext; + int length; + int found; + off_t offset; + off_t file_size; + off_t found_off = -1; + + gameexe_ini_found = 1; + + ext = filename_extension(namebase); + length = ext-1-namebase; + file_size = get_streamfile_size(inistreamfile); + + /* format of line is: + * #DSTRACK = 00000000 - eeeeeeee - ssssssss = "name" = "name2?" + * ^22 ^33 ^45 ^57 + */ + + for (found = 0, offset = 0; !found && offsetchannels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + + vgmstream->num_samples = read_32bitLE(0x1c,streamFile)/channel_count; + + if (just_pcm) { + switch (read_16bitLE(0x02,streamFile)) { + case 8: + vgmstream->coding_type = coding_PCM8; + vgmstream->interleave_block_size = 1; + break; + case 16: + vgmstream->coding_type = coding_PCM16LE; + vgmstream->interleave_block_size = 2; + break; + default: + goto fail; + } + if (channel_count > 1) { + vgmstream->layout_type = layout_interleave; + } else { + vgmstream->layout_type = layout_none; + } + } + else + { + switch (comp_level) + { + case 0: + vgmstream->coding_type = coding_NWA0; + break; + case 1: + vgmstream->coding_type = coding_NWA1; + break; + case 2: + vgmstream->coding_type = coding_NWA2; + break; + case 3: + vgmstream->coding_type = coding_NWA3; + break; + case 4: + vgmstream->coding_type = coding_NWA4; + break; + case 5: + vgmstream->coding_type = coding_NWA5; + break; + default: + goto fail; + break; + } + vgmstream->layout_type = layout_none; + } + + if (nwainfo_ini_found) { + vgmstream->meta_type = meta_NWA_NWAINFOINI; + if (loop_flag) { + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } else if (gameexe_ini_found) { + vgmstream->meta_type = meta_NWA_GAMEEXEINI; + if (loop_flag) { + vgmstream->loop_start_sample = loop_start_sample; + vgmstream->loop_end_sample = loop_end_sample; + } + } else { + vgmstream->meta_type = meta_NWA; + } + + + if (just_pcm) { + /* open the file for reading by each channel */ + STREAMFILE *chstreamfile; + + /* have both channels use the same buffer, as interleave is so small */ + chstreamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=0x2c+(off_t)(i*vgmstream->interleave_block_size); + } + } + else + { + vgmstream->codec_data = data; + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + if (data) { + if (data->nwa) + { + close_nwa(data->nwa); + } + free(data); + } + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c new file mode 100644 index 000000000..835779bb5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ogg_vorbis_file.c @@ -0,0 +1,448 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_VORBIS + +#include +#include +#include "meta.h" +#include "../util.h" +#include + + +#define DEFAULT_BITSTREAM 0 + +static size_t read_func(void *ptr, size_t size, size_t nmemb, void * datasource) +{ + ogg_vorbis_streamfile * const ov_streamfile = datasource; + size_t items_read; + + size_t bytes_read; + + bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb, + ov_streamfile->streamfile); + + items_read = bytes_read / size; + + ov_streamfile->offset += items_read * size; + + return items_read; +} + +static size_t read_func_um3(void *ptr, size_t size, size_t nmemb, void * datasource) +{ + ogg_vorbis_streamfile * const ov_streamfile = datasource; + size_t items_read; + + size_t bytes_read; + + bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb, + ov_streamfile->streamfile); + + items_read = bytes_read / size; + + /* first 0x800 bytes of um3 are xor'd with 0xff */ + if (ov_streamfile->offset < 0x800) { + int num_crypt = 0x800-ov_streamfile->offset; + int i; + + if (num_crypt > bytes_read) num_crypt=bytes_read; + for (i=0;ioffset += items_read * size; + + return items_read; +} + +static size_t read_func_kovs(void *ptr, size_t size, size_t nmemb, void * datasource) +{ + ogg_vorbis_streamfile * const ov_streamfile = datasource; + size_t items_read; + + size_t bytes_read; + + bytes_read = read_streamfile(ptr, ov_streamfile->offset+ov_streamfile->other_header_bytes, size * nmemb, + ov_streamfile->streamfile); + + items_read = bytes_read / size; + + /* first 0x100 bytes of KOVS are xor'd with offset */ + if (ov_streamfile->offset < 0x100) { + int i; + + for (i=ov_streamfile->offset;i<0x100;i++) + ((uint8_t*)ptr)[i-ov_streamfile->offset] ^= i; + } + + ov_streamfile->offset += items_read * size; + + return items_read; +} + +static size_t read_func_scd(void *ptr, size_t size, size_t nmemb, void * datasource) +{ + ogg_vorbis_streamfile * const ov_streamfile = datasource; + size_t items_read; + + size_t bytes_read; + + bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb, + ov_streamfile->streamfile); + + items_read = bytes_read / size; + + /* first bytes are xor'd with a constant byte */ + if (ov_streamfile->offset < ov_streamfile->scd_xor_len) { + int num_crypt = ov_streamfile->scd_xor_len-ov_streamfile->offset; + int i; + + if (num_crypt > bytes_read) num_crypt=bytes_read; + for (i=0;iscd_xor; + } + + ov_streamfile->offset += items_read * size; + + return items_read; +} + +static size_t read_func_psych(void *ptr, size_t size, size_t nmemb, void * datasource) +{ + ogg_vorbis_streamfile * const ov_streamfile = datasource; + size_t items_read; + + size_t bytes_read; + size_t i; + + bytes_read = read_streamfile(ptr, ov_streamfile->offset + ov_streamfile->other_header_bytes, size * nmemb, + ov_streamfile->streamfile); + + /* add 0x23 ('#') */ + for (i=0;ioffset += items_read * size; + + return items_read; +} + +static int seek_func(void *datasource, ogg_int64_t offset, int whence) { + ogg_vorbis_streamfile * const ov_streamfile = datasource; + ogg_int64_t base_offset; + ogg_int64_t new_offset; + + switch (whence) { + case SEEK_SET: + base_offset = 0; + break; + case SEEK_CUR: + base_offset = ov_streamfile->offset; + break; + case SEEK_END: + base_offset = ov_streamfile->size - ov_streamfile->other_header_bytes; + break; + default: + return -1; + break; + } + + new_offset = base_offset + offset; + if (new_offset < 0 || new_offset > (ov_streamfile->size - ov_streamfile->other_header_bytes)) { + return -1; + } else { + ov_streamfile->offset = new_offset; + return 0; + } +} + +static long tell_func(void * datasource) { + ogg_vorbis_streamfile * const ov_streamfile = datasource; + return ov_streamfile->offset; +} + +/* setting close_func in ov_callbacks to NULL doesn't seem to work */ +static int close_func(void * datasource) { + return 0; +} + +/* Ogg Vorbis, by way of libvorbisfile */ + +VGMSTREAM * init_vgmstream_ogg_vorbis(STREAMFILE *streamFile) { + char filename[PATH_LIMIT]; + + ov_callbacks callbacks; + + off_t other_header_bytes = 0; + int um3_ogg = 0; + int kovs_ogg = 0; + int psych_ogg = 0; + + vgm_vorbis_info_t inf; + memset(&inf, 0, sizeof(inf)); + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + + /* It is only interesting to use oggs with vgmstream if they are looped. + To prevent such files from being played by other plugins and such they + may be renamed to .logg. This meta reader should still support .ogg, + though. */ + if (strcasecmp("logg",filename_extension(filename)) && + strcasecmp("ogg",filename_extension(filename))) { + if (!strcasecmp("um3",filename_extension(filename))) { + um3_ogg = 1; + } else if (!strcasecmp("kovs",filename_extension(filename))) { + kovs_ogg = 1; + } else { + goto fail; + } + } + + /* not all um3-ogg are crypted */ + if (um3_ogg && read_32bitBE(0x0,streamFile)==0x4f676753) { + um3_ogg = 0; + } + + /* use KOVS header */ + if (kovs_ogg) { + if (read_32bitBE(0x0,streamFile)!=0x4b4f5653) { /* "KOVS" */ + goto fail; + } + if (read_32bitLE(0x8,streamFile)!=0) { + inf.loop_start = read_32bitLE(0x8,streamFile); + inf.loop_flag = 1; + } + + other_header_bytes = 0x20; + } + + /* detect Psychic Software obfuscation (as seen in "Darkwind") */ + if (read_32bitBE(0x0,streamFile)==0x2c444430) { + psych_ogg = 1; + } + + if (um3_ogg) { + callbacks.read_func = read_func_um3; + } else if (kovs_ogg) { + callbacks.read_func = read_func_kovs; + } else if (psych_ogg) { + callbacks.read_func = read_func_psych; + } else { + callbacks.read_func = read_func; + } + callbacks.seek_func = seek_func; + callbacks.close_func = close_func; + callbacks.tell_func = tell_func; + + if (um3_ogg) { + inf.meta_type = meta_um3_ogg; + } else if (kovs_ogg) { + inf.meta_type = meta_KOVS_ogg; + } else if (psych_ogg) { + inf.meta_type = meta_psych_ogg; + } else { + inf.meta_type = meta_ogg_vorbis; + } + + inf.layout_type = layout_ogg_vorbis; + + return init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, &callbacks, other_header_bytes, &inf); + +fail: + return NULL; +} + +VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks_p, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf) { + VGMSTREAM * vgmstream = NULL; + + OggVorbis_File temp_ovf; + ogg_vorbis_streamfile temp_streamfile; + + ogg_vorbis_codec_data * data = NULL; + OggVorbis_File *ovf; + int inited_ovf = 0; + vorbis_info *info; + + int loop_flag = vgm_inf->loop_flag; + int32_t loop_start = vgm_inf->loop_start; + int loop_length_found = vgm_inf->loop_length_found; + int32_t loop_length = vgm_inf->loop_length; + int loop_end_found = vgm_inf->loop_end_found; + int32_t loop_end = vgm_inf->loop_end; + + ov_callbacks default_callbacks; + + if (!callbacks_p) { + default_callbacks.read_func = read_func; + default_callbacks.seek_func = seek_func; + default_callbacks.close_func = close_func; + default_callbacks.tell_func = tell_func; + + if (vgm_inf->scd_xor != 0) { + default_callbacks.read_func = read_func_scd; + } + + callbacks_p = &default_callbacks; + } + + temp_streamfile.streamfile = streamFile; + temp_streamfile.offset = 0; + temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); + temp_streamfile.other_header_bytes = other_header_bytes; + temp_streamfile.scd_xor = vgm_inf->scd_xor; + temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; + + /* can we open this as a proper ogg vorbis file? */ + memset(&temp_ovf, 0, sizeof(temp_ovf)); + if (ov_test_callbacks(&temp_streamfile, &temp_ovf, NULL, + 0, *callbacks_p)) goto fail; + + /* we have to close this as it has the init_vgmstream meta-reading + STREAMFILE */ + ov_clear(&temp_ovf); + + /* proceed to open a STREAMFILE just for this stream */ + data = calloc(1,sizeof(ogg_vorbis_codec_data)); + if (!data) goto fail; + + data->ov_streamfile.streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!data->ov_streamfile.streamfile) goto fail; + data->ov_streamfile.offset = 0; + data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); + data->ov_streamfile.other_header_bytes = other_header_bytes; + data->ov_streamfile.scd_xor = vgm_inf->scd_xor; + data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; + + /* open the ogg vorbis file for real */ + if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, + 0, *callbacks_p)) goto fail; + ovf = &data->ogg_vorbis_file; + inited_ovf = 1; + + data->bitstream = DEFAULT_BITSTREAM; + + info = ov_info(ovf,DEFAULT_BITSTREAM); + + /* grab the comments */ + { + int i; + vorbis_comment *comment; + + comment = ov_comment(ovf,DEFAULT_BITSTREAM); + + /* search for a "loop_start" comment */ + for (i=0;icomments;i++) { + if (strstr(comment->user_comments[i],"loop_start=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"LOOP_START=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"COMMENT=LOOPPOINT=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"LOOPSTART=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"um3.stream.looppoint.start=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"LOOP_BEGIN=")== + comment->user_comments[i] || + strstr(comment->user_comments[i],"LoopStart=")== + comment->user_comments[i] + ) { + loop_start=atol(strrchr(comment->user_comments[i],'=')+1); + if (loop_start >= 0) + loop_flag=1; + } + else if (strstr(comment->user_comments[i],"LOOPLENGTH=")== + comment->user_comments[i]) { + loop_length=atol(strrchr(comment->user_comments[i],'=')+1); + loop_length_found=1; + } + else if (strstr(comment->user_comments[i],"title=-lps")== + comment->user_comments[i]) { + loop_start=atol(comment->user_comments[i]+10); + if (loop_start >= 0) + loop_flag=1; + } + else if (strstr(comment->user_comments[i],"album=-lpe")== + comment->user_comments[i]) { + loop_end=atol(comment->user_comments[i]+10); + loop_flag=1; + loop_end_found=1; + } + else if (strstr(comment->user_comments[i],"LoopEnd=")== + comment->user_comments[i]) { + if(loop_flag) { + loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; + loop_length_found=1; + } + } + else if (strstr(comment->user_comments[i],"LOOP_END=")== + comment->user_comments[i]) { + if(loop_flag) { + loop_length=atol(strrchr(comment->user_comments[i],'=')+1)-loop_start; + loop_length_found=1; + } + } + else if (strstr(comment->user_comments[i],"lp=")== + comment->user_comments[i]) { + sscanf(strrchr(comment->user_comments[i],'=')+1,"%d,%d", + &loop_start,&loop_end); + loop_flag=1; + loop_end_found=1; + } + } + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(info->channels,loop_flag); + if (!vgmstream) goto fail; + + /* store our fun extra datas */ + vgmstream->codec_data = data; + + /* fill in the vital statistics */ + vgmstream->channels = info->channels; + vgmstream->sample_rate = info->rate; + + /* let's play the whole file */ + vgmstream->num_samples = ov_pcm_total(ovf,-1); + + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + if (loop_length_found) + vgmstream->loop_end_sample = loop_start+loop_length; + else if (loop_end_found) + vgmstream->loop_end_sample = loop_end; + else + vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->loop_flag = loop_flag; + + if (vgmstream->loop_end_sample > vgmstream->num_samples) + vgmstream->loop_end_sample = vgmstream->num_samples; + } + vgmstream->coding_type = coding_ogg_vorbis; + vgmstream->layout_type = vgm_inf->layout_type; + vgmstream->meta_type = vgm_inf->meta_type; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (data) { + if (inited_ovf) + ov_clear(&data->ogg_vorbis_file); + if (data->ov_streamfile.streamfile) + close_streamfile(data->ov_streamfile.streamfile); + free(data); + } + if (vgmstream) { + vgmstream->codec_data = NULL; + close_vgmstream(vgmstream); + } + return NULL; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/otm.c b/Frameworks/vgmstream/vgmstream/src/meta/otm.c new file mode 100644 index 000000000..500771c07 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/otm.c @@ -0,0 +1,73 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Otomedius OTM (Arcade) */ +VGMSTREAM * init_vgmstream_otm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("otm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x20,streamFile) != 0x10B10200) + goto fail; + if (read_32bitBE(0x24,streamFile) != 0x04001000) + goto fail; + + if (read_32bitBE(0x14,streamFile) != 0x00000000) + loop_flag = 1; + else + loop_flag = 0; + channel_count = read_16bitLE(0x1A,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x2C; + vgmstream->num_samples = (get_streamfile_size(streamFile)- start_offset)/channel_count/2; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x1C,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x10,streamFile))/channel_count/2; + vgmstream->loop_end_sample = (read_32bitLE(0xC,streamFile) - start_offset)/channel_count/2; + } + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_OTM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/p3d.c b/Frameworks/vgmstream/vgmstream/src/meta/p3d.c new file mode 100644 index 000000000..ebc0ab09f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/p3d.c @@ -0,0 +1,117 @@ +#include "meta.h" +#include "../util.h" + +/* P3D, with Radical ADPCM, from Prototype */ + +VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t parse_offset; + off_t start_offset; + size_t file_size; + + uint32_t header_size; + uint32_t sample_rate; + uint32_t body_bytes; + int loop_flag; + int channel_count; + const int interleave = 0x14; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("p3d",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x503344FF) /* P3D\xFF */ + goto fail; + header_size = read_32bitLE(0x4,streamFile); + if (0xC != header_size) goto fail; + file_size = get_streamfile_size(streamFile); + if (read_32bitLE(0x8,streamFile) != file_size) goto fail; + if (read_32bitBE(0xC,streamFile) != 0xFE) goto fail; + /* body size twice? */ + if (read_32bitLE(0x10,streamFile) + header_size != file_size) goto fail; + if (read_32bitLE(0x14,streamFile) + header_size != file_size) goto fail; + + /* mysterious 10! */ + if (read_32bitLE(0x18,streamFile) != 10) goto fail; + + /* parse header text */ + parse_offset = 0x1C; + { + int text_len = read_32bitLE(parse_offset,streamFile); + if (9 != text_len) goto fail; + /* AudioFile */ + if (read_32bitBE(parse_offset+4,streamFile) != 0x41756469 || + read_32bitBE(parse_offset+8,streamFile) != 0x6F46696C || + read_16bitBE(parse_offset+12,streamFile) != 0x6500) goto fail; + parse_offset += 4 + text_len + 1; + } + { + uint32_t name_count = read_32bitLE(parse_offset,streamFile); + int i; + parse_offset += 4; + /* names? */ + for (i = 0; i < name_count; i++) + { + int text_len = read_32bitLE(parse_offset,streamFile); + parse_offset += 4 + text_len + 1; + } + } + /* info count? */ + if (1 != read_32bitLE(parse_offset,streamFile)) goto fail; + parse_offset += 4; + { + int text_len = read_32bitLE(parse_offset,streamFile); + if (4 != text_len) goto fail; + /* radp */ + if (read_32bitBE(parse_offset+4,streamFile) != 0x72616470 || + read_8bit(parse_offset+8,streamFile) != 0) goto fail; + parse_offset += 4 + text_len + 1; + } + + /* real RADP header */ + if (0x52414450 != read_32bitBE(parse_offset,streamFile)) goto fail; + channel_count = read_32bitLE(parse_offset+4,streamFile); + sample_rate = read_32bitLE(parse_offset+8,streamFile); + /* codec id? */ + //if (9 != read_32bitLE(parse_offset+0xC,streamFile)) goto fail; + body_bytes = read_32bitLE(parse_offset+0x10,streamFile); + start_offset = parse_offset+0x14; + if (start_offset + body_bytes != file_size) goto fail; + + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = sample_rate; + vgmstream->coding_type = coding_RAD_IMA_mono; + vgmstream->interleave_block_size = interleave; + vgmstream->num_samples = body_bytes / interleave / channel_count * 32; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_P3D; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].offset=vgmstream->ch[i].channel_start_offset=start_offset+interleave*i; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c new file mode 100644 index 000000000..db6949d61 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_adp.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* ADP (from Balls of Steel) */ +VGMSTREAM * init_vgmstream_bos_adp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("adp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x41445021) /* "ADP!" */ + goto fail; + + loop_flag = (-1 != read_32bitLE(0x08,streamFile)); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x18; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_DVI_IMA; + vgmstream->num_samples = read_32bitLE(0x04,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_BOS_ADP; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + vgmstream->ch[0].streamfile = file; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + // 0x10, 0x12 - both initial history? + //vgmstream->ch[0].adpcm_history1_32 = read_16bitLE(0x10,streamFile); + // 0x14 - initial step index? + //vgmstream->ch[0].adpcm_step_index = read_32bitLE(0x14,streamFile); + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_mxst.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_mxst.c new file mode 100644 index 000000000..2e79f0f13 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_mxst.c @@ -0,0 +1,218 @@ +//MxSt files ripped from Jukebox.si in Lego Island +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_pc_mxst(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int bits_per_sample; + int channel_count; + int sample_rate,bytes_per_second; + long sample_count; + int i; + off_t file_size; + off_t chunk_list_size=-1; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mxst",filename_extension(filename))) goto fail; + + /* looping info not found yet */ + //loop_flag = get_streamfile_size(streamFile) > 700000; + + /* check MxSt header */ + if (0x4d785374 != read_32bitBE(0, streamFile)) goto fail; + file_size = read_32bitLE(4, streamFile) + 8; + if (file_size != get_streamfile_size(streamFile)) goto fail; + + /* read chunks */ + { + off_t MxDa=-1; /* points inside the MxDa chunk */ + off_t MxCh=-1; /* point at start of the first MxCh chunk */ + off_t chunk_offset = 8; + uint32_t stream_id; + while (chunk_offset < file_size) + { + uint32_t chunk_size = (read_32bitLE(chunk_offset+4, streamFile)+1)/2*2; + switch (read_32bitBE(chunk_offset, streamFile)) + { + case 0x4d784f62: /* MxOb */ + /* not interesting for playback */ + break; + case 0x20574156: /* " WAV" */ + if (chunk_size == 1) + chunk_size = 8; + break; + case 0x4c495354: /* LIST */ + { + off_t first_item_offset = chunk_offset+0x14; + off_t list_chunk_offset = first_item_offset+ + read_32bitLE(chunk_offset+0x10,streamFile); + + if (read_32bitBE(chunk_offset+0x8,streamFile) == 0x4d784461) /* MxDa */ + MxDa = first_item_offset; + else + goto fail; + + if (read_32bitBE(chunk_offset+0xC,streamFile) == + 0x4d784368) /* MxCh */ + { + MxCh = list_chunk_offset; + chunk_list_size = chunk_size - (list_chunk_offset-(chunk_offset+8)); + } + else + goto fail; + + break; + } + default: + goto fail; + } + + chunk_offset += 8 + chunk_size; + if (chunk_offset > file_size) goto fail; + } + + if (MxDa == -1 || MxCh == -1 || chunk_list_size == -1) goto fail; + + /* parse MxDa */ + { + /* ??? */ + if (0 != read_16bitLE(MxDa+0x00,streamFile)) goto fail; + stream_id = read_32bitLE(MxDa+0x2,streamFile); + /* First sample (none in MxDa block) */ + if (-1 != read_32bitLE(MxDa+0x06,streamFile)) goto fail; + /* size of format data */ + if (0x18 != read_32bitLE(MxDa+0x0a,streamFile)) goto fail; + /* PCM */ + if (1 != read_16bitLE(MxDa+0x0e,streamFile)) goto fail; + /* channel count */ + channel_count = read_16bitLE(MxDa+0x10,streamFile); + /* only mono known */ + if (1 != channel_count) goto fail; + sample_rate = read_32bitLE(MxDa+0x12,streamFile); + bits_per_sample = read_16bitLE(MxDa+0x1c,streamFile); + /* bytes per second */ + bytes_per_second = read_32bitLE(MxDa+0x16,streamFile); + if (bits_per_sample/8*channel_count*sample_rate != bytes_per_second) goto fail; + /* block align */ + if (bits_per_sample/8*channel_count != + read_16bitLE(MxDa+0x1a,streamFile)) goto fail; + sample_count = read_32bitLE(MxDa+0x1e,streamFile)/(bits_per_sample/8)/channel_count; + /* 2c? data offset in normal RIFF WAVE? */ + if (0x2c != read_32bitLE(MxDa+0x22,streamFile)) goto fail; + } + + /* parse through all MxCh for consistency check */ + { + long samples = 0; + int split_frames_seen = 0; + off_t MxCh_offset = MxCh; + while (MxCh_offset < MxCh+chunk_list_size) + { + uint16_t flags; + if (read_32bitBE(MxCh_offset,streamFile)!=0x70616420) /*pad*/ + { + if (read_32bitBE(MxCh_offset,streamFile)!=0x4d784368) /*MxCh*/ + goto fail; + + flags = read_16bitLE(MxCh_offset+8+0,streamFile); + + if (read_32bitLE(MxCh_offset+8+2,streamFile)!=stream_id) + goto fail; + + if (flags & 0x10) + { + split_frames_seen ++; + if (split_frames_seen == 1) + { + if (read_32bitLE(MxCh_offset+8+6,streamFile)!=(samples*UINT64_C(1000)+sample_rate-1)/sample_rate) + goto fail; + } + else if (split_frames_seen == 2) + { + if ( read_32bitLE(MxCh_offset+8+0xa,streamFile)!= + read_32bitLE(MxCh_offset+4,streamFile)-0xe ) goto fail; + split_frames_seen = 0; + } + else goto fail; + } + + if (!(flags & 0x10)) + { + if (split_frames_seen != 0) + { + goto fail; + } + if (read_32bitLE(MxCh_offset+8+6,streamFile)!=(samples*UINT64_C(1000)+sample_rate-1)/sample_rate) + goto fail; + + if ( read_32bitLE(MxCh_offset+8+0xa,streamFile)!= + read_32bitLE(MxCh_offset+4,streamFile)-0xe ) goto fail; + } + samples += (read_32bitLE(MxCh_offset+4,streamFile)-0xe)/(bits_per_sample/8/channel_count); + + } + MxCh_offset += 8 + (read_32bitLE(MxCh_offset+4,streamFile)+1)/2*2; + if (MxCh_offset > MxCh+chunk_list_size) goto fail; + } + //printf("samples=%d sample_count=%d\n",samples,sample_count); + //samples = (samples * (bits_per_sample/8) * channel_count + 31)/32*32/(bits_per_sample/8)/channel_count; + if (samples < sample_count) + { + sample_count = samples; + } + if (samples != sample_count) goto fail; + } + + start_offset = MxCh; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = sample_rate; + vgmstream->layout_type = layout_mxch_blocked; + + vgmstream->meta_type = meta_PC_MXST; + if(bits_per_sample == 8) + { + vgmstream->coding_type = coding_PCM8_U; + } + else if (bits_per_sample == 16) + { + vgmstream->coding_type = coding_PCM16LE; + } + else goto fail; + vgmstream->num_samples = sample_count; + if(loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = + streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + + } + mxch_block_update(start_offset, vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c new file mode 100644 index 000000000..95f7ad5c9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_smp.c @@ -0,0 +1,94 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* .smp file, with MS ADPCM. From Ghostbusters (PC). */ + +VGMSTREAM * init_vgmstream_pc_smp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int channel_count; + off_t start_offset; + int interleave; + + int loop_flag = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("smp",filename_extension(filename))) goto fail; + + /* 6? */ + if (6 != read_32bitLE(0,streamFile)) goto fail; + if (0 != read_32bitLE(0x14,streamFile)) goto fail; + if (4 != read_32bitLE(0x24,streamFile)) goto fail; + if (4 != read_32bitLE(0x2C,streamFile)) goto fail; + + start_offset = read_32bitLE(0x1c, streamFile); + /* check body start + body size = total size */ + if (start_offset + read_32bitLE(0x20,streamFile) != get_streamfile_size(streamFile)) goto fail; + + /* might also be codec id? */ + channel_count = read_32bitLE(0x28,streamFile); + if (channel_count != 1 && channel_count != 2) goto fail; + + /* verify MS ADPCM codec setup */ + { + int i; + /* coefficients and statement of 0x100 samples per block?? */ + static const uint8_t ms_setup[0x20] = { + 0x00,0x01,0x07,0x00,0x00,0x01,0x00,0x00, + 0x00,0x02,0x00,0xFF,0x00,0x00,0x00,0x00, + 0xC0,0x00,0x40,0x00,0xF0,0x00,0x00,0x00, + 0xCC,0x01,0x30,0xFF,0x88,0x01,0x18,0xFF}; + + for (i = 0; i < 0x20; i++) + { + if ((uint8_t)read_8bit(0x34+i,streamFile) != ms_setup[i]) goto fail; + } + + /* verify padding */ + for (i = 0x20; i+0x34 < start_offset; i++) + { + if (read_8bit(0x34+i,streamFile) != 0) goto fail; + } + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitLE(0x18,streamFile); + vgmstream->sample_rate = read_32bitLE(0x30,streamFile); + + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_none; // MS ADPCM does own interleave + interleave = 0x86*channel_count; + vgmstream->interleave_block_size = interleave; + + vgmstream->meta_type = meta_PC_SMP; + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + channel_count*interleave*2); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_snds.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_snds.c new file mode 100644 index 000000000..03b1d23d7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_snds.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* .snds - from Incredibles PC */ + +VGMSTREAM * init_vgmstream_pc_snds(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t file_size; + int i; + + /* check extension, case insensitive */ + /* this is all we have to go on, snds is completely headerless */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("snds",filename_extension(filename))) goto fail; + + file_size = get_streamfile_size(streamFile); + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = 48000; + + /* file seems to be mistakenly 1/8 too long */ + vgmstream->num_samples = file_size*8/9; + + /* check for 32 0 bytes where the padding should start */ + for (i = 0; i < 8; i++) + { + if (read_32bitBE(vgmstream->num_samples+i*4,streamFile) != 0) + { + /* not padding? just play the whole file */ + vgmstream->num_samples = file_size; + break; + } + } + + vgmstream->coding_type = coding_SNDS_IMA; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PC_SNDS; + + /* open the file for reading */ + vgmstream->ch[0].streamfile = vgmstream->ch[1].streamfile = + streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[0].streamfile) goto fail; + + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset= + vgmstream->ch[1].channel_start_offset= + vgmstream->ch[1].offset=0; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c b/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c new file mode 100644 index 000000000..d6a5d7296 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pc_sob.c @@ -0,0 +1,82 @@ +#include "meta.h" +#include "../util.h" + +/* SOB/SAB combination as found in Worms 4: Mayhem +they are actually soundpacks, but the audio data is just streamed as one big stream +*/ + +VGMSTREAM * init_vgmstream_sab(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE* sob = NULL; + char filename[PATH_LIMIT]; + int i; + int loop_flag, channel_count, numSounds; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sab",filename_extension(filename))) goto fail; + + /* read information from sob file*/ + filename[strlen(filename)-2]='o'; //change extension in sob of file + sob = open_stdio_streamfile(filename); + if(!sob) goto fail; + filename[strlen(filename)-2]='a';//change back to original file + + if (read_32bitBE(0,streamFile)!=0x43535732)//CSW2 header sab file + { + goto fail; + } + if (read_32bitBE(0,sob)!=0x43544632)//CTF2 header sob file + { + goto fail; + } + numSounds = read_32bitLE(8,sob); + if(numSounds==1) + {//it means it's a single stream and not a voice bank + loop_flag = 1; + }else + { + loop_flag = 0; + } + + /* Read channels */ + channel_count = read_32bitLE(0x30,sob); + if( (channel_count>2)||(numSounds>1))/* dirty hack for number of channels*/ + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + //is offset OK. sab files can contain more audio files, but without the sob it's just a long stream of sound effects + vgmstream->current_block_offset=8+32*numSounds; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x20,streamFile); + vgmstream->coding_type = coding_PCM16LE_int; + vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-vgmstream->current_block_offset)/2/channel_count); + if(loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PC_SOB_SAB; + + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=vgmstream->current_block_offset+2*i; + } + } + close_streamfile(sob); + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (sob) close_streamfile(sob); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pcm.c b/Frameworks/vgmstream/vgmstream/src/meta/pcm.c new file mode 100644 index 000000000..ff6371069 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pcm.c @@ -0,0 +1,128 @@ +#include "meta.h" +#include "../util.h" + +/* PCM (from Lunar: Eternal Blue (Sega CD) */ +VGMSTREAM * init_vgmstream_pcm_scd(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pcm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x00020000) + goto fail; + + loop_flag = (read_32bitLE(0x02,streamFile)!=0); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x200; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 32000; + vgmstream->coding_type = coding_PCM8_SB_int; + vgmstream->num_samples = read_32bitBE(0x06,streamFile)*2; + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x02,streamFile)*0x400*2; + vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1; + vgmstream->meta_type = meta_PCM_SCD; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* PCM - Custom header from Konami, which contains only loop infos... + found in: Ephemeral Fantasia [Reiselied] + Yu-Gi-Oh! The Duelists of the Roses [Yu-Gi-Oh! Shin Duel Monsters II] +*/ +VGMSTREAM * init_vgmstream_pcm_ps2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pcm",filename_extension(filename))) goto fail; + + // if ((read_32bitLE(0x00,streamFile)+0x800) != (get_streamfile_size(streamFile))) + // goto fail; + if ((read_32bitLE(0x00,streamFile)) != (read_32bitLE(0x04,streamFile)*4)) + goto fail; + + loop_flag = (read_32bitLE(0x08,streamFile) != 0x0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 24000; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x0,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_PCM_PS2; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pona.c b/Frameworks/vgmstream/vgmstream/src/meta/pona.c new file mode 100644 index 000000000..791c23aa3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pona.c @@ -0,0 +1,127 @@ +#include "meta.h" +#include "../util.h" + +/* PONA (from Policenauts [3DO]) */ +VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pona",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x13020000) + goto fail; + + if ((read_32bitBE(0x06,streamFile)+0x800) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = (read_32bitBE(0x0A,streamFile) != 0xFFFFFFFF); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = (uint16_t)(read_16bitBE(0x04,streamFile)); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 22050; + vgmstream->coding_type = coding_SDX2; + vgmstream->num_samples = (get_streamfile_size(streamFile))-start_offset; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x0A,streamFile)); + vgmstream->loop_end_sample = (read_32bitBE(0x06,streamFile)); + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PONA_3DO; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* PONA (from Policenauts [PSX]) */ +VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pona",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00000800) + goto fail; + + if ((read_32bitBE(0x08,streamFile)+0x800) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = (read_32bitBE(0xC,streamFile) != 0xFFFFFFFF); + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitBE(0x04,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((get_streamfile_size(streamFile))-start_offset)/16/channel_count*28; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x0C,streamFile)/16/channel_count*28); + vgmstream->loop_end_sample = (read_32bitBE(0x08,streamFile)/16/channel_count*28); + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PONA_PSX; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/pos.c b/Frameworks/vgmstream/vgmstream/src/meta/pos.c new file mode 100644 index 000000000..153f7b11b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/pos.c @@ -0,0 +1,66 @@ +#include +#include "meta.h" +#include "../util.h" + +#ifdef WIN32 +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +/* .pos is a tiny file with loop points, and the same base name as a .wav */ + +VGMSTREAM * init_vgmstream_pos(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileWAV = NULL; + char filename[PATH_LIMIT]; + char filenameWAV[260]; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pos",filename_extension(filename))) goto fail; + + /* check for .WAV file */ + strcpy(filenameWAV,filename); + strcpy(filenameWAV+strlen(filenameWAV)-3,"wav"); + + streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileWAV) { + /* try again, ucase */ + for (i=strlen(filenameWAV);i>=0&&filenameWAV[i]!=DIRSEP;i--) + filenameWAV[i]=toupper(filenameWAV[i]); + + streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileWAV) goto fail; + } + + /* let the real initer do the parsing */ + vgmstream = init_vgmstream_riff(streamFileWAV); + if (!vgmstream) goto fail; + + close_streamfile(streamFileWAV); + streamFileWAV = NULL; + + /* install loops */ + if (!vgmstream->loop_flag) { + vgmstream->loop_flag = 1; + vgmstream->loop_ch = calloc(vgmstream->channels, + sizeof(VGMSTREAMCHANNEL)); + if (!vgmstream->loop_ch) goto fail; + } + + vgmstream->loop_start_sample = read_32bitLE(0,streamFile); + vgmstream->loop_end_sample = read_32bitLE(4,streamFile); + vgmstream->meta_type = meta_RIFF_WAVE_POS; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileWAV) close_streamfile(streamFileWAV); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_2pfs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_2pfs.c new file mode 100644 index 000000000..1be1bc960 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_2pfs.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../util.h" + +/* 2PFS + - Mahoromatic: Moetto - KiraKira Maid-San (PS2) + + +*/ +VGMSTREAM * init_vgmstream_ps2_2pfs(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("2pfs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x32504653) + goto fail; + + // channel count + channel_count = read_8bit(0x40,streamFile); + + // header size + start_offset = 0x800; + + // loop flag + //if ((read_32bitLE(0x38, streamFile) != 0 || + // (read_32bitLE(0x34, streamFile) != 0))) + //{ + // loop_flag = 1; + //} + + // Loop info unknown right now + //if (loop_flag) + //{ + // vgmstream->loop_start_sample = read_32bitLE(0x38,streamFile)*28/16/channel_count; + // vgmstream->loop_end_sample = read_32bitLE(0x34,streamFile)*28/16/channel_count; + //} + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x44,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile)*28/16/channel_count; + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1000; + vgmstream->meta_type = meta_PS2_2PFS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i); + + } + + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c new file mode 100644 index 000000000..82e2f51bc --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adm.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* WAD (from The golden Compass) */ +VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int i; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("adm",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + +#if 0 + vgmstream->num_samples = read_32bitLE(0x0,streamFile)/channel_count/16*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/channel_count/16*28; + } +#endif + + vgmstream->layout_type = layout_ps2_adm_blocked; + vgmstream->interleave_block_size = 0x400; + + + vgmstream->meta_type = meta_PS2_ADM; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + + /* Calc num_samples */ + ps2_adm_block_update(start_offset,vgmstream); + vgmstream->num_samples=0; //(get_streamfile_size(streamFile)/0x1000*0xFE0)/32*28; + + do { + + vgmstream->num_samples += 0xFE0*14/16; + ps2_adm_block_update(vgmstream->next_block_offset,vgmstream); + } while (vgmstream->next_block_offsetget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ads",filename_extension(filename)) && + strcasecmp("ss2",filename_extension(filename))) goto fail; + + /* check SShd Header */ + if (read_32bitBE(0x00,streamFile) != 0x53536864) + goto fail; + + /* check SSbd Header */ + if (read_32bitBE(0x20,streamFile) != 0x53536264) + goto fail; + + /* check if file is not corrupt */ + /* seems the Gran Turismo 4 ADS files are considered corrupt,*/ + /* so I changed it to adapt the stream size if that's the case */ + /* instead of failing playing them at all*/ + streamSize = read_32bitLE(0x24,streamFile); + + if (get_streamfile_size(streamFile) < (size_t)(streamSize + 0x28)) + { + streamSize = get_streamfile_size(streamFile) - 0x28; + } + + /* check loop */ + if ((read_32bitLE(0x1C,streamFile) == 0xFFFFFFFF) || + ((read_32bitLE(0x18,streamFile) == 0) && (read_32bitLE(0x1C,streamFile) == 0))) + { + loop_flag = 0; + } + else + { + loop_flag = 1; + } + + channel_count=read_32bitLE(0x10,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x10,streamFile); + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((streamSize-0x40)/16*28)/vgmstream->channels; + + /* SS2 container with RAW Interleaved PCM */ + if (read_32bitLE(0x08,streamFile)!=0x10) + { + + vgmstream->coding_type=coding_PCM16LE; + vgmstream->num_samples = streamSize/2/vgmstream->channels; + } + + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_SShd; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + if((read_32bitLE(0x1C,streamFile)*0x10*vgmstream->channels+0x800)==get_streamfile_size(streamFile)) + { + // Search for Loop Value + readOffset=(off_t)get_streamfile_size(streamFile)-(4*vgmstream->interleave_block_size); + + do { + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + // Loop End ... + if(testBuffer[0x01]==0x01) { + if(loopEnd==0) loopEnd = readOffset-0x10; + break; + } + + } while (streamFile->get_offset(streamFile)<(int32_t)get_streamfile_size(streamFile)); + + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample /=vgmstream->channels; + + } else { + if(read_32bitLE(0x1C,streamFile)<=vgmstream->num_samples) { + vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + } else { + vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*0x10)/16*28/vgmstream->channels;; + vgmstream->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28/vgmstream->channels; + } + } + } + + /* don't know why, but it does happen, in ps2 too :( */ + if (vgmstream->loop_end_sample > vgmstream->num_samples) + vgmstream->loop_end_sample = vgmstream->num_samples; + { + start_offset=0x28; + } + + + if ((streamSize * 2) == (get_streamfile_size(streamFile) - 0x18)) + { + // True Fortune PS2 + streamSize = (read_32bitLE(0x24,streamFile) * 2) - 0x10; + vgmstream->num_samples = streamSize / 16 * 28 / vgmstream->channels; + } + else if(get_streamfile_size(streamFile) - read_32bitLE(0x24,streamFile) >= 0x800) + { + // Hack for files with start_offset = 0x800 + start_offset=0x800; + } + + if((vgmstream->coding_type == coding_PSX) && (start_offset==0x28)) + { + start_offset=0x800; + + for(i=0;i<0x1f6;i+=4) + { + if(read_32bitLE(0x28+(i*4),streamFile)!=0) + { + start_offset=0x28; + break; + } + } + } + + // check if we got a real pcm (ex: Clock Tower 3) + if(vgmstream->coding_type==coding_PCM16LE) + { + check_offset=start_offset; + do + { + if(read_8bit(check_offset+1,streamFile)>7) + { + isPCM=1; + break; + } + else + { + check_offset+=0x10; + } + + } while (check_offsetnum_samples=(get_streamfile_size(streamFile)-start_offset)/16*28/vgmstream->channels; + vgmstream->coding_type=coding_PSX; + } + } + + /* expect pcm format allways start @ 0x800, don't know if it's true :P */ + /*if(vgmstream->coding_type == coding_PCM16LE) + start_offset=0x800;*/ + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_adsc.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adsc.c new file mode 100644 index 000000000..ad6063c9e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_adsc.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* ADSC (from Kenka Bancho 2: Full Throttle) */ +VGMSTREAM * init_vgmstream_ps2_adsc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ads",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x41445343) /* ADSC */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x18,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x1000; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x14,streamFile); + vgmstream->coding_type = coding_PSX; + if(read_32bitLE(0x18,streamFile)==0x01) + vgmstream->num_samples = read_32bitLE(0x2c,streamFile)*56/32; + else + vgmstream->num_samples = read_32bitLE(0x2c,streamFile)*28/32; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile); + vgmstream->meta_type = meta_PS2_ADSC; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c new file mode 100644 index 000000000..1253bc43b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ass.c @@ -0,0 +1,92 @@ +#include "meta.h" +#include "../util.h" + +/* SVS (from Dai Senryaku VII - Exceed) */ + +VGMSTREAM * init_vgmstream_ps2_ass(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + uint8_t testBuffer[0x10]; + off_t loopStart = 0; + off_t loopEnd = 0; + off_t readOffset = 0; + size_t fileLength; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ass",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x02000000) /* "0x02000000" */ + goto fail; + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x08,streamFile)*2)*28/16/channel_count; + + fileLength = get_streamfile_size(streamFile); + + do { + + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + /* Loop Start */ + if(testBuffer[0x01]==0x06) { + if(loopStart == 0) loopStart = readOffset-0x10; + /* break; */ + } + /* Loop End */ + if(testBuffer[0x01]==0x03) { + if(loopEnd == 0) loopEnd = readOffset-0x10; + /* break; */ + } + } while (streamFile->get_offset(streamFile)<(int32_t)fileLength); + + if(loopStart == 0) { + loop_flag = 0; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)*28/16/channel_count; + } else { + loop_flag = 1; + vgmstream->loop_start_sample = (loopStart-start_offset)*28/16/channel_count; + vgmstream->loop_end_sample = (loopEnd-start_offset)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile); + vgmstream->meta_type = meta_PS2_ASS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ast.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ast.c new file mode 100644 index 000000000..2d3f9dbf8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ast.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../util.h" + +/* AST */ +VGMSTREAM * init_vgmstream_ps2_ast(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + int variant_type; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ast",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x41535400) /* "AST\0" */ + goto fail; + + /* determine variant */ + if (read_32bitBE(0x10,streamFile) == 0) + { + variant_type = 1; + } + else + { + variant_type = 2; + } + + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (variant_type == 1) + { + start_offset = 0x800; + channel_count = 2; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)*28/16/channel_count; + vgmstream->interleave_block_size = read_32bitLE(0x08,streamFile); + loop_flag = 0; + } + else if (variant_type == 2) + { + start_offset = 0x100; + channel_count = read_32bitLE(0x0C,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->num_samples = (read_32bitLE(0x04,streamFile)-start_offset)*28/16/channel_count; + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->coding_type = coding_PSX; + vgmstream->meta_type = meta_PS2_AST; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c new file mode 100644 index 000000000..24bb3883f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_aus.c @@ -0,0 +1,71 @@ +#include "meta.h" +#include "../util.h" + +/* AUS (found in various Capcom games) */ +VGMSTREAM * init_vgmstream_aus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("aus",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x41555320) /* "AUS " */ + goto fail; + + loop_flag = (read_32bitLE(0x0c,streamFile)!=0); + channel_count = read_32bitLE(0xC,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->num_samples = read_32bitLE(0x08,streamFile); + + if(read_16bitLE(0x06,streamFile)==0x02) { + vgmstream->coding_type = coding_XBOX; + vgmstream->layout_type=layout_none; + } else { + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + } + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x08,streamFile); + } + + vgmstream->meta_type = meta_AUS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_b1s.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_b1s.c new file mode 100644 index 000000000..2b4b464c4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_b1s.c @@ -0,0 +1,56 @@ +#include "meta.h" +#include "../util.h" + +/* B1S (found in 7 Wonders of the Ancient World) */ +VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("b1s",filename_extension(filename))) goto fail; + + if ((read_32bitLE(0x04,streamFile)+0x18) != get_streamfile_size(streamFile)) + goto fail; + + channel_count = read_32bitLE(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x18; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16/channel_count*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile); + vgmstream->meta_type = meta_PS2_B1S; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_bg00.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bg00.c new file mode 100644 index 000000000..4ae1362da --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bg00.c @@ -0,0 +1,65 @@ +#include "meta.h" +#include "../util.h" + +/* BG0 (from Ibara, Mushihimesama) +Note: Seems the Loop Infos are stored external... */ +VGMSTREAM * init_vgmstream_bg00(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bg00",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x42473030) /* "BG00" */ + goto fail; + + loop_flag = (read_32bitLE(0x08,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x80,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); + vgmstream->meta_type = meta_BG00; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c new file mode 100644 index 000000000..dc0e93093 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_bmdx.c @@ -0,0 +1,92 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_ps2_bmdx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bmdx",filename_extension(filename))) goto fail; + + /* check NPSF Header */ + if (read_32bitBE(0x00,streamFile) != 0x01006408 || + read_32bitBE(0x04,streamFile) != 0) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x10,streamFile)!=0); + channel_count=read_32bitLE(0x1C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + + /* Check for Compression Scheme */ + if (read_32bitLE(0x20,streamFile) == 1) + vgmstream->coding_type = coding_invert_PSX; + else + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0c,streamFile)*28/16/channel_count; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile)*28/16/channel_count; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count > 1) { + vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile); + vgmstream->layout_type = layout_interleave; + } + + vgmstream->meta_type = meta_PS2_BMDX; + + start_offset = read_32bitLE(0x08,streamFile); + + if (vgmstream->coding_type == coding_invert_PSX) + { + uint8_t xor = read_8bit(start_offset,streamFile); + uint8_t add = (~(uint8_t)read_8bit(start_offset+2,streamFile))+1; + int c; + for (c=0;cch[c].bmdx_xor = xor; + vgmstream->ch[c].bmdx_add = add; + } + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[0].streamfile) { + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,0x8000); + } + vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile; + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ccc.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ccc.c new file mode 100644 index 000000000..ab2a4013d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ccc.c @@ -0,0 +1,68 @@ +#include "meta.h" +#include "../util.h" + +/* CCC */ +VGMSTREAM * init_vgmstream_ps2_ccc(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ccc",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x01000000) + goto fail; + + /* check file size */ + if (read_32bitLE(0x0C,streamFile)+0x50 != get_streamfile_size(streamFile)) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x50; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/32*28; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; + vgmstream->meta_type = meta_PS2_CCC; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_dxh.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_dxh.c new file mode 100644 index 000000000..c9f38324c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_dxh.c @@ -0,0 +1,76 @@ +#include "meta.h" +#include "../util.h" + +/* DXH (from Tokobot Plus - Mysteries of the Karakuri) */ +VGMSTREAM * init_vgmstream_ps2_dxh(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dxh",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00445848) /* 0\DXH" */ + goto fail; + + loop_flag = (read_32bitLE(0x50,streamFile)!=0); + channel_count = read_32bitLE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x20,streamFile); + + if (read_32bitBE(0x54,streamFile) == 0) { + /* if (loop_flag) { */ + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = get_streamfile_size(streamFile)*28/16/channel_count; + vgmstream->num_samples = get_streamfile_size(streamFile)*28/16/channel_count; + /* } */ + + } else { + + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x50,streamFile)*0x20)*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x54,streamFile)*0x20)*28/16/channel_count; + vgmstream->num_samples = (read_32bitLE(0x54,streamFile)*0x20)*28/16/channel_count; + + } +} + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->meta_type = meta_PS2_DXH; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_enth.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_enth.c new file mode 100644 index 000000000..c3e6eb19c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_enth.c @@ -0,0 +1,94 @@ +#include "meta.h" +#include "../util.h" + +/* ENTH (from Enthusia - Professional Racing) */ +VGMSTREAM * init_vgmstream_ps2_enth(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int header_check; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("enth",filename_extension(filename))) goto fail; + + /* check header and loop_flag */ + header_check = read_32bitBE(0x00,streamFile); + switch (header_check) { + case 0x41502020: /* AP */ + loop_flag = (read_32bitLE(0x14,streamFile)!=0); + break; + case 0x4C455020: /* LEP */ + loop_flag = (read_32bitLE(0x58,streamFile)!=0); + break; + default: + goto fail; + } + + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + header_check = read_32bitBE(0x00,streamFile); + + switch (header_check) { + case 0x41502020: /* AP */ + start_offset = read_32bitLE(0x1C,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x18,streamFile))*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x14,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x18,streamFile))*28/16/channel_count; + } + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile); + break; + case 0x4C455020: /* LEP */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x12,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x08,streamFile))*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x58,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))*28/16/channel_count; + } + vgmstream->interleave_block_size = 0x10; + break; + default: + goto fail; +} + + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_ENTH; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_exst.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_exst.c new file mode 100644 index 000000000..d3f5cea2f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_exst.c @@ -0,0 +1,79 @@ +#include "meta.h" +#include "../util.h" + +/* EXST + + PS2 INT format is an interleaved format found in Shadow of the Colossus + The header start with a EXST id. + The headers and bgm datas was separated in the game, and joined in order + to add support for vgmstream + + The interleave value is allways 0x400 + known extensions : .STS + + 2008-05-13 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_exst(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sts",filename_extension(filename))) goto fail; + + /* check EXST Header */ + if (read_32bitBE(0x00,streamFile) != 0x45585354) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x0C,streamFile)==1); + + channel_count=read_16bitLE(0x06,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_16bitLE(0x06,streamFile); + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + + /* Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x14,streamFile)*0x400)/16*28; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x10,streamFile)*0x400)/16*28; + vgmstream->loop_end_sample = (read_32bitLE(0x14,streamFile)*0x400)/16*28; + } + + vgmstream->interleave_block_size = 0x400; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_EXST; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(0x78+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c new file mode 100644 index 000000000..4f888bdc7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_filp.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* FILp (Resident Evil - Dead Aim) */ +VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("filp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x46494C70) /* "FILp" */ + goto fail; + if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */ + goto fail; + if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */ + goto fail; + if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile)) + goto fail; + + loop_flag = (read_32bitLE(0x34,streamFile) == 0); + channel_count = read_32bitLE(0x4,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x110,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_filp_blocked; + vgmstream->meta_type = meta_FILP; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + } + } + + filp_block_update(start_offset,vgmstream); + vgmstream->num_samples = read_32bitLE(0x10C,streamFile)/16*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_gbts.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gbts.c new file mode 100644 index 000000000..0a04851be --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gbts.c @@ -0,0 +1,92 @@ +#include "meta.h" +#include "../util.h" + +/* GBTS : Pop'n'Music 9 Bgm File */ + +VGMSTREAM * init_vgmstream_ps2_gbts(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + off_t loopStart = 0; + off_t loopEnd = 0; + size_t filelength; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gbts",filename_extension(filename))) goto fail; + + /* check loop */ + start_offset=0x801; + + filelength = get_streamfile_size(streamFile); + do { + // Loop Start ... + if(read_8bit(start_offset,streamFile)==0x06) { + if(loopStart==0) loopStart = start_offset-0x801; + } + + // Loop End ... + if(read_8bit(start_offset,streamFile)==0x03) { + if(loopEnd==0) loopEnd = start_offset-0x801-0x10; + } + + start_offset+=0x10; + + } while (start_offset<(int32_t)filelength); + + loop_flag = (loopEnd!=0); + channel_count=read_32bitLE(0x1C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile);; + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels; + vgmstream->interleave_block_size = 0x10; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = (loopStart/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28; + vgmstream->loop_start_sample += (loopStart%vgmstream->interleave_block_size)/16*28; + vgmstream->loop_start_sample /=vgmstream->channels; + vgmstream->loop_end_sample = (loopEnd/(vgmstream->interleave_block_size)*vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample += (loopEnd%vgmstream->interleave_block_size)/16*28; + vgmstream->loop_end_sample /=vgmstream->channels; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_GBTS; + + start_offset = (off_t)0x800; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c new file mode 100644 index 000000000..92a07800a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_gcm.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../util.h" + +/* GCM (from NamCollection) */ +VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gcm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D434700) /* "MCG" */ + goto fail; + if (read_32bitBE(0x20,streamFile) != 0x56414770) /* "VAGp" */ + goto fail; + + loop_flag = 0; + channel_count= 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x30,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x10,streamFile)*28/32; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->meta_type = meta_PS2_GCM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_hgc1.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hgc1.c new file mode 100644 index 000000000..7588febe8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hgc1.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* hgC1 (from Knights of the Temple 2) */ +VGMSTREAM * init_vgmstream_hgc1(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("hgc1",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x68674331) /* "hgC1" */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_HGC1; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c new file mode 100644 index 000000000..ecd219d32 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_hsf.c @@ -0,0 +1,100 @@ +#include "meta.h" +#include "../util.h" + +/* HSF - Found in Lowrider (PS2) - STREAM.BIN archive */ +VGMSTREAM * init_vgmstream_ps2_hsf(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + size_t fileLength; + size_t frequencyFlag; + + off_t readOffset = 0; + uint8_t testBuffer[0x10]; + off_t loopEndOffset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("hsf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x48534600) // "HSF" + goto fail; + + loop_flag = 0; + channel_count = 2; + fileLength = get_streamfile_size(streamFile); + frequencyFlag = read_32bitLE(0x08, streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + + if (frequencyFlag == 0x0EB3) + { + vgmstream->sample_rate = 44100; + } + else if (frequencyFlag == 0x1000) + { + vgmstream->sample_rate = 48000; + } + + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((fileLength - 0x10) / 16 * 28) / vgmstream->channels; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x0C, streamFile); + vgmstream->meta_type = meta_PS2_HSF; + + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + /* + readOffset = fileLength - 0x10; + + do + { + readOffset -=(off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + if (testBuffer[1] == 0x07) + { + loopEndOffset = readOffset + 0x10; + vgmstream->loop_end_sample = ((loopEndOffset - 0x10) / 16 * 28) / vgmstream->channels; + break; + } + + } while (readOffset > 0); + */ + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_iab.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_iab.c new file mode 100644 index 000000000..0d9fdb782 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_iab.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* IAB: Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) */ +VGMSTREAM * init_vgmstream_ps2_iab(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int i; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("iab",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x10000000) + goto fail; + + /* check file size */ + if (read_32bitLE(0x1C,streamFile) != get_streamfile_size(streamFile)) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x4,streamFile); + vgmstream->coding_type = coding_PSX; + + vgmstream->layout_type = layout_ps2_iab_blocked; + vgmstream->interleave_block_size = read_32bitLE(0xC, streamFile); + vgmstream->meta_type = meta_PS2_IAB; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile, filename, vgmstream->interleave_block_size); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* Calc num_samples */ + ps2_iab_block_update(start_offset, vgmstream); + vgmstream->num_samples=0; + + do + { + vgmstream->num_samples += 0x4000 * 14 / 16; + ps2_iab_block_update(vgmstream->next_block_offset, vgmstream); + } while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); + + ps2_iab_block_update(start_offset, vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ikm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ikm.c new file mode 100644 index 000000000..2b16f156a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ikm.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* IKM (found in Zwei!) */ +VGMSTREAM * init_vgmstream_ikm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ikm",filename_extension(filename))) goto fail; + + /* check header */ + if ((read_32bitBE(0x00,streamFile) != 0x494B4D00) && /* "IKM\0" */ + (read_32bitBE(0x40,streamFile) != 0x41535400)) /* "AST\0" */ + goto fail; + + loop_flag = (read_32bitLE(0x14,streamFile)!=0); /* Not sure */ + channel_count = read_32bitLE(0x50,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x44,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x4C,streamFile)-start_offset)/16/channel_count*28; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_IKM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c new file mode 100644 index 000000000..ea6a846f1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ild.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* ILD */ + +VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ild",filename_extension(filename))) goto fail; + + /* check ILD Header */ + if (read_32bitBE(0x00,streamFile) != 0x494C4400) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x2C,streamFile)!=0); + channel_count=read_32bitLE(0x04,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x04,streamFile); + vgmstream->sample_rate = read_32bitLE(0x28,streamFile); + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x2C,streamFile)/16*28; + vgmstream->loop_end_sample = read_32bitLE(0x30,streamFile)/16*28; + } + + vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile)/2; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_ILD; + + start_offset = (off_t)read_32bitLE(0x08,streamFile); + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c new file mode 100644 index 000000000..e7aa1a84e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_int.c @@ -0,0 +1,115 @@ +#include "meta.h" +#include "../util.h" + +/* INT + + PS2 INT format is a RAW 48khz PCM file without header + The only fact about those file, is that the raw is interleaved + + The interleave value is allways 0x200 + known extensions : INT + + 2008-05-11 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_int(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int i,channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("int",filename_extension(filename)) && + strcasecmp("wp2",filename_extension(filename))) goto fail; + + if(!strcasecmp("int",filename_extension(filename))) + channel_count = 2; + else + channel_count = 4; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels=channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile)/(vgmstream->channels*2)); + vgmstream->interleave_block_size = 0x200; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_RAW; + + /* open the file for reading by each channel */ + { + for (i=0;ichannels;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +// OMU is a PS2 .INT file with header ... +// found in Alter Echo +VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int i,channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("omu",filename_extension(filename))) goto fail; + + /* check header */ + if((read_32bitBE(0,streamFile)!=0x4F4D5520) && (read_32bitBE(0x08,streamFile)!=0x46524D54)) + goto fail; + + channel_count = (int)read_8bit(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,1); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels=channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2)); + vgmstream->interleave_block_size = 0x200; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_OMU; + + vgmstream->loop_start_sample=0; + vgmstream->loop_end_sample=vgmstream->num_samples; + + /* open the file for reading by each channel */ + { + for (i=0;ichannels;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=0x40+(i*vgmstream->interleave_block_size); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_joe.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_joe.c new file mode 100644 index 000000000..8087bf280 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_joe.c @@ -0,0 +1,111 @@ +#include "meta.h" +#include "../util.h" + +/* JOE (found in Wall-E and some more Pixar games) */ +VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + uint8_t testBuffer[0x10]; + off_t loopStart = 0; + off_t loopEnd = 0; + off_t readOffset = 0; + off_t blockOffset = 0; + off_t sampleOffset = 0; + size_t fileLength; + size_t dataLength; + size_t dataInterleave; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("joe",filename_extension(filename))) goto fail; + + /* check header */ + // if (read_32bitBE(0x0C,streamFile) != 0xCCCCCCCC) + // goto fail; + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + fileLength = get_streamfile_size(streamFile); + dataLength = read_32bitLE(0x4,streamFile); + dataInterleave = read_32bitLE(0x8,streamFile); + + /* fill in the vital statistics */ + start_offset = fileLength - dataLength; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = dataLength*28/16/channel_count; + + + readOffset = start_offset; + do { + off_t blockRead = (off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + readOffset += blockRead; + blockOffset += blockRead; + + if (blockOffset >= dataInterleave) { + readOffset += dataInterleave; + blockOffset -= dataInterleave; + } + + /* Loop Start */ + if(testBuffer[0x01]==0x06) { + if(loopStart == 0) loopStart = sampleOffset; + /* break; */ + } + + sampleOffset += 28; + + /* Loop End */ + if(testBuffer[0x01]==0x03) { + if(loopEnd == 0) loopEnd = sampleOffset; + /* break; */ + } + + } while (streamFile->get_offset(streamFile)<(int32_t)fileLength); + + if(loopStart == 0 && loopEnd == 0) { + loop_flag = 0; + vgmstream->num_samples = dataLength*28/16/channel_count; + } else { + loop_flag = 1; + vgmstream->loop_start_sample = loopStart; + vgmstream->loop_end_sample = loopEnd; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = dataInterleave; + vgmstream->meta_type = meta_PS2_JOE; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_jstm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_jstm.c new file mode 100644 index 000000000..bb7399958 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_jstm.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* JSTM (.STM (renamed .JSTM) from Tantei Jinguji Saburo - Kind of Blue) */ +VGMSTREAM * init_vgmstream_ps2_jstm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset = 0x20; + int loop_flag; + int channel_count; + char filename[PATH_LIMIT]; + + /* check extension */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("stm",filename_extension(filename)) && + strcasecmp("jstm",filename_extension(filename))) goto fail; + + /* check header (JSTM) */ + if (read_32bitBE(0x0,streamFile) != 0x4A53544D) goto fail; + + loop_flag = (read_32bitLE(0x14,streamFile) != 0); + channel_count = read_16bitLE(0x4,streamFile); + + // hmm, don't know what 6 is, one is probably bytes per sample and the + // other is channels, but who can say? + if (channel_count != read_16bitLE(0x6,streamFile)) goto fail; + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the statistics vitale */ + vgmstream->sample_rate = read_32bitLE(0x8,streamFile); + vgmstream->coding_type = coding_PCM16LE_XOR_int; + vgmstream->num_samples = read_32bitLE(0xC,streamFile)/2/channel_count; + vgmstream->layout_type = layout_none; + + vgmstream->meta_type = meta_PS2_JSTM; + + if (loop_flag) { + vgmstream->loop_start_sample=read_32bitLE(0x14,streamFile)/2/channel_count; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0; i < channel_count; i++) { + vgmstream->ch[i].streamfile = file; + vgmstream->ch[i].channel_start_offset = + vgmstream->ch[i].offset = start_offset + 2*i; + vgmstream->ch[i].key_xor = 0x5A5A; + } + } + + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_kces.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_kces.c new file mode 100644 index 000000000..6be6840cc --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_kces.c @@ -0,0 +1,71 @@ +#include "meta.h" +#include "../util.h" + +/* KCES (from Dance Dance Revolution) */ +VGMSTREAM * init_vgmstream_ps2_kces(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("kces",filename_extension(filename)) && + strcasecmp("vig",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x01006408) + goto fail; + + loop_flag = (read_32bitLE(0x14,streamFile)!=0); + channel_count = read_32bitLE(0x1C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x08,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0C,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x0C,streamFile)-read_32bitLE(0x14,streamFile))*28/16/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile)*28/16/channel_count; + } + + + if(vgmstream->channels==1) { + vgmstream->layout_type=layout_none; + } else { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile); + } + vgmstream->meta_type = meta_PS2_KCES; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_khv.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_khv.c new file mode 100644 index 000000000..e700025fb --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_khv.c @@ -0,0 +1,65 @@ +#include "meta.h" +#include "../util.h" + +/* KHV (from Kingdom Hearts 2) */ +/* VAG files with custom headers */ +VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("khv",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56414770) /* "VAGp" */ + goto fail; + + loop_flag = (read_32bitBE(0x14,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x60; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_KHV; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_leg.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_leg.c new file mode 100644 index 000000000..146bca55b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_leg.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* LEG - found in Legaia 2 - Duel Saga (PS2) +the headers are stored seperately in the main executable... */ +VGMSTREAM * init_vgmstream_leg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("leg",filename_extension(filename))) goto fail; + + /* comparing the filesize with (num_samples*0x800) + headersize, + if it doesn't match, we will abort the vgmstream... */ + if ((read_32bitLE(0x48,streamFile)*0x800)+0x4C != get_streamfile_size(streamFile)) + goto fail; + + loop_flag = (read_32bitLE(0x44,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x4C; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x40,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x48,streamFile)*0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x44,streamFile)*0x800)*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x48,streamFile)*0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x400; + vgmstream->meta_type = meta_LEG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_lpcm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_lpcm.c new file mode 100644 index 000000000..0037cded6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_lpcm.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* LPCM (from Ah! My Goddess (PS2)) */ +VGMSTREAM * init_vgmstream_ps2_lpcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("lpcm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0,streamFile) != 0x4C50434D) /* LPCM */ + goto fail; + + loop_flag = read_32bitLE(0x8,streamFile); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x4,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x8,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0xc,streamFile); + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_PS2_LPCM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c new file mode 100644 index 000000000..0cb4c057c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mcg.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../util.h" + +/* GUN (Gunvari Streams) */ +VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mcg",filename_extension(filename))) goto fail; + + /* check header */ + if (!((read_32bitBE(0x00,streamFile) == 0x4D434700) && + (read_32bitBE(0x20,streamFile) == 0x56414770) && + (read_32bitBE(0x50,streamFile) == 0x56414770))) + goto fail; + + loop_flag = (read_32bitLE(0x34,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x30,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x2C,streamFile)/16*14*channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->meta_type = meta_PS2_MCG; + + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x34,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c new file mode 100644 index 000000000..a509d2db1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mib.c @@ -0,0 +1,355 @@ +#include "meta.h" +#include "../util.h" + +/* MIB + + PS2 MIB format is a headerless format. + The interleave value can be found by checking the body of the data. + + The interleave start allways at offset 0 with a int value (which can have + many values : 0x0000, 0x0002, 0x0006 etc...) follow by 12 empty (zero) values. + + The interleave value is the offset where you found the same 16 bytes. + + The n° of channels can be found by checking each time you found this 16 bytes. + + The interleave value can be very "large" (up to 0x20000 found so far) and is allways + a 0x10 multiply value. + + The loop values can be found by checking the 'tags' offset (found @ 0x02 each 0x10 bytes). + 06 = start of the loop point (can be found for each channel) + 03 - end of the loop point (can be found for each channel) + + The .MIH header contains all informations about frequency, numbers of channels, interleave + but has, afaik, no loop values. + + known extensions : MIB (MIH for the header) MIC (concatenation of MIB+MIH) + Nota : the MIC stuff is not supported here as there is + another MIC format which can be found in Koei Games. + + 2008-05-14 - Fastelbja : First version ... + 2008-05-20 - Fastelbja : Fix loop value when loopEnd==0 +*/ + +VGMSTREAM * init_vgmstream_ps2_mib(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileMIH = NULL; + char filename[PATH_LIMIT]; + + uint8_t mibBuffer[0x10]; + uint8_t testBuffer[0x10]; + uint8_t doChannelUpdate=1; + uint8_t bDoUpdateInterleave=1; + + size_t fileLength; + + off_t loopStart = 0; + off_t loopEnd = 0; + + off_t interleave = 0; + + off_t readOffset = 0; + + char filenameMIH[260]; + off_t loopStartPoints[0x10]; + int loopStartPointsCount=0; + + off_t loopEndPoints[0x10]; + int loopEndPointsCount=0; + + int loopToEnd=0; + int forceNoLoop=0; + int gotEmptyLine=0; + + uint8_t gotMIH=0; + + int i, channel_count=0; + + // Initialize loop point to 0 + for(i=0; i<0x10; i++) { + loopStartPoints[i]=0; + loopEndPoints[i]=0; + } + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mib",filename_extension(filename)) && + strcasecmp("mi4",filename_extension(filename)) && + strcasecmp("vb",filename_extension(filename)) && + strcasecmp("xag",filename_extension(filename))) goto fail; + + /* check for .MIH file */ + strcpy(filenameMIH,filename); + strcpy(filenameMIH+strlen(filenameMIH)-3,"MIH"); + + streamFileMIH = streamFile->open(streamFile,filenameMIH,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (streamFileMIH) gotMIH = 1; + + /* Search for interleave value & loop points */ + /* Get the first 16 values */ + fileLength = get_streamfile_size(streamFile); + + readOffset+=(off_t)read_streamfile(mibBuffer,0,0x10,streamFile); + readOffset=0; + mibBuffer[0]=0; + + do { + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + // be sure to point to an interleave value + if(readOffset<(int32_t)(fileLength*0.5)) { + + if(memcmp(testBuffer+2, mibBuffer+2,0x0e)) { + if(doChannelUpdate) { + doChannelUpdate=0; + channel_count++; + } + if(channel_count<2) + bDoUpdateInterleave=1; + } + + testBuffer[0]=0; + if(!memcmp(testBuffer,mibBuffer,0x10)) { + + gotEmptyLine=1; + + if(bDoUpdateInterleave) { + bDoUpdateInterleave=0; + interleave=readOffset-0x10; + } + if(((readOffset-0x10)==(channel_count*interleave))) { + doChannelUpdate=1; + } + } + } + + // Loop Start ... + if(testBuffer[0x01]==0x06) + { + if(loopStartPointsCount<0x10) + { + loopStartPoints[loopStartPointsCount] = readOffset-0x10; + loopStartPointsCount++; + } + } + + // Loop End ... + if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) { + if(loopEndPointsCount<0x10) + { + loopEndPoints[loopEndPointsCount] = readOffset; + loopEndPointsCount++; + } + } + + if(testBuffer[0x01]==0x04) + { + // 0x04 loop points flag can't be with a 0x03 loop points flag + if(loopStartPointsCount<0x10) + { + loopStartPoints[loopStartPointsCount] = readOffset-0x10; + loopStartPointsCount++; + + // Loop end value is not set by flags ... + // go until end of file + loopToEnd=1; + } + } + + } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); + + if((testBuffer[0]==0x0c) && (testBuffer[1]==0)) + forceNoLoop=1; + + if(channel_count==0) + channel_count=1; + + if(gotMIH) + channel_count=read_32bitLE(0x08,streamFileMIH); + + // force no loop + if(!strcasecmp("vb",filename_extension(filename))) + loopStart=0; + + if(!strcasecmp("xag",filename_extension(filename))) + channel_count=2; + + // Calc Loop Points & Interleave ... + if(loopStartPointsCount>=2) + { + // can't get more then 0x10 loop point ! + if(loopStartPointsCount<=0x0F) { + // Always took the first 2 loop points + interleave=loopStartPoints[1]-loopStartPoints[0]; + loopStart=loopStartPoints[1]; + + // Can't be one channel .mib with interleave values + if((interleave>0) && (channel_count==1)) + channel_count=2; + } else + loopStart=0; + } + + if(loopEndPointsCount>=2) + { + // can't get more then 0x10 loop point ! + if(loopEndPointsCount<=0x0F) { + // No need to recalculate interleave value ... + loopEnd=loopEndPoints[loopEndPointsCount-1]; + + // Can't be one channel .mib with interleave values + if(channel_count==1) channel_count=2; + } else { + loopToEnd=0; + loopEnd=0; + } + } + + if (loopToEnd) + loopEnd=fileLength; + + // force no loop + if(forceNoLoop) + loopEnd=0; + + if((interleave>0x10) && (channel_count==1)) + channel_count=2; + + if(interleave==0) interleave=0x10; + + // further check on channel_count ... + if(gotEmptyLine) + { + int newChannelCount = 0; + + readOffset=0; + + do + { + newChannelCount++; + read_streamfile(testBuffer,readOffset,0x10,streamFile); + readOffset+=interleave; + } while(!memcmp(testBuffer,mibBuffer,16)); + + newChannelCount--; + + if(newChannelCount>channel_count) + channel_count=newChannelCount; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,(loopEnd!=0)); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + + if(gotMIH) { + // Read stuff from the MIH file + vgmstream->channels = read_32bitLE(0x08,streamFileMIH); + vgmstream->sample_rate = read_32bitLE(0x0C,streamFileMIH); + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFileMIH); + vgmstream->num_samples=((read_32bitLE(0x10,streamFileMIH)* + (read_32bitLE(0x14,streamFileMIH)-1)*2)+ + ((read_32bitLE(0x04,streamFileMIH)>>8)*2))/16*28/2; + } else { + vgmstream->channels = channel_count; + vgmstream->interleave_block_size = interleave; + + if(!strcasecmp("mib",filename_extension(filename))) + vgmstream->sample_rate = 44100; + + if(!strcasecmp("mi4",filename_extension(filename))) + vgmstream->sample_rate = 48000; + + if(!strcasecmp("xag",filename_extension(filename))) { + vgmstream->channels=2; + vgmstream->sample_rate = 44100; + } + + if(!strcasecmp("vb",filename_extension(filename))) + { + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size=0; + vgmstream->sample_rate = 22050; + vgmstream->channels = 1; + vgmstream->start_ch = 1; + vgmstream->loop_ch = 1; + } + + vgmstream->num_samples = (int32_t)(fileLength/16/channel_count*28); + } + + if(loopEnd!=0) { + if(vgmstream->channels==1) { + vgmstream->loop_start_sample = loopStart/16*18; + vgmstream->loop_end_sample = loopEnd/16*28; + } else { + vgmstream->loop_start_sample = ((((loopStart/vgmstream->interleave_block_size)-1)*vgmstream->interleave_block_size)/16*14*channel_count)/channel_count; + if(loopStart%vgmstream->interleave_block_size) { + vgmstream->loop_start_sample += (((loopStart%vgmstream->interleave_block_size)-1)/16*14*channel_count); + } + + if(loopEnd==fileLength) + { + vgmstream->loop_end_sample=(loopEnd/16*28)/channel_count; + } else { + vgmstream->loop_end_sample = ((((loopEnd/vgmstream->interleave_block_size)-1)*vgmstream->interleave_block_size)/16*14*channel_count)/channel_count; + + if(loopEnd%vgmstream->interleave_block_size) { + vgmstream->loop_end_sample += (((loopEnd%vgmstream->interleave_block_size)-1)/16*14*channel_count); + } + } + } + } + + if(loopToEnd) + { + // try to find if there's no empty line ... + int emptySamples=0; + + for(i=0; i<16;i++) { + mibBuffer[i]=0; + } + + readOffset=fileLength-0x10; + + do { + read_streamfile(testBuffer,readOffset,0x10,streamFile); + if(!memcmp(mibBuffer,testBuffer,16)) + { + emptySamples+=28; + } + readOffset-=0x10; + } while(!memcmp(testBuffer,mibBuffer,16)); + + vgmstream->loop_end_sample-=(emptySamples*channel_count); + } + vgmstream->meta_type = meta_PS2_MIB; + + if (gotMIH) { + vgmstream->meta_type = meta_PS2_MIB_MIH; + close_streamfile(streamFileMIH); streamFileMIH=NULL; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileMIH) close_streamfile(streamFileMIH); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mic.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mic.c new file mode 100644 index 000000000..3a1f52071 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mic.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../util.h" + +/* MIC + + PS2 MIC format is an interleaved format found in most of KOEI Games + The header always start the long value 0x800 which is the start + of the BGM datas. + + 2008-05-15 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_mic(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mic",filename_extension(filename))) goto fail; + + /* check Header */ + if (read_32bitLE(0x00,streamFile) != 0x800) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x14,streamFile)!=1); + + channel_count=read_32bitLE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + + /* Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x10,streamFile)*14*channel_count; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile)*14*channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x10,streamFile)*14*channel_count; + } + + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile); + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_MIC; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(0x800+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c new file mode 100644 index 000000000..b1dcbea6f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mihb.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../util.h" + +/* MIHB (Merged MIH+MIB) */ +VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int mib_blocks; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mihb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x40000000) + goto fail; + + mib_blocks = read_32bitLE(0x14,streamFile); + loop_flag = 0; + channel_count = read_32bitLE(0x08,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((read_32bitLE(0x10,streamFile))*mib_blocks)*28/16; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = ((read_32bitLE(0x10,streamFile))*mib_blocks)*28/16; + } + + + if (vgmstream->channels > 1) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); + } else { + vgmstream->layout_type = layout_none; + } + + vgmstream->meta_type = meta_PS2_MIHB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_msa.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_msa.c new file mode 100644 index 000000000..6ad75cecf --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_msa.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../util.h" + +/* MSA (from Psyvariar -Complete Edition-) */ +VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("msa",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00000000) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x14; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)*28/32; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x4000; + vgmstream->meta_type = meta_PS2_MSA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mss.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mss.c new file mode 100644 index 000000000..c0a96c27c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mss.c @@ -0,0 +1,68 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_ps2_mss(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mss",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4D435353) /* "MCSS" */ + goto fail; + + loop_flag = 0; + channel_count = read_16bitLE(0x16,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x08,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x1C,streamFile); + + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile); + } + + vgmstream->meta_type = meta_PS2_MSS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_mtaf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mtaf.c new file mode 100644 index 000000000..8465e3563 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_mtaf.c @@ -0,0 +1,182 @@ +//#include +#include "meta.h" +#include "../util.h" + +/* MTAF (Metal Gear Solid 3: Snake Eater) */ +VGMSTREAM * init_vgmstream_ps2_mtaf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int stream_count; + int loop_flag = 1; + int channel_count; + int32_t loop_start; + int32_t loop_end; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mtaf",filename_extension(filename))) goto fail; + + /* check header */ + + // master MTAF header (mostly useless) + + if (read_32bitBE(0, streamFile) != 0x4d544146) // "MTAF" + { + //fprintf(stderr, "no MTAF header at 0x%08lx\n", cur_off); + goto fail; + } + + //const uint32_t pseudo_size = readint32(&mtaf_header_buf[4]); + + // check the rest is clear + for (i = 0x8; i < 0x20; i++) + { + if (read_8bit(i, streamFile) != 0) + { + //fprintf(stderr, "unexpected nonzero in MTAF header at 0x%08lx\n", cur_off+i); + goto fail; + } + } + + // ignore the rest for now + + // HEAD chunk header + + if (read_32bitBE(0x40, streamFile) != 0x48454144) // "HEAD" + { + //fprintf(stderr, "no HEAD chunk at 0x%08lx\n", cur_off); + goto fail; + } + + { + uint32_t mtaf_head_chunk_size = read_32bitLE(0x44, streamFile); + if (mtaf_head_chunk_size != 0xB0) + { + //fprintf(stderr, "unexpected size for MTAF header at 0x%08lx\n", cur_off); + goto fail; + } + } + + stream_count = read_8bit(0x61, streamFile); + + // check some standard stuff + if ( 0 != read_32bitLE(0x48, streamFile) || + 0x7F != read_32bitLE(0x50, streamFile) || + 0x40 != read_32bitLE(0x54, streamFile) || + 0 != read_16bitLE(0x62, streamFile) || + 0 != read_32bitLE(0x6c, streamFile)) // || + //5 != readint32(&mtaf_header_buf[0x68])) || + //(dc.streams==3 ? 12:0) != readint32(&mtaf_header_buf[0x7c])) + { + //fprintf(stderr, "unexpected header values at 0x%08lx\n", cur_off); + goto fail; + } + + // 0 streams should be impossible + if (stream_count == 0) + { + //fprintf(stderr, "0 streams at 0x%08lx\n", cur_off); + goto fail; + } + + // check the other stream count indicator + if (stream_count*0x10 != read_8bit(0x60, streamFile)) + { + //fprintf(stderr, "secondary stream count mismatch at 0x%08lx\n", cur_off); + goto fail; + } + +#if 0 + // maybe this is how to compute channels per stream? + // check total channel count + if (2*stream_count != read_32bitLE(0x4c, streamFile)) + { + //fprintf(stderr, "total channel count does not match stream count at 0x%08lx\n", cur_off); + goto fail; + } +#endif + + // check loop points as frame counts + if (read_32bitLE(0x64, streamFile) != read_32bitLE(0x58, streamFile)/0x100 || + read_32bitLE(0x68, streamFile) != read_32bitLE(0x5c, streamFile)/0x100) + { + //fprintf(stderr, "loop frame count mismatch at 0x%lx\n", cur_off); + goto fail; + } + + // check that rest is clear + for (i = 0x78; i < 0xf8; i++) + { + if (read_8bit(i, streamFile) != 0) + { + //fprintf(stderr, "unexpected nonzero in HEAD chunk at 0x%lx\n", cur_off+i); + goto fail; + } + } + + // check TRKP chunks + for (i = 0; i < 16; i++) + { + if (read_32bitBE(0xf8+0x70*i, streamFile) != 0x54524b50 || // "TRKP" + read_32bitLE(0xf8+0x70*i+4, streamFile) != 0x68) + { + //fprintf(stderr, "missing or unusual TRKP chunk #%d at 0x%lx\n", i, cur_off); + goto fail; + } + } + + // check for grand finale, DATA + if (read_32bitBE(0x7f8, streamFile) != 0x44415441) // "DATA" + { + //fprintf(stderr, "missing DATA header at 0x%lx\n", cur_off); + goto fail; + } + + start_offset = 0x800; + + // seems to always be the case + channel_count = 2 * stream_count; + + loop_start = read_32bitLE(0x58, streamFile); + loop_end = read_32bitLE(0x5c, streamFile); + if (loop_start == loop_end) loop_flag = 0; + + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + // a guess + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_MTAF; + vgmstream->num_samples = read_32bitLE(0x5c, streamFile); + + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + vgmstream->interleave_block_size = 0x110/2; + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_MTAF; + + //const uint32_t pseudo_data_size = readint32(&mtaf_header_buf[4]); + + // TODO: first block + + /* open the file for reading */ + for (i = 0; i < channel_count; i++) { + STREAMFILE * file = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + if (!file) goto fail; + vgmstream->ch[i].streamfile = file; + vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset = start_offset + vgmstream->interleave_block_size*2*(i/2); + } + + return vgmstream; + +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c new file mode 100644 index 000000000..9bad95cac --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_npsf.c @@ -0,0 +1,74 @@ +#include "meta.h" +#include "../util.h" + +/* Sony .ADS with SShd & SSbd Headers */ + +VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("npsf",filename_extension(filename))) goto fail; + + /* check NPSF Header */ + if (read_32bitBE(0x00,streamFile) != 0x4E505346) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x14,streamFile)!=0xFFFFFFFF); + channel_count=read_32bitLE(0x0C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x0C,streamFile); + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x08,streamFile)*28/16; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x08,streamFile)*28/16; + } + + vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile)/2; + vgmstream->meta_type = meta_PS2_NPSF; + start_offset = (off_t)read_32bitLE(0x10,streamFile); + + if (vgmstream->channels == 1) { + vgmstream->layout_type = layout_none; + } else { + vgmstream->layout_type = layout_interleave; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_p2bt.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_p2bt.c new file mode 100644 index 000000000..674177d15 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_p2bt.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +/* P2BT : Pop'n'Music 7 & 8 Bgm File */ + +VGMSTREAM * init_vgmstream_ps2_p2bt(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("p2bt",filename_extension(filename))) goto fail; + + if((read_32bitBE(0x00,streamFile)!=0x4d4F5645) && // MOVE + (read_32bitBE(0x00,streamFile)!=0x50324254)) // P2BT + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x0C,streamFile)!=0); + channel_count=read_32bitLE(0x20,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile);; + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x10,streamFile)/16*28/vgmstream->channels; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile)/16*28/vgmstream->channels; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile);; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_P2BT; + + start_offset = (off_t)0x800; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_pnb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_pnb.c new file mode 100644 index 000000000..86dc606e1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_pnb.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* PNB : PsychoNauts Bgm File */ + +VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("pnb",filename_extension(filename))) goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x0C,streamFile)!=0xFFFFFFFF); + channel_count=1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = 1; + vgmstream->sample_rate = 44100; + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x08,streamFile)/16*28; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile)/16*28; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->interleave_block_size = 0x10; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_PNB; + + start_offset = (off_t)read_32bitBE(0x00,streamFile); + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c new file mode 100644 index 000000000..e502a1ee6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_psh.c @@ -0,0 +1,89 @@ +#include "meta.h" +#include "../util.h" + +/* PSH (from Dawn of Mana - Seiken Densetsu 4) */ +/* probably Square Vag Stream */ +VGMSTREAM * init_vgmstream_ps2_psh(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + uint8_t testBuffer[0x10]; + off_t loopEnd = 0; + off_t readOffset = 0; + size_t fileLength; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("psh",filename_extension(filename))) goto fail; + + /* check header */ + if (read_16bitBE(0x02,streamFile) != 0x6400) + goto fail; + + loop_flag = (read_16bitLE(0x06,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (uint16_t)read_16bitLE(0x0C,streamFile)*0x800*28/16/channel_count; + + // loop end is set by the loop marker which we need to find ... + // there's some extra data on unloop files, so we calculate + // the sample count with loop marker on this files + fileLength = get_streamfile_size(streamFile); + do { + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + // Loop End ... + if(testBuffer[0x01]==0x03) { + if(loopEnd==0) loopEnd = readOffset-0x10; + break; + } + } while (streamFile->get_offset(streamFile)<(int32_t)fileLength); + + if(loopEnd!=0) + vgmstream->num_samples = loopEnd*28/16/channel_count; + + if(loop_flag) { + vgmstream->loop_start_sample = + ((uint16_t)read_16bitLE(0x06,streamFile)-0x8000)*0x400*28/16; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + vgmstream->meta_type = meta_PS2_PSH; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_psw.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_psw.c new file mode 100644 index 000000000..6ac4ffa2b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_psw.c @@ -0,0 +1,88 @@ +#include "meta.h" +#include "../util.h" + +/* PSW (from Rayman Raving Rabbids) +...coefs are missing for the dsp type... */ +VGMSTREAM * init_vgmstream_ps2_psw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("psw",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52494646 && /* "RIFF" */ + read_32bitBE(0x08,streamFile) != 0x57415645 && /* "WAVE" */ + read_32bitBE(0x26,streamFile) != 0x64617461) /* "data" */ + goto fail; + + loop_flag = 0; + channel_count = read_16bitLE(0x16,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + switch ((uint16_t)read_16bitBE(0x14,streamFile)) { + case 0xFFFF: + start_offset = 0x2E; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_16bitLE(0x1C,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x2A,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = read_32bitLE(0x2A,streamFile)*28/16/channel_count; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x6400; + vgmstream->meta_type = meta_PS2_PSW; + + break; + case 0xFEFF: + start_offset = 0x2E; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_16bitLE(0x1C,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitLE(0x2A,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = read_32bitLE(0x2A,streamFile)*28/16/channel_count; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x12C00; + vgmstream->meta_type = meta_PS2_PSW; + + break; +default: + goto fail; +} + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rnd.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rnd.c new file mode 100644 index 000000000..0042359a8 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rnd.c @@ -0,0 +1,56 @@ +#include "meta.h" +#include "../util.h" + +/* rnd (from Karaoke Revolution) */ +VGMSTREAM * init_vgmstream_ps2_rnd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rnd",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x00,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x10)/16*28/vgmstream->channels; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; + vgmstream->meta_type = meta_HGC1; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c new file mode 100644 index 000000000..3e501c69f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rstm.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* RSTM (from Midnight Club 3, Bully - Canis Canim Edit) */ +VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rstm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x5253544D) /* "RSTM" */ + goto fail; + + loop_flag = (read_32bitLE(0x24,streamFile)!=0xFFFFFFFF); + channel_count = read_32bitLE(0x0C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x20,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x24,streamFile)*28/16/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x20,streamFile)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_RSTM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rws.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rws.c new file mode 100644 index 000000000..976c5e449 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rws.c @@ -0,0 +1,103 @@ +#include "meta.h" +#include "../util.h" + +/* RWS (Silent Hill Origins, Ghost Rider, Max Payne 2) */ +VGMSTREAM * init_vgmstream_rws(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rws",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x0D080000) + goto fail; +#if 0 + /* check if is used as container file */ + if (read_32bitBE(0x38,streamFile) != 0x01000000) + goto fail; +#endif + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x50,streamFile); + vgmstream->channels = channel_count; + + + switch (read_32bitLE(0x38,streamFile)) { + case 0x01: + vgmstream->sample_rate = read_32bitLE(0xE4,streamFile); + vgmstream->num_samples = read_32bitLE(0x98,streamFile)/16*28/vgmstream->channels; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x98,streamFile)/16*28/vgmstream->channels; + } + break; + case 0x02: + if (start_offset < 0x800) // Max Payne 2 + { + vgmstream->sample_rate = read_32bitLE(0x178,streamFile); + vgmstream->num_samples = read_32bitLE(0x150,streamFile)/16*28/vgmstream->channels; + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x150,streamFile)/16*28/vgmstream->channels; + } + } + else // Nana (2005)(Konami) + { + vgmstream->sample_rate = read_32bitLE(0x128,streamFile); + vgmstream->num_samples = read_32bitLE(0x7F8,streamFile)/16*28/vgmstream->channels; + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x7F8,streamFile)/16*28/vgmstream->channels; + } + } + break; + default: + goto fail; +} + + +vgmstream->coding_type = coding_PSX; + + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x4C,streamFile)/2; + vgmstream->meta_type = meta_RWS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxw.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxw.c new file mode 100644 index 000000000..520a1d0f7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_rxw.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +/* RXW file (Arc the Lad) */ +VGMSTREAM * init_vgmstream_ps2_rxw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rxw",filename_extension(filename))) goto fail; + + /* check RXWS/FORM Header */ + if (!((read_32bitBE(0x00,streamFile) == 0x52585753) && + (read_32bitBE(0x10,streamFile) == 0x464F524D))) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x3C,streamFile)!=0xFFFFFFFF); + + /* Always stereo files */ + channel_count=2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x2E,streamFile); + + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x38,streamFile)*28/16)/2; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x3C,streamFile)/16*14; + vgmstream->loop_end_sample = read_32bitLE(0x38,streamFile)/16*14; + } + + vgmstream->interleave_block_size = read_32bitLE(0x1c,streamFile)+0x10; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_RXW; + + start_offset = 0x40; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c new file mode 100644 index 000000000..ebe04561a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sfs.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* SFS (from Baroque) */ +VGMSTREAM * init_vgmstream_sfs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sfs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53544552) /* "STER" */ + goto fail; + + loop_flag = (read_32bitLE(0x08,streamFile)!=0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x04,streamFile)*2)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x04,streamFile)*2)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_SFS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_sl3.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sl3.c new file mode 100644 index 000000000..b145cc506 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sl3.c @@ -0,0 +1,65 @@ +#include "meta.h" +#include "../util.h" + +/* SL3 (from Test Drive Unlimited, Transformers) */ +VGMSTREAM * init_vgmstream_sl3(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sl3",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x534C3300) /* "SL3\0" */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x8000; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x8000)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x20,streamFile); + vgmstream->meta_type = meta_SL3; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c new file mode 100644 index 000000000..0c4b76f5f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_smpl.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* SMPL (from Homura) */ +VGMSTREAM * init_vgmstream_ps2_smpl(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("smpl",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x534D504C) /* "SMPL" */ + goto fail; + + loop_flag = 1; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX_badflags; + vgmstream->num_samples = read_32bitBE(0xc,streamFile)*56/32; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x30,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PS2_SMPL; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_snd.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_snd.c new file mode 100644 index 000000000..5990a7b33 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_snd.c @@ -0,0 +1,79 @@ +#include "meta.h" +#include "../util.h" + +/* SND (Warriors of Might and Magic Heroes of M&M:Dragonbone Staff) */ +VGMSTREAM * init_vgmstream_ps2_snd(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("snd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) !=0x53534e44) goto fail; + + /* Force Loop 0->end */ + loop_flag = 1; + channel_count = read_16bitLE(0x0a,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x04,streamFile)+8; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0xe,streamFile); + + if(read_8bit(0x08,streamFile)==1) { + vgmstream->coding_type = coding_INT_DVI_IMA; + } + else + vgmstream->coding_type = coding_PCM16LE; + + vgmstream->num_samples = read_32bitLE(0x16,streamFile); + + vgmstream->interleave_block_size = (uint16_t)read_16bitLE(0x12,streamFile); + + if((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size) + { + /* not sure if this is right ... */ + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%vgmstream->interleave_block_size)/vgmstream->channels; + } else { + vgmstream->layout_type = layout_interleave; + } + vgmstream->meta_type = meta_PS2_SND; + + if(loop_flag) { + vgmstream->loop_start_sample=0; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_spm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_spm.c new file mode 100644 index 000000000..b184407d2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_spm.c @@ -0,0 +1,65 @@ +#include "meta.h" +#include "../util.h" + +/* SPM (from Lethal Skies Elite Pilot: Team SW) */ +VGMSTREAM * init_vgmstream_ps2_spm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("spm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53504D00) /* "SPM" */ + goto fail; + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)/4; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x8,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0xC,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_PS2_SPM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_sps.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sps.c new file mode 100644 index 000000000..f08906c2e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_sps.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../util.h" + +/* SPS (from Ape Escape 2) */ +VGMSTREAM * init_vgmstream_ps2_sps(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sps",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x10,streamFile) != 0x01000000) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x1C,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (read_32bitLE(0x18,streamFile)-0x800)/2/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x200; + vgmstream->meta_type = meta_PS2_SPS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_ster.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ster.c new file mode 100644 index 000000000..f56e57c5c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_ster.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* STER (from Juuni Kokuki: Kakukaku Taru Ou Michi Beni Midori no Uka) */ +VGMSTREAM * init_vgmstream_ps2_ster(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ster",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53544552) /* "STER" */ + goto fail; + + + loop_flag = (read_16bitLE(0xB,streamFile)==0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)*56/32; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x8,streamFile)*28/32; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_STER; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_stm.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_stm.c new file mode 100644 index 000000000..5e391dba6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_stm.c @@ -0,0 +1,78 @@ +#include "meta.h" +#include "../util.h" + +/* STM: Red Dead Revolver */ +VGMSTREAM * init_vgmstream_ps2_stm(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ps2stm",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x53544d41) goto fail; + if (read_32bitBE(0x4,streamFile) != 0x6b690000) goto fail; + + /* check bps */ + if (read_32bitLE(0x10,streamFile) != 4) goto fail; + + loop_flag = read_32bitLE(0x20,streamFile); + channel_count = read_32bitLE(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->sample_rate = (uint16_t)read_32bitLE(0xc,streamFile); + + vgmstream->coding_type = coding_INT_DVI_IMA; + + vgmstream->num_samples = read_32bitLE(0x18,streamFile); + + //vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile) / channel_count; + vgmstream->interleave_block_size = 0x40; + + if(1 < channel_count) + { + /* not sure if this is right ... */ + vgmstream->layout_type = layout_interleave; + } else { + vgmstream->layout_type = layout_none; + } + vgmstream->meta_type = meta_PS2_STM; + + if(loop_flag) { + vgmstream->loop_start_sample=read_32bitLE(0x24,streamFile); + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_str.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_str.c new file mode 100644 index 000000000..d02dcba18 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_str.c @@ -0,0 +1,96 @@ +#include "meta.h" +#include "../util.h" + +/* STR + + 2008-05-19 - Fastelbja : Test version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_str(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * infileSTH = NULL; + char filename[PATH_LIMIT]; + + char * filenameSTH = NULL; + + int i, channel_count, loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check for .MIH file */ + filenameSTH=(char *)malloc(strlen(filename)+1); + + if (!filenameSTH) goto fail; + + strcpy(filenameSTH,filename); + strcpy(filenameSTH+strlen(filenameSTH)-3,"STH"); + + infileSTH = streamFile->open(streamFile,filenameSTH,STREAMFILE_DEFAULT_BUFFER_SIZE); + + /* STH File is necessary, so we can't confuse those file */ + /* with others .STR file as it is a very common extension */ + if (!infileSTH) goto fail; + + if(read_32bitLE(0x2C,infileSTH)==0) + goto fail; + + if((read_32bitLE(0x2C,infileSTH)==0x07) || + (read_32bitLE(0x2C,infileSTH)==0x06)) + channel_count=2; + if(read_32bitLE(0x2C,infileSTH)==0x05) + channel_count=1; + + loop_flag = read_32bitLE(0x2C,infileSTH) & 0x01; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x24,infileSTH); + + vgmstream->interleave_block_size=0x4000; + + if(read_32bitLE(0x40,infileSTH)==0x01) + vgmstream->interleave_block_size = 0x8000; + + vgmstream->num_samples=read_32bitLE(0x20,infileSTH); + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + + vgmstream->meta_type = meta_PS2_STR; + + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x20,infileSTH); + } + + close_streamfile(infileSTH); infileSTH=NULL; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset+=(off_t)(vgmstream->interleave_block_size*i); + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (infileSTH) close_streamfile(infileSTH); + if (filenameSTH) {free(filenameSTH); filenameSTH=NULL;} + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c new file mode 100644 index 000000000..cdfe4a14f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_strlr.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* STR: The Bouncer (PS2) */ +VGMSTREAM * init_vgmstream_ps2_strlr(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int i; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + +#if 0 + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x5354524C) /* "STRL" */ + goto fail; + if (read_32bitBE(0x00,streamFile) != 0x53545252) /* "STRR" */ + goto fail; +#endif + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PSX; + + vgmstream->layout_type = layout_ps2_strlr_blocked; + //vgmstream->interleave_block_size = read_32bitLE(0xC, streamFile); + vgmstream->meta_type = meta_PS2_STRLR; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile, filename, 0x8000); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* Calc num_samples */ + ps2_strlr_block_update(start_offset, vgmstream); + vgmstream->num_samples=0; + + do + { + vgmstream->num_samples += vgmstream->current_block_size * 14 / 16; + ps2_strlr_block_update(vgmstream->next_block_offset, vgmstream); + } while (vgmstream->next_block_offset < get_streamfile_size(streamFile)); + + ps2_strlr_block_update(start_offset, vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_svag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_svag.c new file mode 100644 index 000000000..ee9204180 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_svag.c @@ -0,0 +1,85 @@ +#include "meta.h" +#include "../util.h" + +/* SVAG + + PS2 SVAG format is an interleaved format found in many konami Games + The header start with a Svag id and have the sentence : + "ALL RIGHTS RESERVED.KONAMITYO Sound Design Dept. " + or "ALL RIGHTS RESERVED.KCE-Tokyo Sound Design Dept. " + + 2008-05-13 - Fastelbja : First version ... + Thx to HCS for his awesome work on shortblock interleave +*/ + +VGMSTREAM * init_vgmstream_ps2_svag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("svag",filename_extension(filename))) goto fail; + + /* check SVAG Header */ + if (read_32bitBE(0x00,streamFile) != 0x53766167) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x14,streamFile)==1); + + channel_count=read_16bitLE(0x0C,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_16bitLE(0x0C,streamFile); + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + + /* Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile)/16*28; + vgmstream->loop_end_sample = read_32bitLE(0x04,streamFile)/16*28/vgmstream->channels; + } + + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); + if (channel_count > 1) { + vgmstream->interleave_smallblock_size = (read_32bitLE(0x04,streamFile)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels; + vgmstream->layout_type = layout_interleave_shortblock; + } else { + vgmstream->layout_type = layout_none; + } + vgmstream->meta_type = meta_PS2_SVAG; + + /* open the file for reading by each channel */ + { + for (i=0;i 1) + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + else + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(0x800+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_tec.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tec.c new file mode 100644 index 000000000..270f2456c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tec.c @@ -0,0 +1,93 @@ +#include "meta.h" +#include "../util.h" + +/* TEC (from TECMO games) */ +/* probably TECMO Vag Stream */ +VGMSTREAM * init_vgmstream_ps2_tec(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + int current_chunk; + off_t start_offset; + int dataBuffer = 0; + int Founddata = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tec",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x0; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX_badflags; + vgmstream->num_samples = get_streamfile_size(streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = get_streamfile_size(streamFile)*28/16/channel_count; + } + + // Check the first frame header (should be always zero) + if ((uint8_t)(read_8bit(0x00,streamFile) != 0x0)) + goto fail; + + // Scan for Interleave + { + current_chunk = 16; + while (!Founddata && current_chunk < 65536) { + dataBuffer = (uint8_t)(read_8bit(current_chunk,streamFile)); + if (dataBuffer == 0x0) { /* "0x0" */ + Founddata = 1; + break; + } + current_chunk = current_chunk + 16; + } + } + + // Cancel if we can't find an interleave + if (Founddata == 0) { + goto fail; + } else if (Founddata == 1) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = current_chunk; + } + + // Cancel if the first flag isn't invalid/bad + if ((uint8_t)(read_8bit(0x01,streamFile) == 0x0)) + goto fail; + if ((uint8_t)(read_8bit(0x01+current_chunk,streamFile) == 0x0)) + goto fail; + + vgmstream->meta_type = meta_PS2_TEC; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c new file mode 100644 index 000000000..631e7f788 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_tk5.c @@ -0,0 +1,129 @@ + +#include "meta.h" +#include "../util.h" + +/* TK5 (Tekken 5 Streams) */ +VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tk5",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x544B3553) + goto fail; + + loop_flag = (read_32bitLE(0x0C,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PSX_badflags; + vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_TK5; + + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* TK1 (Tekken 5 Streams from Tekken (NamCollection)) */ +VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tk1",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x544B3553) + goto fail; + + loop_flag = (read_32bitLE(0x0C,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX_badflags; + vgmstream->num_samples = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_TK1; + + if (vgmstream->loop_flag) + { + vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; + vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c new file mode 100644 index 000000000..5b4331210 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vag.c @@ -0,0 +1,227 @@ +#include "meta.h" +#include "../util.h" + +/* VAG + + PS2 SVAG format is an interleaved format found in many SONY Games + The header start with a "VAG" id and is follow by : + + i : interleaved format + + 2008-05-17 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + // used for loop points ... + uint8_t eofVAG[16]={0x00,0x07,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77,0x77}; + uint8_t eofVAG2[16]={0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t readbuf[16]; + + off_t readOffset = 0x20; + + off_t loopStart = 0; + off_t loopEnd = 0; + + uint8_t vagID; + off_t start_offset; + size_t fileLength; + + size_t interleave; + + int loop_flag=0; + int channel_count=1; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vag",filename_extension(filename))) goto fail; + + /* check VAG Header */ + if (((read_32bitBE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700) && + ((read_32bitLE(0x00,streamFile) & 0xFFFFFF00) != 0x56414700)) + goto fail; + + /* Check for correct channel count */ + vagID=read_8bit(0x03,streamFile); + + switch(vagID) { + case '1': + channel_count=1; + break; + case '2': + channel_count=2; + break; + case 'i': + channel_count=2; + break; + case 'V': + if(read_32bitBE(0x20,streamFile)==0x53746572) // vag Stereo + channel_count=2; + case 'p': + if((read_32bitBE(0x04,streamFile)<=0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) { + loop_flag=(read_32bitBE(0x14,streamFile)!=0); + channel_count=2; + } else { + /* Search for loop in VAG */ + fileLength = get_streamfile_size(streamFile); + + do { + readOffset+=0x10; + + // Loop Start ... + if(read_8bit(readOffset+0x01,streamFile)==0x06) { + if(loopStart==0) loopStart = readOffset; + } + + // Loop End ... + if(read_8bit(readOffset+0x01,streamFile)==0x03) { + if(loopEnd==0) loopEnd = readOffset; + } + + // Loop from end to beginning ... + if((read_8bit(readOffset+0x01,streamFile)==0x01)) { + // Check if we have the eof tag after the loop point ... + // if so we don't loop, if not present, we loop from end to start ... + read_streamfile(readbuf,readOffset+0x10,0x10,streamFile); + if((readbuf[0]!=0) && (readbuf[0]!=0x0c)) { + if(memcmp(readbuf,eofVAG,0x10) && (memcmp(readbuf,eofVAG2,0x10))) { + loopStart = 0x40; + loopEnd = readOffset; + } + } + } + + } while (streamFile->get_offset(streamFile)<(off_t)fileLength); + loop_flag = (loopEnd!=0); + } + break; + default: + goto fail; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + + switch(vagID) { + case '1': // VAG1 + vgmstream->layout_type=layout_none; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; + interleave = read_32bitLE(0x08,streamFile); + if (interleave != 0) goto fail; + vgmstream->meta_type=meta_PS2_VAG1; + start_offset=0x40; + break; + case '2': // VAG2 + vgmstream->layout_type=layout_interleave; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; + interleave = 0x800; + vgmstream->meta_type=meta_PS2_VAG2; + start_offset=0x40; + break; + case 'i': // VAGi + vgmstream->layout_type=layout_interleave; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; + interleave = read_32bitLE(0x08,streamFile); + vgmstream->meta_type=meta_PS2_VAGi; + start_offset=0x800; + break; + case 'p': // VAGp + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + interleave=0x10; // used for loop calc + + if((read_32bitBE(0x04,streamFile)==0x00000004) && (read_32bitBE(0x0c,streamFile)<(get_streamfile_size(streamFile)/2))) { + vgmstream->channels=2; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile); + + if(loop_flag) { + vgmstream->loop_start_sample=read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample =read_32bitBE(0x18,streamFile); + } + + start_offset=0x80; + vgmstream->layout_type=layout_interleave; + vgmstream->meta_type=meta_PS2_VAGs; + + // Double VAG Header @ 0x0000 & 0x1000 + if(read_32bitBE(0,streamFile)==read_32bitBE(0x1000,streamFile)) { + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; + interleave=0x1000; + start_offset=0; + } + + } else { + vgmstream->layout_type=layout_none; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/16*28; + vgmstream->meta_type=meta_PS2_VAGp; + start_offset=0x30; + } + break; + case 'V': // pGAV + vgmstream->layout_type=layout_interleave; + interleave=0x2000; + + // Jak X hack ... + if(read_32bitLE(0x1000,streamFile)==0x56414770) + interleave=0x1000; + + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->num_samples = read_32bitLE(0x0C,streamFile)/16*14; + vgmstream->meta_type=meta_PS2_pGAV; + start_offset=0; + break; + default: + goto fail; + } + + vgmstream->interleave_block_size=interleave; + + /* Don't add the header size to loop calc points */ + if(vgmstream->meta_type!=meta_PS2_VAGs) { + loopStart-=start_offset; + loopEnd-=start_offset; + + if(loop_flag!=0) { + vgmstream->loop_start_sample = (int32_t)((loopStart/(interleave*channel_count))*interleave)/16*28; + vgmstream->loop_start_sample += (int32_t)(loopStart%(interleave*channel_count))/16*28; + vgmstream->loop_end_sample = (int32_t)((loopEnd/(interleave*channel_count))*interleave)/16*28; + vgmstream->loop_end_sample += (int32_t)(loopEnd%(interleave*channel_count))/16*28; + } + } + + /* Compression Scheme */ + vgmstream->coding_type = coding_PSX; + + /* open the file for reading by each channel */ + { + for (i=0;iinterleave_block_size > 0) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + } else { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + } + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c new file mode 100644 index 000000000..b4e279e35 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vas.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* VAS (from Pro Baseball Spirits 5) */ +VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vas",filename_extension(filename))) goto fail; + + /* check header */ +#if 0 + if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */ + goto fail; +#endif + + loop_flag = (read_32bitLE(0x10,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x00,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile)*28/16/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x00,streamFile)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x200; + vgmstream->meta_type = meta_PS2_VAS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vbk.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vbk.c new file mode 100644 index 000000000..3bc44fe18 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vbk.c @@ -0,0 +1,111 @@ +#include "meta.h" +#include "../util.h" + +//#include +//#include + +/* VBK (from Disney's Stitch - Experiment 626) */ + +VGMSTREAM * init_vgmstream_ps2_vbk(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + uint8_t testBuffer[0x10]; + off_t loopStart = 0; + off_t loopEnd = 0; + off_t readOffset = 0; + size_t fileLength; + int loop_flag; + int channel_count; + + //_TCHAR szBuffer[100]; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vbk",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x2E56424B) /* .VBK */ + goto fail; + + loop_flag = 1; + channel_count = read_32bitLE(0x28,streamFile) + 1; + + //_stprintf(szBuffer, _T("%x"), channel_count); + //MessageBox(NULL, szBuffer, _T("Foo"), MB_OK); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + fileLength = get_streamfile_size(streamFile); + start_offset = read_32bitLE(0x0C, streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x20,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (fileLength - start_offset)*28/16/channel_count; + + // get loop start + do { + + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + if(testBuffer[0x01]==0x06) + { + loopStart = readOffset-0x10; + break; + } + + } while (streamFile->get_offset(streamFile)<(int32_t)fileLength); + + + // get loop end + readOffset = fileLength - 0x10; + + do { + readOffset-=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + /* Loop End */ + if(testBuffer[0x01]==0x03) + { + loopEnd = readOffset-0x10; + break; + } + } while (readOffset > 0); + + loop_flag = 1; + vgmstream->loop_start_sample = (loopStart-start_offset)*28/16/channel_count; + vgmstream->loop_end_sample = (loopEnd-start_offset)*28/16/channel_count; + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile); + vgmstream->meta_type = meta_PS2_VBK; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c new file mode 100644 index 000000000..3137955b0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgs.c @@ -0,0 +1,122 @@ +#include "meta.h" +#include "../util.h" + +/* VGS (Phantom of Inferno) + + This format is used in _many_ Princess Soft games. +*/ +VGMSTREAM * init_vgmstream_ps2_vgs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + off_t loop_start_offset; + off_t loop_end_offset; + + uint8_t testBuffer[0x10]; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vgs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56475300) + goto fail; + + // get file length + fileLength = get_streamfile_size(streamFile); + + // Find loop start + do { + readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop Start ... + if(testBuffer[0x01] == 0x06) + { + loop_start_offset = readOffset - 0x10; + break; + } + + } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); + + // start at last line of file and move up + readOffset = (int32_t)fileLength - 0x10; + + // Find loop end + do { + readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop End ... + if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) + { + loop_end_offset = readOffset + 0x20; + break; + } + } while (readOffset > 0); + + // setup loops + if (loop_start_offset > 0) + { + loop_flag = 1; + + // if we have a start loop, use EOF if end loop is not found + if (loop_end_offset == 0) + { + loop_end_offset = (int32_t)fileLength - 0x10; + } + } + else + { + loop_flag = 0; + } + + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x30)/16/channel_count*28); + + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; + vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile)*0x1000; + vgmstream->meta_type = meta_PS2_VGS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgv.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgv.c new file mode 100644 index 000000000..7ffb45069 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vgv.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* VGV (from Rune: Viking Warlord) */ +VGMSTREAM * init_vgmstream_ps2_vgv(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vgv",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x08,streamFile) != 0x0) + goto fail; + if (read_32bitBE(0x0C,streamFile) != 0x0) + goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile))*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_PS2_VGV; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset; //+vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c new file mode 100644 index 000000000..fb11ad7ce --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vms.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* VMS (Autobahn Raser: Police Madness [SLES-53536]) */ +VGMSTREAM * init_vgmstream_ps2_vms(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + int header_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vms",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x564D5320) + goto fail; + + loop_flag = 1; + channel_count = read_8bit(0x08,streamFile); + header_size = read_32bitLE(0x1C, streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = header_size; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x14,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((get_streamfile_size(streamFile) - header_size)/16/ channel_count * 28); + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); + vgmstream->meta_type = meta_PS2_VMS; + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile))/16/ channel_count * 28; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_voi.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_voi.c new file mode 100644 index 000000000..2d5a38689 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_voi.c @@ -0,0 +1,81 @@ +#include "meta.h" +#include "../util.h" + +/* VOI - found in "RAW Danger" (PS2) */ +VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("voi",filename_extension(filename))) goto fail; + + /* check header */ + if (((read_32bitLE(0x04,streamFile)*2)+0x800) != (get_streamfile_size(streamFile))) + { + goto fail; + } + + loop_flag = 0; + channel_count = read_32bitLE(0x00,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/channel_count/2; + + if (loop_flag) + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x04,streamFile)/2); + } + + if (read_32bitLE(0x08,streamFile) == 0) + { + vgmstream->sample_rate = 48000; + vgmstream->interleave_block_size = 0x200; + } + else if (read_32bitLE(0x08,streamFile) == 1) + { + vgmstream->sample_rate = 24000; + vgmstream->interleave_block_size = 0x100; + } + else + { + goto fail; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_VOI; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c new file mode 100644 index 000000000..4fc58fc4d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_vpk.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +/* VPK */ + +VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vpk",filename_extension(filename))) goto fail; + + /* check VPK Header */ + if (read_32bitBE(0x00,streamFile) != 0x204B5056) + goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x7FC,streamFile)!=0); + channel_count=read_32bitLE(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = read_32bitLE(0x14,streamFile); + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + + /* Check for Compression Scheme */ + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x04,streamFile)/16*28; + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x7FC,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile)/2; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_VPK; + + start_offset = (off_t)read_32bitLE(0x08,streamFile); + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_wad.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wad.c new file mode 100644 index 000000000..9242f4cb7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wad.c @@ -0,0 +1,71 @@ +#include "meta.h" +#include "../util.h" + +/* WAD (from The golden Compass) */ +VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wad",filename_extension(filename))) goto fail; + + /* check header */ + if ((read_32bitLE(0x00,streamFile)+0x40) != get_streamfile_size(streamFile)) + goto fail; + + loop_flag = 0; + channel_count = (uint16_t) read_16bitLE(0x4,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t) read_16bitLE(0x6,streamFile);; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x0,streamFile)/channel_count/16*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/channel_count/16*28; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + goto fail; + } + + vgmstream->meta_type = meta_PS2_WAD; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_wb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wb.c new file mode 100644 index 000000000..49efbf6b7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wb.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* WB (from Shooting Love. ~TRIZEAL~) */ +VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0,streamFile) != 0x00000000) + goto fail; + + loop_flag = read_32bitLE(0x4,streamFile); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0xC,streamFile)/4; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x8,streamFile); + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_PS2_WB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_wmus.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wmus.c new file mode 100644 index 000000000..f669f78a1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_wmus.c @@ -0,0 +1,102 @@ +#include "meta.h" +#include "../util.h" + +//#include +//#include + +/* WMUS - Arbitrary extension chosen for The Warriors (PS2) */ + +VGMSTREAM * init_vgmstream_ps2_wmus(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag = 1; + int channel_count; + off_t start_offset; + int i; + + int blockCount; + int shortBlockSize; + int lastBlockLocation; + + char filenameWHED[260]; + STREAMFILE * streamFileWHED = NULL; + + //_TCHAR szBuffer[100]; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + + if (strcasecmp("wmus",filename_extension(filename))) + { + goto fail; + } + + /* check for .WHED file */ + strcpy(filenameWHED, filename); + strcpy(filenameWHED + strlen(filenameWHED) - 4, "WHED"); + + streamFileWHED = streamFile->open(streamFile, filenameWHED, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileWHED) + { + goto fail; + } + + /* check loopand channel */ + loop_flag = 1; + channel_count = read_32bitLE(0x14, streamFileWHED); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) + { + goto fail; + } + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04, streamFileWHED); + + vgmstream->coding_type = coding_PSX; + + vgmstream->interleave_block_size = read_32bitLE(0x18, streamFileWHED); + blockCount = read_32bitLE(0x1C, streamFileWHED) * channel_count; + shortBlockSize = read_32bitLE(0x20, streamFileWHED); + + vgmstream->num_samples = (vgmstream->interleave_block_size * blockCount) / 16 / channel_count * 28; + vgmstream->loop_start_sample = 0; + + lastBlockLocation = (vgmstream->interleave_block_size * blockCount) - (vgmstream->interleave_block_size - shortBlockSize); + vgmstream->loop_end_sample = lastBlockLocation / 16 / channel_count * 28; + + //_stprintf(szBuffer, _T("%x"), lastBlockLocation); + //MessageBox(NULL, szBuffer, _T("Foo"), MB_OK); + + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS2_WMUS; + + start_offset = 0; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileWHED) close_streamfile(streamFileWHED); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c new file mode 100644 index 000000000..a16d380e9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa2.c @@ -0,0 +1,118 @@ +#include "meta.h" +#include "../util.h" + +/* XA2 (XG3 Extreme-G Racing) */ +VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa2",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x0,streamFile); + + if (read_32bitLE(0x4,streamFile) > 0x1000) goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/channel_count/16*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile); + vgmstream->meta_type = meta_PS2_XA2; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* XA2 (RC Revenge Pro) */ +VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa2",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0xC,streamFile) != 0x00000000) + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x0,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x1000; + vgmstream->meta_type = meta_PS2_XA2_RRP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa30.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa30.c new file mode 100644 index 000000000..52770d1b9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xa30.c @@ -0,0 +1,63 @@ +#include "meta.h" +#include "../util.h" + +/* XA30 (found in Driver - Parallel Lines) */ +VGMSTREAM * init_vgmstream_xa30(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa30",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x58413330) /* "XA30 */ + goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x0C,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x14,streamFile)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile)*28/16/channel_count; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_XA30; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps2_xau.c b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xau.c new file mode 100644 index 000000000..a662e119c --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps2_xau.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../util.h" + +/* XAU (Spectral Force Chronicle [SLPM-65967]) */ +VGMSTREAM * init_vgmstream_ps2_xau(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xau",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x58415500) + goto fail; + + loop_flag = 0; + channel_count = read_8bit(0x18,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x50, streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((read_32bitBE(0x4C, streamFile) * channel_count)/ 16 / channel_count * 28); + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + vgmstream->meta_type = meta_PS2_XAU; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + + file = streamFile->open(streamFile, filename, STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset + vgmstream->interleave_block_size * i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} \ No newline at end of file diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_cps.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_cps.c new file mode 100644 index 000000000..78e2a8037 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_cps.c @@ -0,0 +1,74 @@ +#include "meta.h" +#include "../util.h" + +/* CPS (from Eternal Sonata) */ +VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("cps",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x43505320) /* "CPS" */ + goto fail; + + loop_flag = read_32bitBE(0x18,streamFile); + + channel_count = read_32bitBE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitBE(0x4,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + if (read_32bitBE(0x20,streamFile)==0x00000000){ + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0xc,streamFile)/4; + vgmstream->interleave_block_size = 2; + } + else { + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0xc,streamFile)*28/32; + vgmstream->interleave_block_size = 0x10; + } + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile)*28/32; + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)*28/32; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_PS3_CPS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c new file mode 100644 index 000000000..a7d19132f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_ivag.c @@ -0,0 +1,86 @@ +#include "meta.h" +#include "../util.h" + +/* IVAG + - The Idolm@ster: Gravure For You! Vol. 3 (PS3) + + Appears to be two VAGp streams interleaved. +*/ +VGMSTREAM * init_vgmstream_ps3_ivag(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ivag",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x49564147) // "IVAG" + goto fail; + + // channel count + channel_count = read_32bitBE(0x08, streamFile); + + // header size + start_offset = 0x40 + (0x40 * channel_count); + + // loop flag + if ((read_32bitBE(0x14, streamFile) != 0 || + (read_32bitBE(0x18, streamFile) != 0))) + { + loop_flag = 1; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x10,streamFile); + + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x1C,streamFile); + vgmstream->meta_type = meta_PS3_IVAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i); + + } + + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c new file mode 100644 index 000000000..405138e6e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_klbs.c @@ -0,0 +1,122 @@ +#include "meta.h" +#include "../util.h" + +/* .KLBS (L@VE ONCE PS3 */ +VGMSTREAM * init_vgmstream_ps3_klbs(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + off_t loop_start_offset; + off_t loop_end_offset; + + uint8_t testBuffer[0x10]; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bnk",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x20,streamFile) != 0x6B6C4253) + goto fail; + + // get file length + fileLength = get_streamfile_size(streamFile); + + // Find loop start + start_offset = read_32bitBE(0x10,streamFile); + readOffset = start_offset; + + do { + readOffset += (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop Start ... + if(testBuffer[0x01] == 0x06) + { + loop_start_offset = readOffset - 0x10; + break; + } + + } while (streamFile->get_offset(streamFile)<((int32_t)fileLength)); + + // start at last line of file and move up + readOffset = (int32_t)fileLength - 0x10; + + // Find loop end + do { + readOffset -= (off_t)read_streamfile(testBuffer, readOffset, 0x10, streamFile); + + // Loop End ... + if((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) + { + loop_end_offset = readOffset + 0x20; + break; + } + } while (readOffset > 0); + + // setup loops + if (loop_start_offset > 0) + { + loop_flag = 1; + + // if we have a start loop, use EOF if end loop is not found + if (loop_end_offset == 0) + { + loop_end_offset = (int32_t)fileLength - 0x10; + } + } + else + { + loop_flag = 0; + } + + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x90, streamFile); + vgmstream->meta_type = meta_PS3_KLBS; + + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((vgmstream->interleave_block_size * channel_count)/16/channel_count*28); + + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start_offset/16/channel_count*28; + vgmstream->loop_end_sample = loop_end_offset/16/channel_count*28; + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c new file mode 100644 index 000000000..3072c3ca4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_msf.c @@ -0,0 +1,156 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* MSF header */ +VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int32_t loop_start, loop_end; + int loop_flag = 0; + int channel_count; + int codec_id; + size_t fileLength; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("msf",filename_extension(filename))) goto fail; + + + if (read_8bit(0x0,streamFile) != 0x4D) goto fail; /* M */ + if (read_8bit(0x1,streamFile) != 0x53) goto fail; /* S */ + if (read_8bit(0x2,streamFile) != 0x46) goto fail; /* F */ + + fileLength = get_streamfile_size(streamFile); + + loop_flag = (read_32bitBE(0x18,streamFile) != 0xFFFFFFFF); + if (loop_flag) + { + loop_start = read_32bitBE(0x18,streamFile); + loop_end = read_32bitBE(0x0C,streamFile); + } + + channel_count = read_32bitBE(0x8,streamFile); + codec_id = read_32bitBE(0x4,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + + /* Sample rate hack for strange files that don't have a specified frequency */ + if (read_32bitBE(0x10,streamFile)==0x00000000) + vgmstream->sample_rate = 48000; + else + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + + start_offset = 0x40; + + switch (codec_id) { + case 0x0: /* PCM (Big Endian) */ + { + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)/2/channel_count; + + if (loop_flag){ + vgmstream->loop_start_sample = loop_start/2/channel_count; + vgmstream->loop_end_sample = loop_end/2/channel_count; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + } + } + break; + case 0x3: /* PSx ADPCM */ + { + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitBE(0x0C,streamFile)*28/16/channel_count; + + if (vgmstream->num_samples == 0xFFFFFFFF) + { + vgmstream->num_samples = (fileLength - start_offset)*28/16/channel_count; + } + + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start*28/16/channel_count; + vgmstream->loop_end_sample = loop_end*28/16/channel_count; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count > 1) + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; // read_32bitBE(0x14,streamFile); + } + } + break; +#ifdef VGM_USE_MPEG + case 0x7: /* MPEG */ + { + mpeg_codec_data *mpeg_data = NULL; + struct mpg123_frameinfo mi; + coding_t ct; + + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, vgmstream->sample_rate, vgmstream->channels, &ct, NULL, NULL); + if (!mpeg_data) goto fail; + vgmstream->codec_data = mpeg_data; + + if (MPG123_OK != mpg123_info(mpeg_data->m, &mi)) goto fail; + + vgmstream->coding_type = ct; + vgmstream->layout_type = layout_mpeg; + if (mi.vbr != MPG123_CBR) goto fail; + vgmstream->num_samples = mpeg_bytes_to_samples(read_32bitBE(0xC,streamFile), &mi); + vgmstream->num_samples -= vgmstream->num_samples%576; + if (loop_flag) { + vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi); + vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; + vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, &mi); + vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; + } + vgmstream->interleave_block_size = 0; + } + break; +#endif + default: + goto fail; + } + + vgmstream->meta_type = meta_PS3_MSF; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_past.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_past.c new file mode 100644 index 000000000..fb3416982 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_past.c @@ -0,0 +1,73 @@ +#include "meta.h" +#include "../util.h" + +/* .PAST (Bakugan Battle Brawlers */ +VGMSTREAM * init_vgmstream_ps3_past(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("past",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x534E4450) /* SNDP */ + goto fail; + + loop_flag = (read_32bitBE(0x1C,streamFile)!=0); + channel_count = (uint16_t)read_16bitBE(0xC,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (read_32bitBE(0x14,streamFile))/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/2/channel_count; + vgmstream->loop_end_sample = read_32bitBE(0x1C,streamFile)/2/channel_count; + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else + { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + vgmstream->meta_type = meta_PS3_PAST; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c new file mode 100644 index 000000000..3b9b0fb05 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_sgh_sgb.c @@ -0,0 +1,200 @@ +#include "meta.h" +#include "../util.h" + +/* SGH+SGB (from Folklore) */ +VGMSTREAM * init_vgmstream_ps3_sgh_sgb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset = 0; + STREAMFILE * streamFileSGH = NULL; + char filename[PATH_LIMIT]; + char filenameSGH[260]; + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sgb",filename_extension(filename))) goto fail; + + strcpy(filenameSGH,filename); + strcpy(filenameSGH+strlen(filenameSGH)-3,"sgh"); + + streamFileSGH = streamFile->open(streamFile,filenameSGH,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileSGH) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFileSGH) != 0x53475844) /* "SGXD" */ + goto fail; + + channel_count = read_8bit(0x29,streamFileSGH); + if (read_32bitBE(0x44,streamFileSGH)==0xFFFFFFFF) + loop_flag = 0; + else + loop_flag = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x2C,streamFileSGH); + vgmstream->num_samples = read_32bitLE(0xC,streamFileSGH)*28/32; + vgmstream->coding_type = coding_PSX; + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFileSGH); + vgmstream->loop_end_sample = read_32bitLE(0x48,streamFileSGH); + } + + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS3_SGH_SGB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileSGH) close_streamfile(streamFileSGH); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +VGMSTREAM * init_vgmstream_ps3_sgx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sgx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53475844) /* "SGXD" */ + goto fail; + + loop_flag = (read_32bitLE(0x44,streamFile) != 0xFFFFFFFF); + channel_count = read_8bit(0x29,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x4,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x2C,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0xC,streamFile)/16/channel_count*28; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x48,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile); + vgmstream->meta_type = meta_PS3_SGX; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +VGMSTREAM * init_vgmstream_ps3_sgd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sgd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53475844) /* "SGXD" */ + goto fail; + + loop_flag = (read_32bitLE(0x44,streamFile) != 0xFFFFFFFF); + channel_count = read_8bit(0x29,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x8,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x2C,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x40,streamFile)/16/channel_count*28; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x48,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_8bit(0x39,streamFile); // just a guess, all of my samples seem to be 0x10 interleave + vgmstream->meta_type = meta_PS3_SGX; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c new file mode 100644 index 000000000..199e29930 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_vawx.c @@ -0,0 +1,79 @@ +#include "meta.h" +#include "../util.h" + +/* VAWX + - No More Heroes: Heroes Paradise (PS3) +*/ +VGMSTREAM * init_vgmstream_ps3_vawx(STREAMFILE *streamFile) +{ + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t fileLength; + off_t readOffset = 0; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vawx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56415758) // "VAWX" + goto fail; + + if (read_8bit(0xF,streamFile) == 2) + { + loop_flag = 1; + } + + channel_count = read_8bit(0x39,streamFile);; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x40,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = ((get_streamfile_size(streamFile)-start_offset)/16/channel_count*28); + + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0x44,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x48,streamFile);; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS3_VAWX; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset + (vgmstream->interleave_block_size * i); + + } + + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ps3_xvag.c b/Frameworks/vgmstream/vgmstream/src/meta/ps3_xvag.c new file mode 100644 index 000000000..f4c0fc47a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ps3_xvag.c @@ -0,0 +1,230 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* XVAG (from Ratchet & Clank Future: Quest for Booty) */ +/* v0.1 : bxaimc : Initial release */ +/* v0.2 : Fastelbja : add support for loops points */ +/* + little endian header values */ + +VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + uint8_t testBuffer[0x10]; + + off_t start_offset; + off_t fileLength; + + int loop_flag = 0; + int channel_count; + off_t readOffset = 0; + int little_endian = 0; + long sample_rate = 0; + long num_samples = 0; + +#ifdef VGM_USE_MPEG + mpeg_codec_data *mpeg_data = NULL; + coding_t mpeg_coding_type = coding_MPEG1_L3; +#endif + + int loopStartPointsCount=0; + int loopEndPointsCount=0; + uint16_t mp3ID; + off_t loopStartPoints[0x10]; + off_t loopEndPoints[0x10]; + + off_t loopStart = 0; + off_t loopEnd = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xvag",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x58564147) /* "XVAG" */ + goto fail; + + fileLength = get_streamfile_size(streamFile); + + if (read_8bit(0x07,streamFile)==0) + little_endian=1; + + if(little_endian) + { + channel_count = read_32bitLE(0x28,streamFile); + start_offset = read_32bitLE(0x4,streamFile); + sample_rate = read_32bitLE(0x3c,streamFile); + num_samples = read_32bitLE(0x30,streamFile); + } + else + { + channel_count = read_32bitBE(0x28,streamFile); + start_offset = read_32bitBE(0x4,streamFile); + sample_rate = read_32bitBE(0x3c,streamFile); + num_samples = read_32bitBE(0x30,streamFile); + } + + readOffset=start_offset; + + // MP3s ? + mp3ID=(uint16_t)read_16bitBE(start_offset,streamFile); + if(mp3ID==0xFFFB) { +#ifdef VGM_USE_MPEG + int rate; + int channels; + + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, -1, -1, &mpeg_coding_type, &rate, &channels); // -1 to not check sample rate or channels + if (!mpeg_data) goto fail; + + channel_count = channels; + sample_rate = rate; + +#else + // reject if no MPEG support + goto fail; +#endif + } else { + // get the loops the same way we get on .MIB + do { + readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile); + + // Loop Start ... + if(testBuffer[0x01]==0x06) + { + if(loopStartPointsCount<0x10) + { + loopStartPoints[loopStartPointsCount] = readOffset-0x10; + loopStartPointsCount++; + } + } + + // Loop End ... + if(((testBuffer[0x01]==0x03) && (testBuffer[0x03]!=0x77)) || + (testBuffer[0x01]==0x01)) + { + if(loopEndPointsCount<0x10) + { + loopEndPoints[loopEndPointsCount] = readOffset; //-0x10; + loopEndPointsCount++; + } + + } + + } while (readOffset<((int32_t)fileLength)); + + // Calc Loop Points & Interleave ... + if(loopStartPointsCount>=channel_count) + { + // can't get more then 0x10 loop point ! + if((loopStartPointsCount<=0x0F) && (loopStartPointsCount>=2)) + { + // Always took the first 2 loop points + loopStart=loopStartPoints[1]-start_offset; + loop_flag=1; + } else + loopStart=0; + } + + if(loopEndPointsCount>=channel_count) + { + // can't get more then 0x10 loop point ! + if((loopEndPointsCount<=0x0F) && (loopEndPointsCount>=2)) { + loop_flag=1; + loopEnd=loopEndPoints[loopEndPointsCount-1]-start_offset; + } else { + loopEnd=0; + } + } + + // as i can get on the header if a song is looped or not + // if try to take the loop marker on the file + // if the last byte of the file is = 00 is assume that the song is not looped + // i know that i can cover 95% of the file, but can't work on some of them + if(read_8bit((fileLength-1),streamFile)==0) + loop_flag=0; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->channels = channel_count; + vgmstream->meta_type = meta_PS3_XVAG; + + if(mp3ID==0xFFFB) { +#ifdef VGM_USE_MPEG + /* NOTE: num_samples seems to be quite wrong for MPEG */ + vgmstream->codec_data = mpeg_data; + vgmstream->layout_type = layout_mpeg; + vgmstream->coding_type = mpeg_coding_type; +#else + // reject if no MPEG support + goto fail; +#endif + } + else { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->coding_type = coding_PSX; + } + + if (loop_flag) { + if(loopStart!=0) { + vgmstream->loop_start_sample = ((((loopStart/vgmstream->interleave_block_size)-1)*vgmstream->interleave_block_size)/16*28)/channel_count; + if(loopStart%vgmstream->interleave_block_size) { + vgmstream->loop_start_sample += (((loopStart%vgmstream->interleave_block_size)-1)/16*14*channel_count); + } + } + vgmstream->loop_end_sample = ((((loopEnd/vgmstream->interleave_block_size)-1)*vgmstream->interleave_block_size)/16*28)/channel_count; + if(loopEnd%vgmstream->interleave_block_size) { + vgmstream->loop_end_sample += (((loopEnd%vgmstream->interleave_block_size)-1)/16*14*channel_count); + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + if(vgmstream->layout_type == layout_interleave) { + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } +#ifdef VGM_USE_MPEG + else if(vgmstream->layout_type == layout_mpeg) { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,MPEG_BUFFER_SIZE); + vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset=start_offset; + } + + } +#endif + else { goto fail; } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: +#ifdef VGM_USE_MPEG + if (mpeg_data) { + mpg123_delete(mpeg_data->m); + free(mpeg_data); + + if (vgmstream) { + vgmstream->codec_data = NULL; + } + } +#endif + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c new file mode 100644 index 000000000..2bae43563 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_cdxa.c @@ -0,0 +1,131 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Sony PSX CD-XA */ +/* No looped file ! */ + +off_t init_xa_channel(int *channel,STREAMFILE *streamFile); + +uint8_t AUDIO_CODING_GET_STEREO(uint8_t value) { + return (uint8_t)(value & 3); +} + +uint8_t AUDIO_CODING_GET_FREQ(uint8_t value) { + return (uint8_t)((value >> 2) & 3); +} + +VGMSTREAM * init_vgmstream_cdxa(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int channel_count; + int headerless=0; + int xa_channel=0; + uint8_t bCoding; + off_t start_offset; + + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xa",filename_extension(filename))) goto fail; + + /* check RIFF Header */ + if (!((read_32bitBE(0x00,streamFile) == 0x52494646) && + (read_32bitBE(0x08,streamFile) == 0x43445841) && + (read_32bitBE(0x0C,streamFile) == 0x666D7420))) + headerless=1; + + /* First init to have the correct info of the channel */ + if (!headerless) { + start_offset=init_xa_channel(&xa_channel,streamFile); + + /* No sound ? */ + if(start_offset==0) + goto fail; + + bCoding = read_8bit(start_offset-5,streamFile); + + switch (AUDIO_CODING_GET_STEREO(bCoding)) { + case 0: channel_count = 1; break; + case 1: channel_count = 2; break; + default: channel_count = 0; break; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->xa_channel = xa_channel; + + switch (AUDIO_CODING_GET_FREQ(bCoding)) { + case 0: vgmstream->sample_rate = 37800; break; + case 1: vgmstream->sample_rate = 18900; break; + default: vgmstream->sample_rate = 0; break; + } + + /* Check for Compression Scheme */ + vgmstream->num_samples = (int32_t)((((get_streamfile_size(streamFile) - 0x3C)/2352)*0x1F80)/(2*channel_count)); + } else + { + channel_count=2; + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + vgmstream->xa_headerless=1; + vgmstream->sample_rate=44100; + vgmstream->channels=2; + vgmstream->num_samples = (int32_t)(((get_streamfile_size(streamFile)/ 0x80)*0xE0)/2); + start_offset=0; + } + + vgmstream->coding_type = coding_XA; + vgmstream->layout_type = layout_xa_blocked; + vgmstream->meta_type = meta_PSX_XA; + + /* open the file for reading by each channel */ + { + STREAMFILE *chstreamfile; + chstreamfile = streamFile->open(streamFile,filename,2352); + + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + } + } + + xa_block_update(start_offset,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +off_t init_xa_channel(int* channel,STREAMFILE* streamFile) { + + off_t block_offset=0x44; + size_t filelength=get_streamfile_size(streamFile); + + int8_t currentChannel; + int8_t subAudio; + + // 0 can't be a correct value + if(block_offset>=(off_t)filelength) + return 0; + + currentChannel=read_8bit(block_offset-7,streamFile); + subAudio=read_8bit(block_offset-6,streamFile); + *channel=currentChannel; + //if (!((currentChannel==channel) && (subAudio==0x64))) { + // block_offset+=2352; + // goto begin; + //} + return block_offset; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c new file mode 100644 index 000000000..d58a8c6b3 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_fag.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" + +/* FAG (Jackie Chan - Stuntmaster) */ +VGMSTREAM * init_vgmstream_psx_fag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("fag",filename_extension(filename))) goto fail; + + /* check header */ + + /* Look if there's more than 1 one file... */ + if (read_32bitBE(0x00,streamFile) != 0x01000000) + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x04,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 24000; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (read_32bitLE(0x08,streamFile))/channel_count/32*28; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x08,streamFile))/channel_count/32*28; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + vgmstream->meta_type = meta_PSX_FAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_gms.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_gms.c new file mode 100644 index 000000000..e1caaf77d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_gms.c @@ -0,0 +1,76 @@ +#include "meta.h" +#include "../util.h" + +/* GMS + + PSX GMS format has no recognition ID. + This format was used essentially in Grandia Games but + can be easily used by other header format as the format of the header is very simple + + known extensions : GMS + + 2008-05-19 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_psx_gms(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("gms",filename_extension(filename))) goto fail; + + /* check loop */ + loop_flag = (read_32bitLE(0x20,streamFile)==0); + + /* Always stereo files */ + channel_count=read_32bitLE(0x00,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x1C,streamFile); + + /* Get loop point values */ + if(vgmstream->loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x800; + vgmstream->meta_type = meta_PSX_GMS; + + start_offset = 0x800; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c b/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c new file mode 100644 index 000000000..0951fc101 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/psx_str_mgav.c @@ -0,0 +1,77 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* STR (Future Cop L.A.P.D.) */ +VGMSTREAM * init_vgmstream_psx_mgav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + off_t start_offset; + off_t current_chunk; + char filename[PATH_LIMIT]; + int loop_flag = 0; + int channel_count; + int dataBuffer = 0; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52565753) /* "RVWS" */ + goto fail; + + loop_flag = 1; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x4,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 16000; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_psx_mgav_blocked; + vgmstream->meta_type = meta_PSX_MGAV; + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + } + } + + // calculate samples + current_chunk = start_offset; + vgmstream->num_samples = 0; + while ((current_chunk + start_offset) < (get_streamfile_size(streamFile))) + { + dataBuffer = (read_32bitBE(current_chunk,streamFile)); + if (dataBuffer == 0x4D474156) /* "MGAV" */ + { + psx_mgav_block_update(start_offset,vgmstream); + vgmstream->num_samples += vgmstream->current_block_size/16*28; + current_chunk += vgmstream->current_block_size + 0x1C; + } + current_chunk += 0x10; + } + + + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/raw.c b/Frameworks/vgmstream/vgmstream/src/meta/raw.c new file mode 100644 index 000000000..e9e21c14e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/raw.c @@ -0,0 +1,59 @@ +#include "meta.h" +#include "../util.h" + +/* RAW + + RAW format is native 44khz PCM file + Nothing more :P ... + + 2008-05-17 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_raw(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("raw",filename_extension(filename))) goto fail; + + /* No check to do as they are raw pcm */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = 2; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile)/4); + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_RAW; + + /* open the file for reading by each channel */ + { + STREAMFILE *chstreamfile; + + /* have both channels use the same buffer, as interleave is so small */ + chstreamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!chstreamfile) goto fail; + + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=(off_t)(i*vgmstream->interleave_block_size); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/redspark.c b/Frameworks/vgmstream/vgmstream/src/meta/redspark.c new file mode 100644 index 000000000..ca982dfba --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/redspark.c @@ -0,0 +1,124 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +static uint32_t rotlwi(uint32_t x, uint32_t r) { + return (x << r) | (x >> (32-r)); +} + +static uint32_t find_key(uint32_t firstword) { + uint32_t expected = 0x52656453; + return firstword ^ expected; +} + +/* RSD - RedSpark (MadWorld) */ +VGMSTREAM * init_vgmstream_RedSpark(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + uint32_t key; + enum {encsize = 0x1000}; + uint8_t buf[encsize]; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* decrypt into buffer */ + { + uint32_t data; + int i; + if (read_streamfile(buf,0,encsize,streamFile)!=encsize) goto fail; + + key = find_key(get_32bitBE(&buf[0])); + data = get_32bitBE(&buf[0]) ^ key; + put_32bitBE(&buf[0], data); + key = rotlwi(key,11); + + for (i=4; i < encsize; i+=4) { + key = rotlwi(key,3) + key; + data = get_32bitBE(&buf[i]) ^ key; + put_32bitBE(&buf[i], data); + } + } + + /* check header */ + if (memcmp(&buf[0],"RedSpark",8)) + goto fail; + + loop_flag = (buf[0x4f] != 0); + channel_count = buf[0x4e]; + + /* make sure loop info is the only two cue points */ + if (loop_flag && buf[0x4f] != 2) goto fail; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x1000; + vgmstream->channels = channel_count; + vgmstream->sample_rate = get_32bitBE(&buf[0x3c]); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = get_32bitBE(&buf[0x40])*14; + if (loop_flag) { + off_t start = 0x54; + start += channel_count*8; + vgmstream->loop_start_sample = get_32bitBE(&buf[start+4])*14; + vgmstream->loop_end_sample = (get_32bitBE(&buf[start+0xc])+1)*14; + if (vgmstream->loop_end_sample > vgmstream->num_samples) { + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } + + if (channel_count >= 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 8; + } else { + vgmstream->layout_type = layout_none; + } + vgmstream->meta_type = meta_RedSpark; + + + { + off_t start = 0x54; + int i,j; + + start += channel_count * 8; + if (loop_flag) { + start += 16; + } + + for (j = 0; j < channel_count; j++) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i] = + get_16bitBE(&buf[start+0x2e*j+i*2]); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset + i*vgmstream->interleave_block_size; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/riff.c b/Frameworks/vgmstream/vgmstream/src/meta/riff.c new file mode 100644 index 000000000..d22211c7f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/riff.c @@ -0,0 +1,937 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Resource Interchange File Format */ + +/* return milliseconds */ +long parse_marker(unsigned char * marker) { + long hh,mm,ss,ms; + if (memcmp("Marker ",marker,7)) return -1; + + if (4 != sscanf((char*)marker+7,"%ld:%ld:%ld.%ld",&hh,&mm,&ss,&ms)) + return -1; + + return ((hh*60+mm)*60+ss)*1000+ms; +} + +/* loop points have been found hiding here */ +void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, + long *loop_start, long *loop_end, int *loop_flag) { + int loop_start_found = 0; + int loop_end_found = 0; + + off_t current_chunk = adtl_offset+4; + + while (current_chunk < adtl_offset+adtl_length) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitLE(current_chunk+4,streamFile); + + if (current_chunk+8+chunk_size > adtl_offset+adtl_length) return; + + switch(chunk_type) { + case 0x6c61626c: /* labl */ + { + unsigned char *labelcontent; + labelcontent = malloc(chunk_size-4); + if (!labelcontent) return; + if (read_streamfile(labelcontent,current_chunk+0xc, + chunk_size-4,streamFile)!=chunk_size-4) { + free(labelcontent); + return; + } + + switch (read_32bitLE(current_chunk+8,streamFile)) { + case 1: + if (!loop_start_found && + (*loop_start = parse_marker(labelcontent))>=0) + { + loop_start_found = 1; + } + break; + case 2: + if (!loop_end_found && + (*loop_end = parse_marker(labelcontent))>=0) + { + loop_end_found = 1; + } + break; + default: + break; + } + + free(labelcontent); + } + break; + default: + break; + } + + current_chunk += 8 + chunk_size; + } + + if (loop_start_found && loop_end_found) *loop_flag = 1; + + /* labels don't seem to be consistently ordered */ + if (*loop_start > *loop_end) { + long temp = *loop_start; + *loop_start = *loop_end; + *loop_end = temp; + } +} + +struct riff_fmt_chunk { + off_t offset; + off_t size; + int sample_rate; + int channel_count; + uint32_t block_size; + int coding_type; + int interleave; +}; + +int read_fmt(int big_endian, + STREAMFILE * streamFile, + off_t current_chunk, + struct riff_fmt_chunk * fmt, + int sns, + int mwv) { + + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + if (big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + fmt->offset = current_chunk; + fmt->size = read_32bit(current_chunk+0x4,streamFile); + + fmt->sample_rate = read_32bit(current_chunk+0x0c,streamFile); + fmt->channel_count = read_16bit(current_chunk+0x0a,streamFile); + fmt->block_size = read_16bit(current_chunk+0x14,streamFile); + + switch ((uint16_t)read_16bit(current_chunk+0x8,streamFile)) { + case 1: /* PCM */ + switch (read_16bit(current_chunk+0x16,streamFile)) { + case 16: + if (big_endian) { + fmt->coding_type = coding_PCM16BE; + } else { + fmt->coding_type = coding_PCM16LE; + } + fmt->interleave = 2; + break; + case 8: + fmt->coding_type = coding_PCM8_U_int; + fmt->interleave = 1; + break; + default: + goto fail; + } + break; + case 2: /* MS ADPCM */ + /* ensure 4bps */ + if (read_16bit(current_chunk+0x16,streamFile)!=4) + goto fail; + + fmt->coding_type = coding_MSADPCM; + fmt->interleave = 0; + + break; + case 0x11: /* MS IMA ADCM */ + /* ensure 4bps */ + if (read_16bit(current_chunk+0x16,streamFile)!=4) + goto fail; + fmt->coding_type = coding_MS_IMA; + fmt->interleave = 0; + break; + case 0x69: /* MS IMA ADCM - Rayman Raving Rabbids 2 (PC) */ + /* ensure 4bps */ + if (read_16bit(current_chunk+0x16,streamFile)!=4) + goto fail; + fmt->coding_type = coding_MS_IMA; + fmt->interleave = 0; + break; + case 0x555: /* Level-5 0x555 ADPCM */ + if (!mwv) goto fail; + fmt->coding_type = coding_L5_555; + fmt->interleave = 0x12; + break; + case 0x5050: /* Ubisoft .sns uses this for DSP */ + if (!sns) goto fail; + fmt->coding_type = coding_NGC_DSP; + fmt->interleave = 8; + break; + case 0xFFF0: /* */ + fmt->coding_type = coding_NGC_DSP; + fmt->interleave = 8; + break; +#ifdef VGM_USE_MAIATRAC3PLUS + case 0xFFFE: /* WAVEFORMATEXTENSIBLE */ + if (read_32bit(current_chunk+0x20,streamFile) == 0xE923AABF && + read_16bit(current_chunk+0x24,streamFile) == (int16_t)0xCB58 && + read_16bit(current_chunk+0x26,streamFile) == 0x4471 && + read_32bitLE(current_chunk+0x28,streamFile) == 0xFAFF19A1 && + read_32bitLE(current_chunk+0x2C,streamFile) == 0x62CEE401) { + uint16_t bztmp = read_16bit(current_chunk+0x32,streamFile); + bztmp = (bztmp >> 8) | (bztmp << 8); + fmt->coding_type = coding_AT3plus; + fmt->block_size = (bztmp & 0x3FF) * 8 + 8; + fmt->interleave = 0; + } + break; +#endif + default: + goto fail; + } + + return 0; + +fail: + return -1; +} + +VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct riff_fmt_chunk fmt; + + off_t file_size = -1; + int sample_count = 0; + int fact_sample_count = -1; + off_t start_offset = -1; + + int loop_flag = 0; + long loop_start_ms = -1; + long loop_end_ms = -1; + off_t loop_start_offset = -1; + off_t loop_end_offset = -1; + uint32_t riff_size; + uint32_t data_size = 0; + + int FormatChunkFound = 0; + int DataChunkFound = 0; + + /* Level-5 mwv */ + int mwv = 0; + off_t mwv_pflt_offset = -1; + off_t mwv_ctrl_offset = -1; + + /* Ubisoft sns */ + int sns = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wav",filename_extension(filename)) && + strcasecmp("lwav",filename_extension(filename)) +#ifdef VGM_USE_MAIATRAC3PLUS + && strcasecmp("at3",filename_extension(filename)) +#endif + ) + { + if (!strcasecmp("mwv",filename_extension(filename))) + mwv = 1; + else if (!strcasecmp("sns",filename_extension(filename))) + sns = 1; + else + goto fail; + } + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x52494646) /* "RIFF" */ + goto fail; + /* check for WAVE form */ + if ((uint32_t)read_32bitBE(8,streamFile)!=0x57415645) /* "WAVE" */ + goto fail; + + riff_size = read_32bitLE(4,streamFile); + file_size = get_streamfile_size(streamFile); + + /* check for tructated RIFF */ + if (file_size < riff_size+8) goto fail; + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xc; /* start with first chunk */ + + while (current_chunk < file_size && current_chunk < riff_size+8) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitLE(current_chunk+4,streamFile); + + if (current_chunk+8+chunk_size > file_size) goto fail; + + switch(chunk_type) { + case 0x666d7420: /* "fmt " */ + /* only one per file */ + if (FormatChunkFound) goto fail; + FormatChunkFound = 1; + + if (-1 == read_fmt(0, /* big endian == false*/ + streamFile, + current_chunk, + &fmt, + sns, + mwv)) + goto fail; + + break; + case 0x64617461: /* data */ + /* at most one per file */ + if (DataChunkFound) goto fail; + DataChunkFound = 1; + + start_offset = current_chunk + 8; + data_size = chunk_size; + break; + case 0x4C495354: /* LIST */ + /* what lurks within?? */ + switch (read_32bitBE(current_chunk + 8, streamFile)) { + case 0x6164746C: /* adtl */ + /* yay, atdl is its own little world */ + parse_adtl(current_chunk + 8, chunk_size, + streamFile, + &loop_start_ms,&loop_end_ms,&loop_flag); + break; + default: + break; + } + break; + case 0x736D706C: /* smpl */ + /* check loop count */ + if (read_32bitLE(current_chunk+0x24, streamFile)==1) + { + /* check loop info */ + if (read_32bitLE(current_chunk+0x2c+4, streamFile)==0) + { + loop_flag = 1; + loop_start_offset = + read_32bitLE(current_chunk+0x2c+8, streamFile); + loop_end_offset = + read_32bitLE(current_chunk+0x2c+0xc,streamFile); + } + } + break; + case 0x70666c74: /* pflt */ + if (!mwv) break; /* ignore if not in an mwv */ + /* predictor filters */ + mwv_pflt_offset = current_chunk; + break; + case 0x6374726c: /* ctrl */ + if (!mwv) break; /* ignore if not in an mwv */ + /* loops! */ + if (read_32bitLE(current_chunk+8, streamFile)) + { + loop_flag = 1; + } + mwv_ctrl_offset = current_chunk; + break; + case 0x66616374: /* fact */ + if (chunk_size != 4 + && (!(sns && chunk_size == 0x10))) break; + fact_sample_count = read_32bitLE(current_chunk+8, streamFile); + break; + default: + /* ignorance is bliss */ + break; + } + + current_chunk += 8+chunk_size; + } + } + + if (!FormatChunkFound || !DataChunkFound) goto fail; + + switch (fmt.coding_type) { + case coding_PCM16LE: + sample_count = data_size/2/fmt.channel_count; + break; + case coding_PCM8_U_int: + sample_count = data_size/fmt.channel_count; + break; + case coding_L5_555: + sample_count = data_size/0x12/fmt.channel_count*32; + break; + case coding_MSADPCM: + sample_count = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); + break; + case coding_MS_IMA: + sample_count = (data_size / fmt.block_size) * (fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count + + ((data_size % fmt.block_size) ? (data_size % fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count : 0); + break; + case coding_NGC_DSP: + break; +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: + sample_count = (data_size / fmt.block_size) * 2048 * fmt.channel_count; + break; +#endif + default: + goto fail; + } + + /* .sns uses fact chunk */ + if (sns) + { + if (-1 == fact_sample_count) goto fail; + sample_count = fact_sample_count; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = fmt.sample_rate; + + vgmstream->coding_type = fmt.coding_type; + + vgmstream->layout_type = layout_none; + if (fmt.channel_count > 1) { + switch (fmt.coding_type) { + case coding_PCM8_U_int: + case coding_MS_IMA: + case coding_MSADPCM: +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: +#endif + // use layout_none from above + break; + default: + vgmstream->layout_type = layout_interleave; + break; + } + } + + vgmstream->interleave_block_size = fmt.interleave; + switch (fmt.coding_type) { + case coding_MSADPCM: + case coding_MS_IMA: +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: +#endif + // override interleave_block_size with frame size + vgmstream->interleave_block_size = fmt.block_size; + break; + default: + // use interleave from above + break; + } + +#ifdef VGM_USE_MAIATRAC3PLUS + if (fmt.coding_type == coding_AT3plus) { + maiatrac3plus_codec_data *data = malloc(sizeof(maiatrac3plus_codec_data)); + data->buffer = 0; + data->samples_discard = 0; + data->handle = Atrac3plusDecoder_openContext(); + vgmstream->codec_data = data; + } +#endif + + if (loop_flag) { + if (loop_start_ms >= 0) + { + vgmstream->loop_start_sample = + (long long)loop_start_ms*fmt.sample_rate/1000; + vgmstream->loop_end_sample = + (long long)loop_end_ms*fmt.sample_rate/1000; + vgmstream->meta_type = meta_RIFF_WAVE_labl_Marker; + } + else if (loop_start_offset >= 0) + { + vgmstream->loop_start_sample = loop_start_offset; + vgmstream->loop_end_sample = loop_end_offset; + vgmstream->meta_type = meta_RIFF_WAVE_smpl; + } + else if (mwv && mwv_ctrl_offset != -1) + { + vgmstream->loop_start_sample = read_32bitLE(mwv_ctrl_offset+12, + streamFile); + vgmstream->loop_end_sample = sample_count; + } + } + else + { + vgmstream->meta_type = meta_RIFF_WAVE; + } + + if (mwv) + { + int i, c; + if (fmt.coding_type == coding_L5_555) + { + const int filter_order = 3; + int filter_count = read_32bitLE(mwv_pflt_offset+12, streamFile); + + if (mwv_pflt_offset == -1 || + read_32bitLE(mwv_pflt_offset+8, streamFile) != filter_order || + read_32bitLE(mwv_pflt_offset+4, streamFile) < 8 + filter_count * 4 * filter_order) + goto fail; + if (filter_count > 0x20) goto fail; + for (c = 0; c < fmt.channel_count; c++) + { + for (i = 0; i < filter_count * filter_order; i++) + { + vgmstream->ch[c].adpcm_coef_3by32[i] = read_32bitLE( + mwv_pflt_offset+16+i*4, streamFile + ); + } + } + } + vgmstream->meta_type = meta_RIFF_WAVE_MWV; + } + + if (sns) + { + int c; + /* common codebook? */ + static const int16_t coef[16] = + {0x04ab,0xfced,0x0789,0xfedf,0x09a2,0xfae5,0x0c90,0xfac1, + 0x084d,0xfaa4,0x0982,0xfdf7,0x0af6,0xfafa,0x0be6,0xfbf5}; + + for (c = 0; c < fmt.channel_count; c++) + { + int i; + for (i = 0; i < 16; i++) + { + vgmstream->ch[c].adpcm_coef[i] = coef[i]; + } + } + vgmstream->meta_type = meta_RIFF_WAVE_SNS; + } + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset+i*fmt.interleave; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +VGMSTREAM * init_vgmstream_rifx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct riff_fmt_chunk fmt; + + off_t file_size = -1; + int sample_count = 0; + int fact_sample_count = -1; + off_t start_offset = -1; + off_t wiih_offset = -1; + uint32_t wiih_size = 0; + + int loop_flag = 0; + off_t loop_start_offset = -1; + off_t loop_end_offset = -1; + uint32_t riff_size; + uint32_t data_size = 0; + + int FormatChunkFound = 0; + int DataChunkFound = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wav",filename_extension(filename)) && + strcasecmp("lwav",filename_extension(filename))) + { + goto fail; + } + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x52494658) /* "RIFX" */ + goto fail; + /* check for WAVE form */ + if ((uint32_t)read_32bitBE(8,streamFile)!=0x57415645) /* "WAVE" */ + goto fail; + + riff_size = read_32bitBE(4,streamFile); + file_size = get_streamfile_size(streamFile); + + /* check for tructated RIFF */ + if (file_size < riff_size+8) goto fail; + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xc; /* start with first chunk */ + + while (current_chunk < file_size && current_chunk < riff_size+8) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitBE(current_chunk+4,streamFile); + + if (current_chunk+8+chunk_size > file_size) goto fail; + + switch(chunk_type) { + case 0x666d7420: /* "fmt " */ + /* only one per file */ + if (FormatChunkFound) goto fail; + FormatChunkFound = 1; + + if (-1 == read_fmt(1, /* big endian == true */ + streamFile, + current_chunk, + &fmt, + 0, /* sns == false */ + 0)) /* mwv == false */ + goto fail; + + break; + case 0x64617461: /* data */ + /* at most one per file */ + if (DataChunkFound) goto fail; + DataChunkFound = 1; + + start_offset = current_chunk + 8; + data_size = chunk_size; + break; + case 0x736D706C: /* smpl */ + /* check loop count */ + if (read_32bitBE(current_chunk+0x24, streamFile)==1) + { + /* check loop info */ + if (read_32bitBE(current_chunk+0x2c+4, streamFile)==0) + { + loop_flag = 1; + loop_start_offset = + read_32bitBE(current_chunk+0x2c+8, streamFile); + loop_end_offset = + read_32bitBE(current_chunk+0x2c+0xc,streamFile); + } + } + break; + case 0x66616374: /* fact */ + if (chunk_size != 4) break; + fact_sample_count = read_32bitBE(current_chunk+8, streamFile); + break; + case 0x57696948: /* WiiH */ + wiih_size = read_32bitBE(current_chunk+4, streamFile); + wiih_offset = current_chunk+8; + break; + default: + /* ignorance is bliss */ + break; + } + + current_chunk += 8+chunk_size; + } + } + + if (!FormatChunkFound || !DataChunkFound) goto fail; + + if (wiih_offset < 0 && fmt.coding_type == coding_MSADPCM && + fmt.size == 0x1c + fmt.channel_count * 0x2e + 2) { + + /* Epic Mickey 2 */ + + wiih_offset = fmt.offset + 8 + 0x1c; + wiih_size = fmt.channel_count * 0x2e; + fmt.coding_type = coding_NGC_DSP; + fmt.interleave = 8; + } + + switch (fmt.coding_type) { + case coding_PCM16BE: + sample_count = data_size/2/fmt.channel_count; + break; + case coding_PCM8_U_int: + sample_count = data_size/fmt.channel_count; + break; + case coding_NGC_DSP: + /* the only way of getting DSP info right now */ + if (wiih_offset < 0 || wiih_size != 0x2e*fmt.channel_count) + goto fail; + + break; +#if 0 + /* found in RE:ORC, looks like it should be MS_IMA instead */ + case coding_MSADPCM: + sample_count = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); + break; +#endif + default: + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = fmt.sample_rate; + + vgmstream->coding_type = fmt.coding_type; + + vgmstream->layout_type = layout_none; + if (fmt.channel_count > 1) { + switch (fmt.coding_type) { + case coding_PCM8_U_int: + case coding_MS_IMA: + case coding_MSADPCM: + // use layout_none from above + break; + default: + vgmstream->layout_type = layout_interleave; + break; + } + } + + vgmstream->interleave_block_size = fmt.interleave; + switch (fmt.coding_type) { + case coding_MSADPCM: + case coding_MS_IMA: + // override interleave_block_size with frame size + vgmstream->interleave_block_size = fmt.block_size; + break; + default: + // use interleave from above + break; + } + + if (fmt.coding_type == coding_MS_IMA) + vgmstream->interleave_block_size = fmt.block_size; + + if (loop_flag) { + if (loop_start_offset >= 0) + { + vgmstream->loop_start_sample = loop_start_offset; + vgmstream->loop_end_sample = loop_end_offset; + vgmstream->meta_type = meta_RIFX_WAVE_smpl; + } + } + else + { + vgmstream->meta_type = meta_RIFX_WAVE; + } + + /* read from WiiH */ + if (wiih_offset >= 0) { + int i,j; + for (i=0;ich[i].adpcm_coef[j] = read_16bitBE(wiih_offset + i * 0x2e + j * 2,streamFile); + vgmstream->ch[i].adpcm_history1_16 = read_16bitBE(wiih_offset + i * 0x2e + 0x24,streamFile); + vgmstream->ch[i].adpcm_history2_16 = read_16bitBE(wiih_offset + i * 0x2e + 0x26,streamFile); + } + } + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset+i*fmt.interleave; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* XNBm (Windows 7 Phone) */ +VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + struct riff_fmt_chunk fmt; + + off_t file_size = -1; + int sample_count = 0; + off_t start_offset = -1; + + int loop_flag = 0; +#if 0 + long loop_start_ms = -1; + long loop_end_ms = -1; + off_t loop_start_offset = -1; + off_t loop_end_offset = -1; +#endif + + uint32_t xnbm_size; + uint32_t data_size = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xnb",filename_extension(filename))) + { + goto fail; + } + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x584E426d) /* "XNBm" */ + goto fail; + /* check version? */ + if ((uint32_t)read_16bitLE(4,streamFile)!=5) + goto fail; + + xnbm_size = read_32bitLE(6,streamFile); + file_size = get_streamfile_size(streamFile); + + /* check for tructated XNBm */ + if (file_size < xnbm_size) goto fail; + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xa; /* start with first chunk */ + int id_string_len; + uint32_t fmt_chunk_size; + + /* flag? count of strings? */ + if (read_8bit(current_chunk ++, streamFile) != 1) + goto fail; + + /* string length */ + id_string_len = read_8bit(current_chunk ++, streamFile); + + /* skip string */ + /* may want to check this ID "Microsoft.Xna.Framework.Content.SoundEffectReader" */ + current_chunk += id_string_len; + + /* ???? */ + if (read_32bitLE(current_chunk, streamFile) != 0) + goto fail; + current_chunk += 4; + + /* ???? */ + if (read_8bit(current_chunk ++, streamFile) != 0) + goto fail; + + /* flag? count of chunks? */ + if (read_8bit(current_chunk++, streamFile) != 1) + goto fail; + + /* fmt size */ + fmt_chunk_size = read_32bitLE(current_chunk, streamFile); + current_chunk += 4; + + if (-1 == read_fmt(0, /* big endian == false */ + streamFile, + current_chunk-8, /* read_fmt() expects to skip "fmt "+size */ + &fmt, + 0, /* sns == false */ + 0)) /* mwv == false */ + goto fail; + + current_chunk += fmt_chunk_size; + + /* data size! */ + data_size = read_32bitLE(current_chunk, streamFile); + current_chunk += 4; + + start_offset = current_chunk; + } + + switch (fmt.coding_type) { + case coding_PCM16LE: + sample_count = data_size/2/fmt.channel_count; + break; + case coding_PCM8_U_int: + sample_count = data_size/fmt.channel_count; + break; + case coding_MSADPCM: + sample_count = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); + break; + case coding_MS_IMA: + sample_count = (data_size / fmt.block_size) * (fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count + + ((data_size % fmt.block_size) ? (data_size % fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count : 0); + break; + default: + goto fail; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = sample_count; + vgmstream->sample_rate = fmt.sample_rate; + + vgmstream->coding_type = fmt.coding_type; + + vgmstream->layout_type = layout_none; + if (fmt.channel_count > 1) { + switch (fmt.coding_type) { + case coding_PCM8_U_int: + case coding_MS_IMA: + case coding_MSADPCM: + // use layout_none from above + break; + default: + vgmstream->layout_type = layout_interleave; + break; + } + } + + vgmstream->interleave_block_size = fmt.interleave; + switch (fmt.coding_type) { + case coding_MSADPCM: + case coding_MS_IMA: + // override interleave_block_size with frame size + vgmstream->interleave_block_size = fmt.block_size; + break; + default: + // use interleave from above + break; + } + + vgmstream->meta_type = meta_XNBm; + + /* open the file, set up each channel */ + { + int i; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset = + start_offset+i*fmt.interleave; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rkv.c b/Frameworks/vgmstream/vgmstream/src/meta/rkv.c new file mode 100644 index 000000000..56f7efb3d --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rkv.c @@ -0,0 +1,77 @@ +#include "meta.h" +#include "../util.h" + +/* RKV (from Legacy of Kain - Blood Omen 2) */ +VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset=0; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rkv",filename_extension(filename))) goto fail; + + // Some RKV got info @ offset 0 + // Some other @ offset 4 + if(read_32bitLE(0,streamFile)==0) + start_offset=4; + + loop_flag = (read_32bitLE(start_offset+4,streamFile)!=0xFFFFFFFF); + channel_count = read_32bitLE(start_offset+0x0c,streamFile)+1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(start_offset,streamFile); + vgmstream->coding_type = coding_PSX; + + // sometimes sample count is not set on the header + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/16*28/channel_count; + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(start_offset+4,streamFile); + vgmstream->loop_end_sample = read_32bitLE(start_offset+8,streamFile); + } + + start_offset = 0x800; + + if((get_streamfile_size(streamFile)-0x800)%0x400) + { + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->interleave_smallblock_size=((get_streamfile_size(streamFile)-0x800)%0x400)/channel_count; + } else { + vgmstream->layout_type = layout_interleave; + } + + vgmstream->interleave_block_size = 0x400; + vgmstream->meta_type = meta_PS2_RKV; + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rs03.c b/Frameworks/vgmstream/vgmstream/src/meta/rs03.c new file mode 100644 index 000000000..03307961e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rs03.c @@ -0,0 +1,81 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* .dsp w/ RS03 header - from Metroid Prime 2 */ + +VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int channel_count; + int loop_flag; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x52530003) /* "RS03" */ + goto fail; + + channel_count = read_32bitBE(4,streamFile); + if (channel_count != 1 && channel_count != 2) goto fail; + + /* build the VGMSTREAM */ + + loop_flag = read_16bitBE(0x14,streamFile); + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(8,streamFile); + vgmstream->sample_rate = read_32bitBE(0xc,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile)/8*14; + vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile)/8*14; + } + + start_offset = 0x60; + + vgmstream->coding_type = coding_NGC_DSP; + if (channel_count == 2) { + vgmstream->layout_type = layout_interleave_shortblock; + vgmstream->interleave_block_size = 0x8f00; + vgmstream->interleave_smallblock_size = (((get_streamfile_size(streamFile)-start_offset)%(0x8f00*2))/2+7)/8*8; + } else + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_DSP_RS03; + + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x20+i*2,streamFile); + if (channel_count==2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x40+i*2,streamFile); + } + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8f00); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset+0x8f00*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c new file mode 100644 index 000000000..b6dfce142 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsd.c @@ -0,0 +1,1146 @@ +#include "meta.h" +#include "../util.h" + +/* RSD */ +/* RSD2VAG */ +VGMSTREAM * init_vgmstream_rsd2vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x56414720) /* VAG\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->meta_type = meta_RSD2VAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* RSD2PCMB - Big Endian */ +VGMSTREAM * init_vgmstream_rsd2pcmb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x50434D42) /* PCMB */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + } + + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + + vgmstream->meta_type = meta_RSD2PCMB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* RSD2XADP */ +VGMSTREAM * init_vgmstream_rsd2xadp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534432) /* RSD2 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); /* not sure about this */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_RSD2XADP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + if (vgmstream->coding_type == coding_XBOX) { + vgmstream->layout_type=layout_none; + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* RSD3VAG */ +VGMSTREAM * init_vgmstream_rsd3vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534433) /* RSD3 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x56414720) /* VAG\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); + vgmstream->meta_type = meta_RSD3VAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* RSD3GADP */ +VGMSTREAM * init_vgmstream_rsd3gadp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534433) /* RSD3 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x47414450) /* WADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_RSD3GADP; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1D+i*2,streamFile); + } + } + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* RSD3PCM - Little Endian */ +VGMSTREAM * init_vgmstream_rsd3pcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534433) /* RSD3 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x50434D20) /* PCM\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + } + + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + vgmstream->meta_type = meta_RSD3PCM; + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* RSD3PCMB - Big Endian */ +VGMSTREAM * init_vgmstream_rsd3pcmb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534433) /* RSD3 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x50434D42) /* PCMB */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + } + + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + + vgmstream->meta_type = meta_RSD3PCMB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* RSD4VAG */ +VGMSTREAM * init_vgmstream_rsd4vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534434) /* RSD4 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x56414720) /* VAG\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0xC,streamFile); + vgmstream->meta_type = meta_RSD4VAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* RSD4PCM - Little Endian */ +VGMSTREAM * init_vgmstream_rsd4pcm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534434) /* RSD4 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x50434D20) /* PCM\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)/2/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_RSD4PCM; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + + +/* RSD4PCMB - Big Endian */ +VGMSTREAM * init_vgmstream_rsd4pcmb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534434) /* RSD4 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x50434D42) /* PCMB */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)/2/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_RSD4PCMB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* RSD4RADP */ +VGMSTREAM * init_vgmstream_rsd4radp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534434) /* RSD4 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x52414450) /* RADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_RAD_IMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/0x14/channel_count*32; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x14*channel_count; + vgmstream->meta_type = meta_RSD4RADP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].offset=vgmstream->ch[i].channel_start_offset=start_offset; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* RSD6RADP */ +VGMSTREAM * init_vgmstream_rsd6radp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x52414450) /* RADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_RAD_IMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/0x14/channel_count*32; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x14*channel_count; + vgmstream->meta_type = meta_RSD6RADP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].offset=vgmstream->ch[i].channel_start_offset=start_offset; + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* RSD6VAG */ +VGMSTREAM * init_vgmstream_rsd6vag(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x56414720) /* VAG\0x20 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0xC,streamFile); + vgmstream->meta_type = meta_RSD6VAG; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* RSD6WADP */ +VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x57414450) /* WADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave_byte; //layout_interleave; + vgmstream->interleave_block_size = 2; //read_32bitLE(0xC,streamFile); + vgmstream->meta_type = meta_RSD6WADP; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1A4+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x1CC+i*2,streamFile); + } + } + } + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* RSD6OGG */ +VGMSTREAM * init_vgmstream_rsd6oogv(STREAMFILE *streamFile) { + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x4F4F4756) /* OOGV */ + goto fail; + + #ifdef VGM_USE_VORBIS + { + vgm_vorbis_info_t inf; + VGMSTREAM * result = NULL; + + memset(&inf, 0, sizeof(inf)); + inf.layout_type = layout_ogg_vorbis; + inf.meta_type = meta_RSD6OOGV; + + start_offset = 0x800; + result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + + if (result != NULL) { + return result; + } + } +#endif + +fail: + /* clean up anything we may have opened */ + return NULL; +} + +/* RSD6XADP */ +VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x58414450) /* XADP */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_RSD6XADP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + if (vgmstream->coding_type == coding_XBOX) { + vgmstream->layout_type=layout_none; + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +#if 0 +/* RSD6XMA */ +VGMSTREAM * init_vgmstream_rsd6xma(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52534436) /* RSD6 */ + goto fail; + if (read_32bitBE(0x4,streamFile) != 0x584D4120) /* XMA */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x8,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_XMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*64/36/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = loop_flag; + vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_RSD6XMA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + if (vgmstream->coding_type == coding_XMA) { + vgmstream->layout_type=layout_none; + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + + } + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rsf.c b/Frameworks/vgmstream/vgmstream/src/meta/rsf.c new file mode 100644 index 000000000..864fb07a9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rsf.c @@ -0,0 +1,73 @@ +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +/* .rsf - from Metroid Prime */ + +VGMSTREAM * init_vgmstream_rsf(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + size_t file_size; + + /* check extension, case insensitive */ + /* this is all we have to go on, rsf is completely headerless */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rsf",filename_extension(filename))) goto fail; + + file_size = get_streamfile_size(streamFile); + + { + /* extra check: G.721 has no zero nibbles, so we look at + * the first few bytes*/ + int8_t test_byte; + off_t i; + /* 0x20 is arbitrary, all files are much larger */ + for (i=0;i<0x20;i++) { + test_byte = read_8bit(i,streamFile); + if (!(test_byte&0xf) || !(test_byte&0xf0)) goto fail; + } + /* and also check start of second channel */ + for (i=(file_size+1)/2;i<(file_size+1)/2+0x20;i++) { + test_byte = read_8bit(i,streamFile); + if (!(test_byte&0xf) || !(test_byte&0xf0)) goto fail; + } + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = file_size; + vgmstream->sample_rate = 32000; + + vgmstream->coding_type = coding_G721; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_RSF; + + /* open the file for reading by each channel */ + { + int i; + for (i=0;i<2;i++) { + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (file_size+1)/2*i; + + + g72x_init_state(&(vgmstream->ch[i].g72x_state)); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c new file mode 100644 index 000000000..43bef3c14 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rwsd.c @@ -0,0 +1,384 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* Wii RWAV, 3DS CWAV */ + +struct rwav_data { + // in + off_t offset; + STREAMFILE *streamFile; + int big_endian; + int32_t (*read_32bit)(off_t,STREAMFILE*); + + // out + int version; + off_t start_offset; + off_t info_chunk; + off_t wave_offset; +}; + +static void read_rwav(struct rwav_data * rd) +{ + off_t chunk_table_offset; + off_t chunk_table_step; + off_t info_chunk; + off_t data_chunk; + + if (rd->big_endian) + { + /* "RWAV" */ + if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574156) + return; + + /* big endian, version 2 */ + if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0102) + return; + + chunk_table_offset = rd->offset+0x10; + chunk_table_step = 8; + } + else + { + /* "CWAV" */ + if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x43574156) + return; + + /* little endian, version 2 */ + if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFFFE4000 || + (uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00000102) + return; + + chunk_table_offset = rd->offset+0x18; + chunk_table_step = 0xc; + } + + info_chunk = rd->offset+rd->read_32bit(chunk_table_offset,rd->streamFile); + /* "INFO" */ + if ((uint32_t)read_32bitBE(info_chunk,rd->streamFile)!=0x494e464f) + return; + + data_chunk = rd->offset+rd->read_32bit(chunk_table_offset+chunk_table_step,rd->streamFile); + /* "DATA" */ + if ((uint32_t)read_32bitBE(data_chunk,rd->streamFile)!=0x44415441) + return; + + rd->start_offset = data_chunk + 8; + rd->info_chunk = info_chunk + 8; + rd->version = 2; + rd->wave_offset = info_chunk - 8; // pretend to have a WAVE + + return; +} + +static void read_rwar(struct rwav_data * rd) +{ + if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574152) /* "RWAR" */ + return; + if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0100) /* version 0 */ + return; + + rd->offset += 0x60; + read_rwav(rd); + rd->version = 0; + return; +} + +/* RWSD is quite similar to BRSTM, but can contain several streams. + * Still, some games use it for single streams. We only support the + * single stream form here */ +VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type; + + size_t wave_length; + int codec_number; + int channel_count; + int loop_flag; + int rwar = 0; + int rwav = 0; + struct rwav_data rwav_data; + + size_t stream_size; + + int big_endian = 1; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + const char *ext; + + rwav_data.version = -1; + rwav_data.start_offset = 0; + rwav_data.info_chunk = -1; + rwav_data.wave_offset = -1; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + + ext = filename_extension(filename); + + if (strcasecmp("rwsd",ext)) + { + if (strcasecmp("rwar",ext)) + { + if (strcasecmp("rwav",ext)) + { + if (strcasecmp("bcwav",ext) && strcasecmp("bms",ext)) + { + goto fail; + } + else + { + // cwav, similar to little endian rwav + rwav = 1; + big_endian = 0; + } + } + else + { + // matched rwav + rwav = 1; + } + } + else + { + // matched rwar + rwar = 1; + } + } + else + { + // match rwsd + } + + if (big_endian) + { + read_16bit = read_16bitBE; + read_32bit = read_32bitBE; + } + else + { + read_16bit = read_16bitLE; + read_32bit = read_32bitLE; + } + + /* check header */ + if (rwar || rwav) + { + rwav_data.offset = 0; + rwav_data.streamFile = streamFile; + rwav_data.big_endian = big_endian; + rwav_data.read_32bit = read_32bit; + + if (rwar) read_rwar(&rwav_data); + if (rwav) read_rwav(&rwav_data); + if (rwav_data.wave_offset < 0) goto fail; + } + else + { + if ((uint32_t)read_32bitBE(0,streamFile)!=0x52575344) /* "RWSD" */ + goto fail; + + switch (read_32bitBE(4,streamFile)) + { + case 0xFEFF0102: + /* ideally we would look through the chunk list for a WAVE chunk, + * but it's always in the same order */ + /* get WAVE offset, check */ + rwav_data.wave_offset = read_32bit(0x18,streamFile); + if ((uint32_t)read_32bitBE(rwav_data.wave_offset,streamFile)!=0x57415645) /* "WAVE" */ + goto fail; + /* get WAVE size, check */ + wave_length = read_32bit(0x1c,streamFile); + if (read_32bit(rwav_data.wave_offset+4,streamFile)!=wave_length) + goto fail; + + /* check wave count */ + if (read_32bit(rwav_data.wave_offset+8,streamFile) != 1) + goto fail; /* only support 1 */ + + rwav_data.version = 2; + + break; + case 0xFEFF0103: + rwav_data.offset = 0xe0; + rwav_data.streamFile = streamFile; + rwav_data.big_endian = big_endian; + rwav_data.read_32bit = read_32bit; + + read_rwar(&rwav_data); + if (rwav_data.wave_offset < 0) goto fail; + + rwar = 1; + break; + default: + goto fail; + } + + } + + /* get type details */ + codec_number = read_8bit(rwav_data.wave_offset+0x10,streamFile); + loop_flag = read_8bit(rwav_data.wave_offset+0x11,streamFile); + if (big_endian) + channel_count = read_8bit(rwav_data.wave_offset+0x12,streamFile); + else + channel_count = read_32bit(rwav_data.wave_offset+0x24,streamFile); + + switch (codec_number) { + case 0: + coding_type = coding_PCM8; + break; + case 1: + if (big_endian) + coding_type = coding_PCM16BE; + else + coding_type = coding_PCM16LE; + break; + case 2: + coding_type = coding_NGC_DSP; + break; + case 3: + coding_type = coding_IMA; + break; + default: + goto fail; + } + + if (channel_count < 1) goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (big_endian) + { + vgmstream->num_samples = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x1c,streamFile)); + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x18,streamFile)); + } + else + { + vgmstream->num_samples = read_32bit(rwav_data.wave_offset+0x1c,streamFile); + vgmstream->loop_start_sample = read_32bit(rwav_data.wave_offset+0x18,streamFile); + } + + vgmstream->sample_rate = (uint16_t)read_16bit(rwav_data.wave_offset+0x14,streamFile); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_type; + vgmstream->layout_type = layout_none; + + if (rwar) + vgmstream->meta_type = meta_RWAR; + else if (rwav) + { + if (big_endian) + vgmstream->meta_type = meta_RWAV; + else + vgmstream->meta_type = meta_CWAV; + } + else + vgmstream->meta_type = meta_RWSD; + + { + off_t data_start_offset; + off_t codec_info_offset; + int i,j; + + for (j=0;jchannels;j++) { + if (rwar || rwav) + { + if (big_endian) + { + /* This is pretty nasty, so an explaination is in order. + * At 0x10 in the info_chunk is the offset of a table with + * one entry per channel. Each entry in this table is itself + * an offset to a set of information for the channel. The + * first element in the set is the offset into DATA of the + * channel. + * The second element is the + * offset of the codec-specific setup for the channel. */ + + off_t channel_info_offset; + channel_info_offset = rwav_data.info_chunk + + read_32bit(rwav_data.info_chunk+ + read_32bit(rwav_data.info_chunk+0x10,streamFile)+j*4, + streamFile); + + data_start_offset = rwav_data.start_offset + + read_32bit(channel_info_offset+0, streamFile); + codec_info_offset = rwav_data.info_chunk + + read_32bit(channel_info_offset+4, streamFile); + } + + else + { + // CWAV uses some relative offsets + off_t cur_pos = rwav_data.info_chunk + 0x14; // channel count + cur_pos = cur_pos + read_32bit(cur_pos + 4 + j*8 + 4,streamFile); + + // size is at cur_pos + 4 + data_start_offset = rwav_data.start_offset + read_32bit(cur_pos + 4, streamFile); + // codec-specific info is at cur_pos + 0xC + codec_info_offset = cur_pos + read_32bit(cur_pos + 0xC,streamFile); + } + vgmstream->ch[j].channel_start_offset= + vgmstream->ch[j].offset=data_start_offset; + } else { + // dummy for RWSD, must be a proper way to work this out + codec_info_offset=rwav_data.wave_offset+0x6c+j*0x30; + } + + if (vgmstream->coding_type == coding_NGC_DSP) { + for (i=0;i<16;i++) { + vgmstream->ch[j].adpcm_coef[i]=read_16bit(codec_info_offset+i*2,streamFile); + } + } + + if (vgmstream->coding_type == coding_IMA) { + vgmstream->ch[j].adpcm_history1_16 = read_16bit(codec_info_offset,streamFile); + vgmstream->ch[j].adpcm_step_index = read_16bit(codec_info_offset+2,streamFile); + } + } + } + + if (rwar || rwav) + { + /* */ + } + else + { + if (rwav_data.version == 2) + rwav_data.start_offset = read_32bit(8,streamFile); + } + stream_size = read_32bit(rwav_data.wave_offset+0x50,streamFile); + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename, + 0x1000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + if (!(rwar || rwav)) + { + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + rwav_data.start_offset + i*stream_size; + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/rwx.c b/Frameworks/vgmstream/vgmstream/src/meta/rwx.c new file mode 100644 index 000000000..ad61bcfba --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/rwx.c @@ -0,0 +1,66 @@ +#include "meta.h" +#include "../util.h" +/* RWX (found in Air Force Delta Storm (XBOX)) */ +VGMSTREAM * init_vgmstream_rwx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("rwx",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x52415758) + goto fail; + + + loop_flag = read_32bitLE(0x0C,streamFile); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x04,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x10,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); + vgmstream->loop_end_sample = read_32bitLE(0x10,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_RWX; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c b/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c new file mode 100644 index 000000000..e85db9814 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/s14_sss.c @@ -0,0 +1,105 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_G7221 + +#include "meta.h" +#include "../util.h" +#include "../coding/coding.h" + +/* .s14 and .sss - from Idolm@ster DS (and others?) + * Raw 24kbit Siren 14 stream, s14 is mono and sss is + * frame-interleaved stereo + */ + +VGMSTREAM * init_vgmstream_s14_sss(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int channel_count; + + size_t file_size; + + /* check extension, case insensitive */ + /* this is all we have to go on, rsf is completely headerless */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (!strcasecmp("sss",filename_extension(filename))) + { + channel_count = 2; + } + else if (!strcasecmp("s14",filename_extension(filename))) + { + channel_count = 1; + } + else + { + goto fail; + } + + file_size = get_streamfile_size(streamFile); + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = file_size/0x3c/channel_count*(32000/50); + vgmstream->sample_rate = 32768; + + vgmstream->coding_type = coding_G7221C; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x3c; + if (1 == channel_count) + { + vgmstream->meta_type = meta_S14; + } + else + { + vgmstream->meta_type = meta_SSS; + } + + { + int i; + g7221_codec_data *data; + + /* one data structure per channel */ + data = malloc(sizeof(g7221_codec_data) * channel_count); + if (!data) + { + goto fail; + } + memset(data,0,sizeof(g7221_codec_data) * channel_count); + vgmstream->codec_data = data; + + for (i = 0; i < channel_count; i++) + { + /* Siren 14 == 14khz bandwidth */ + data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000); + if (!data[i].handle) + { + goto fail; /* close_vgmstream is able to clean up */ + } + } + } + + /* open the file for reading by each channel */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=0x3c*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sat_baka.c b/Frameworks/vgmstream/vgmstream/src/meta/sat_baka.c new file mode 100644 index 000000000..8deb46139 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sat_baka.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../util.h" + +/* manakoAT 28.01.2009 : + BAKA - found in "Crypt Killer (Saturn)... + looks like some developers were really bored, every file starts with + the word "BAKA" which is the japanese word for "IDIOT" :o) + Files containing "begloop" markers at EOF... + some files should loop, but i don't know how to get the loopstart here!*/ +VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("baka",filename_extension(filename))) goto fail; + + /* check header */ + if ((read_32bitBE(0x00,streamFile) != 0x42414B41 && /* "BAKA" */ + read_32bitBE(0x08,streamFile) != 0x2041484F && /* " AHO" */ + read_32bitBE(0x0C,streamFile) != 0x50415041 && /* "PAPA" */ + read_32bitBE(0x26,streamFile) != 0x4D414D41)) /* "MAMA" */ + goto fail; + + + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x2E; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0x16,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x16,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_SAT_BAKA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c new file mode 100644 index 000000000..83e019c9a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sat_dvi.c @@ -0,0 +1,68 @@ +#include "meta.h" +#include "../util.h" + +/* DVI (Castlevania Symphony of the Night) */ +VGMSTREAM * init_vgmstream_dvi(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("dvi",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4456492E) /* "DVI." */ + goto fail; + + loop_flag = (read_32bitBE(0x0C,streamFile)!=0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + start_offset = read_32bitBE(0x04,streamFile); + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_INT_DVI_IMA; + + vgmstream->num_samples = read_32bitBE(0x08,streamFile); + + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile); + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 4; + vgmstream->meta_type = meta_DVI; + vgmstream->get_high_nibble=1; + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+(i*vgmstream->interleave_block_size); + vgmstream->ch[i].adpcm_history1_32=0; + vgmstream->ch[i].adpcm_step_index=0; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sat_sap.c b/Frameworks/vgmstream/vgmstream/src/meta/sat_sap.c new file mode 100644 index 000000000..9e03cc638 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sat_sap.c @@ -0,0 +1,67 @@ +#include "meta.h" +#include "../util.h" + +/* SAP (from Bubble_Symphony) */ +VGMSTREAM * init_vgmstream_sat_sap(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sap",filename_extension(filename))) goto fail; + + + /* check header */ + if (read_32bitBE(0x0A,streamFile) != 0x0010400E) /* "0010400E" */ + goto fail; + + + loop_flag = 0; /* (read_32bitLE(0x08,streamFile)!=0); */ + channel_count = read_32bitBE(0x04,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = (uint16_t)read_16bitBE(0x0E,streamFile); + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0x00,streamFile); + if (loop_flag) { + vgmstream->loop_start_sample = 0; /* (read_32bitLE(0x08,streamFile)-1)*28; */ + vgmstream->loop_end_sample = read_32bitBE(0x00,streamFile); + } + + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_SAT_SAP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sd9.c b/Frameworks/vgmstream/vgmstream/src/meta/sd9.c new file mode 100644 index 000000000..ad097aafa --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sd9.c @@ -0,0 +1,81 @@ +#include "meta.h" +#include "../util.h" + +/* SD9 (found in beatmaniaIIDX16 - EMPRESS (Arcade) */ +VGMSTREAM * init_vgmstream_sd9(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sd9",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x53443900) /* SD9 */ + goto fail; + if (read_32bitBE(0x20,streamFile) != 0x52494646) /* RIFF */ + goto fail; + if (read_32bitBE(0x28,streamFile) != 0x57415645) /* WAVE */ + goto fail; + if (read_32bitBE(0x2c,streamFile) != 0x666D7420) /* fmt */ + goto fail; + if (read_32bitBE(0x72,streamFile) != 0x64617461) /* data */ + goto fail; + + loop_flag = (read_16bitLE(0x0e,streamFile)==0x1); + channel_count = read_16bitLE(0x36,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x7a; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x38,streamFile); + vgmstream->coding_type = coding_MSADPCM; + vgmstream->num_samples = read_32bitLE(0x6e,streamFile); + if (loop_flag) { + if (read_16bitLE(0x1C,streamFile)==1) + { + vgmstream->loop_start_sample = read_32bitLE(0x14,streamFile)/2/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x18,streamFile)/2/channel_count; + } + else + { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = read_16bitLE(0x40,streamFile); + vgmstream->meta_type = meta_SD9; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sdt.c b/Frameworks/vgmstream/vgmstream/src/meta/sdt.c new file mode 100644 index 000000000..6b3f4011f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sdt.c @@ -0,0 +1,80 @@ +#include "meta.h" +#include "../util.h" + +/* SDT (Baldur's Gate - Dark Alliance) */ +VGMSTREAM * init_vgmstream_sdt(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sdt",filename_extension(filename))) goto fail; + +#if 0 + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53565300) /* "SVS\0" */ + goto fail; +#endif + + loop_flag = (read_32bitBE(0x04,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0xA0; + vgmstream->channels = channel_count; /*read_32bitBE(0x00,streamFile);*/ + vgmstream->sample_rate = read_32bitBE(0x08,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x14,streamFile)/8*14/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; /* (read_32bitLE(0x08,streamFile)-1)*28; */ + vgmstream->loop_end_sample = read_32bitBE(0x14,streamFile)/8*14/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x8000; + vgmstream->meta_type = meta_SDT; + + +if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x3C+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x6A+i*2,streamFile); + } + } +} + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/seg.c b/Frameworks/vgmstream/vgmstream/src/meta/seg.c new file mode 100644 index 000000000..1a15ceda4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/seg.c @@ -0,0 +1,93 @@ +#include "meta.h" +#include "../util.h" + +/* SEG (found in Eragon) */ +VGMSTREAM * init_vgmstream_seg(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + coding_t coding; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("seg",filename_extension(filename))) goto fail; + + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x73656700) /* "seg\0" */ + goto fail; + if (read_32bitBE(0x04,streamFile) == 0x70733200) /* "ps2\0" */ + { + coding = coding_PSX; + } + else if (read_32bitBE(0x04,streamFile) == 0x78627800) /* "xbx\0" */ + { + coding = coding_XBOX; + } + else goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x24,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x4000; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + vgmstream->coding_type = coding; + + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + } + + vgmstream->interleave_block_size = 0; + + if (coding_PSX == coding) + { + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)*28/16/channel_count; + vgmstream->meta_type = meta_PS2_SEG; + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2000; + } + } + else if (coding_XBOX == coding) + { + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)/36/channel_count*64; + vgmstream->meta_type = meta_XBOX_SEG; + vgmstream->layout_type = layout_none; + } + else goto fail; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sfl.c b/Frameworks/vgmstream/vgmstream/src/meta/sfl.c new file mode 100644 index 000000000..388c9c858 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sfl.c @@ -0,0 +1,182 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_VORBIS + +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* .sfl, odd RIFF-formatted files that go along with oggs */ + +/* return milliseconds */ +static int parse_region(unsigned char * region, long *start, long *end) { + long start_hh,start_mm,start_ss,start_ms; + long end_hh,end_mm,end_ss,end_ms; + + if (memcmp("Region ",region,7)) return -1; + + if (8 != sscanf((char*)region+7,"%ld:%ld:%ld.%ld to %ld:%ld:%ld.%ld", + &start_hh,&start_mm,&start_ss,&start_ms, + &end_hh,&end_mm,&end_ss,&end_ms)) + return -1; + + *start = ((start_hh*60+start_mm)*60+start_ss)*1000+start_ms; + *end = ((end_hh*60+end_mm)*60+end_ss)*1000+end_ms; + + return 0; +} + +/* loop points have been found hiding here */ +static void parse_adtl(off_t adtl_offset, off_t adtl_length, STREAMFILE *streamFile, + long *loop_start, long *loop_end, int *loop_flag) { + int loop_found = 0; + + off_t current_chunk = adtl_offset+4; + + while (current_chunk < adtl_offset+adtl_length) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitLE(current_chunk+4,streamFile); + + if (current_chunk+8+chunk_size > adtl_offset+adtl_length) return; + + switch(chunk_type) { + case 0x6c61626c: /* labl */ + { + unsigned char *labelcontent; + labelcontent = malloc(chunk_size-4); + if (!labelcontent) return; + if (read_streamfile(labelcontent,current_chunk+0xc, + chunk_size-4,streamFile)!=chunk_size-4) { + free(labelcontent); + return; + } + + if (!loop_found && + parse_region(labelcontent,loop_start,loop_end)>=0) + { + loop_found = 1; + } + + free(labelcontent); + } + break; + default: + break; + } + + current_chunk += 8 + chunk_size; + } + + if (loop_found) *loop_flag = 1; +} + +VGMSTREAM * init_vgmstream_sfl(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileOGG = NULL; + char filenameOGG[260]; + char filename[PATH_LIMIT]; + + off_t file_size = -1; + + int loop_flag = 0; + long loop_start_ms = -1; + long loop_end_ms = -1; + uint32_t riff_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sfl",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint32_t)read_32bitBE(0,streamFile)!=0x52494646) /* "RIFF" */ + goto fail; + /* check for SFPL form */ + if ((uint32_t)read_32bitBE(8,streamFile)!=0x5346504C) /* "SFPL" */ + goto fail; + + /* check for .OGG file */ + strcpy(filenameOGG,filename); + strcpy(filenameOGG+strlen(filenameOGG)-3,"ogg"); + + streamFileOGG = streamFile->open(streamFile,filenameOGG,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileOGG) { + goto fail; + } + + /* let the real initer do the parsing */ + vgmstream = init_vgmstream_ogg_vorbis(streamFileOGG); + if (!vgmstream) goto fail; + + close_streamfile(streamFileOGG); + streamFileOGG = NULL; + + /* now that we have an ogg, proceed with parsing the .sfl */ + riff_size = read_32bitLE(4,streamFile); + file_size = get_streamfile_size(streamFile); + + /* check for tructated RIFF */ + if (file_size < riff_size+8) goto fail; + + /* read through chunks to verify format and find metadata */ + { + off_t current_chunk = 0xc; /* start with first chunk */ + + while (current_chunk < file_size) { + uint32_t chunk_type = read_32bitBE(current_chunk,streamFile); + off_t chunk_size = read_32bitLE(current_chunk+4,streamFile); + + /* There seem to be a few bytes left over, included in the + * RIFF but not enough to make a new chunk. + */ + if (current_chunk+8 > file_size) break; + + if (current_chunk+8+chunk_size > file_size) goto fail; + + switch(chunk_type) { + case 0x4C495354: /* LIST */ + /* what lurks within?? */ + switch (read_32bitBE(current_chunk + 8, streamFile)) { + case 0x6164746C: /* adtl */ + /* yay, atdl is its own little world */ + parse_adtl(current_chunk + 8, chunk_size, + streamFile, + &loop_start_ms,&loop_end_ms,&loop_flag); + break; + default: + break; + } + break; + default: + /* ignorance is bliss */ + break; + } + + current_chunk += 8+chunk_size; + } + } + + if (loop_flag) { + /* install loops */ + if (!vgmstream->loop_flag) { + vgmstream->loop_flag = 1; + vgmstream->loop_ch = calloc(vgmstream->channels, + sizeof(VGMSTREAMCHANNEL)); + if (!vgmstream->loop_ch) goto fail; + } + + vgmstream->loop_start_sample = (long long)loop_start_ms*vgmstream->sample_rate/1000; + vgmstream->loop_end_sample = (long long)loop_end_ms*vgmstream->sample_rate/1000; + } + + vgmstream->meta_type = meta_OGG_SFL; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileOGG) close_streamfile(streamFileOGG); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sli.c b/Frameworks/vgmstream/vgmstream/src/meta/sli.c new file mode 100644 index 000000000..621cfb84f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sli.c @@ -0,0 +1,121 @@ +#include "../vgmstream.h" + +#ifdef VGM_USE_VORBIS + +#include +#include "meta.h" +#include "../util.h" + +#ifdef WIN32 +#define DIRSEP '\\' +#else +#define DIRSEP '/' +#endif + +/* .sli is a file with loop points, associated with a similarly named .ogg */ + +VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileOGG = NULL; + char filename[PATH_LIMIT]; + char filenameOGG[260]; + char linebuffer[260]; + off_t bytes_read; + off_t sli_offset; + int done; + int32_t loop_start = -1; + int32_t loop_length = -1; + int32_t loop_from = -1; + int32_t loop_to = -1; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sli",filename_extension(filename))) goto fail; + + /* check for .OGG file */ + strcpy(filenameOGG,filename); + /* strip off .sli */ + filenameOGG[strlen(filenameOGG)-4]='\0'; + + streamFileOGG = streamFile->open(streamFile,filenameOGG,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileOGG) { + goto fail; + } + + /* let the real initer do the parsing */ + vgmstream = init_vgmstream_ogg_vorbis(streamFileOGG); + if (!vgmstream) goto fail; + + close_streamfile(streamFileOGG); + streamFileOGG = NULL; + + sli_offset = 0; + while ((loop_start == -1 || loop_length == -1) && sli_offset < get_streamfile_size(streamFile)) { + char *endptr; + char *foundptr; + bytes_read=get_streamfile_dos_line(sizeof(linebuffer),linebuffer,sli_offset,streamFile,&done); + if (!done) goto fail; + + if (!memcmp("LoopStart=",linebuffer,10) && linebuffer[10]!='\0') { + loop_start = strtol(linebuffer+10,&endptr,10); + if (*endptr != '\0') { + /* if it didn't parse cleanly */ + loop_start = -1; + } + } + else if (!memcmp("LoopLength=",linebuffer,11) && linebuffer[11]!='\0') { + loop_length = strtol(linebuffer+11,&endptr,10); + if (*endptr != '\0') { + /* if it didn't parse cleanly */ + loop_length = -1; + } + } + + /* a completely different format, also with .sli extension and can be handled similarly */ + if ((foundptr=strstr(linebuffer,"To="))!=NULL && isdigit(foundptr[3])) { + loop_to = strtol(foundptr+3,&endptr,10); + if (*endptr != ';') { + loop_to = -1; + } + } + if ((foundptr=strstr(linebuffer,"From="))!=NULL && isdigit(foundptr[5])) { + loop_from = strtol(foundptr+5,&endptr,10); + if (*endptr != ';') { + loop_from = -1; + } + } + + sli_offset += bytes_read; + } + + if ((loop_start != -1 && loop_length != -1) || + (loop_to != -1 && loop_from != -1)) { + /* install loops */ + if (!vgmstream->loop_flag) { + vgmstream->loop_flag = 1; + vgmstream->loop_ch = calloc(vgmstream->channels, + sizeof(VGMSTREAMCHANNEL)); + if (!vgmstream->loop_ch) goto fail; + } + + if (loop_to != -1 && loop_from != -1) { + vgmstream->loop_start_sample = loop_to; + vgmstream->loop_end_sample = loop_from; + vgmstream->meta_type = meta_OGG_SLI2; + } else { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_start+loop_length; + vgmstream->meta_type = meta_OGG_SLI; + } + } else goto fail; /* if there's no loop points the .sli wasn't valid */ + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileOGG) close_streamfile(streamFileOGG); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c b/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c new file mode 100644 index 000000000..53d73c8f9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/spt_spd.c @@ -0,0 +1,108 @@ +#include "meta.h" +#include "../util.h" + +/* SPT+SPT + + 2008-11-27 - manakoAT : First try for splitted files... +*/ + +VGMSTREAM * init_vgmstream_spt_spd(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamFileSPT = NULL; + char filename[PATH_LIMIT]; + char filenameSPT[260]; + int channel_count; + int loop_flag; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("spd",filename_extension(filename))) goto fail; + + strcpy(filenameSPT,filename); + strcpy(filenameSPT+strlen(filenameSPT)-3,"spt"); + + streamFileSPT = streamFile->open(streamFile,filenameSPT,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!streamFileSPT) + goto fail; + + if (read_32bitBE(0x0,streamFileSPT) != 0x1) // make sure that it's not a container + goto fail; + + channel_count = 1; + loop_flag = (read_32bitBE(0x0C,streamFileSPT) == 0x2); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x08,streamFileSPT); + + switch ((read_32bitBE(0x4,streamFileSPT))) { + case 0: + case 1: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples=read_32bitBE(0x14,streamFileSPT)*14/16/channel_count; + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x14,streamFileSPT)*14/16/channel_count; + } + break; + case 2: + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples=read_32bitBE(0x14,streamFileSPT)/channel_count; + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitBE(0x14,streamFileSPT)/channel_count; + } + break; + default: + goto fail; + } + + if (channel_count == 1) { + vgmstream->layout_type = layout_none; + } else if (channel_count == 2) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size=(read_32bitBE(0x34,streamFileSPT)*channel_count)/2; + } + + vgmstream->meta_type = meta_SPT_SPD; + + /* open the file for reading */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x8000); + vgmstream->ch[i].offset = 0; + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFileSPT); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFileSPT); + } + } + } + + + close_streamfile(streamFileSPT); streamFileSPT=NULL; + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (streamFileSPT) close_streamfile(streamFileSPT); + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c new file mode 100644 index 000000000..11d1423a7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/sqex_scd.c @@ -0,0 +1,430 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* Square-Enix SCD (FF XIII, XIV) */ + +/* special streamfile type to handle deinterleaving of complete files, + (based heavily on AIXSTREAMFILE */ +typedef struct _SCDINTSTREAMFILE +{ + STREAMFILE sf; + STREAMFILE *real_file; + const char * filename; + off_t start_physical_offset; + off_t current_logical_offset; + off_t interleave_block_size; + off_t stride_size; + size_t total_size; +} SCDINTSTREAMFILE; + +static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size); + +VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset, meta_offset_offset, meta_offset, post_meta_offset, size_offset; + int32_t loop_start, loop_end; + + int loop_flag = 0; + int channel_count; + int codec_id; + int aux_chunk_count; + + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("scd",filename_extension(filename))) goto fail; + + /* SEDB */ + if (read_32bitBE(0,streamFile) != 0x53454442) goto fail; + /* SSCF */ + if (read_32bitBE(4,streamFile) != 0x53534346) goto fail; + if (read_32bitBE(8,streamFile) == 2 || + read_32bitBE(8,streamFile) == 3) { + /* version 2 BE, as seen in FFXIII demo for PS3 */ + /* version 3 BE, as seen in FFXIII for PS3 */ + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + size_offset = 0x14; + meta_offset_offset = 0x40 + read_16bit(0xe,streamFile); + } else if (read_32bitLE(8,streamFile) == 3 || + read_32bitLE(8,streamFile) == 2) { + /* version 2/3 LE, as seen in FFXIV for ?? */ + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + size_offset = 0x10; + meta_offset_offset = 0x40 + read_16bit(0xe,streamFile); + } else goto fail; + + /* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ +#if 0 + /* check file size with header value */ + if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile)) + goto fail; +#endif + + meta_offset = read_32bit(meta_offset_offset,streamFile); + + /* check that chunk size equals stream size (?) */ + loop_start = read_32bit(meta_offset+0x10,streamFile); + loop_end = read_32bit(meta_offset+0x14,streamFile); + loop_flag = (loop_end > 0); + + channel_count = read_32bit(meta_offset+4,streamFile); + codec_id = read_32bit(meta_offset+0xc,streamFile); + + post_meta_offset = meta_offset + 0x20; + + /* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks + before anything else */ + + aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); + for (; aux_chunk_count > 0; aux_chunk_count --) + { + /* skip aux chunks */ + /*printf("skipping %08x\n", read_32bitBE(post_meta_offset, streamFile));*/ + post_meta_offset += read_32bit(post_meta_offset+4,streamFile); + } + + start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile); + +#ifdef VGM_USE_VORBIS + if (codec_id == 0x6) + { + vgm_vorbis_info_t inf; + uint32_t seek_table_size = read_32bit(post_meta_offset+0x10, streamFile); + uint32_t vorb_header_size = read_32bit(post_meta_offset+0x14, streamFile); + VGMSTREAM * result = NULL; + + memset(&inf, 0, sizeof(inf)); + inf.loop_start = loop_start; + inf.loop_end = loop_end; + inf.loop_flag = loop_flag; + inf.loop_end_found = loop_flag; + inf.loop_length_found = 0; + inf.layout_type = layout_ogg_vorbis; + inf.meta_type = meta_SQEX_SCD; + + result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + + if (result != NULL) { + return result; + } + + // try skipping seek table + { + if ((post_meta_offset-meta_offset) + seek_table_size + vorb_header_size != read_32bit(meta_offset+0x18, streamFile)) { + return NULL; + } + + start_offset = post_meta_offset + 0x20 + seek_table_size; + result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + if (result != NULL) { + return result; + } + } + + // failed with Ogg, try deobfuscating header + { + // skip chunks before xor_byte + unsigned char xor_byte; + + xor_byte = read_8bit(post_meta_offset+2, streamFile); + + if (xor_byte == 0) { + return NULL; + } + + inf.scd_xor = xor_byte; + inf.scd_xor_len = vorb_header_size; + + result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); + return result; + } + } +#endif + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bit(meta_offset+8,streamFile); + + switch (codec_id) { + case 0x1: + /* PCM */ + vgmstream->coding_type = coding_PCM16LE_int; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = read_32bit(meta_offset+0,streamFile) / 2 / channel_count; + + if (loop_flag) { + vgmstream->loop_start_sample = loop_start / 2 / channel_count; + vgmstream->loop_end_sample = loop_end / 2 / channel_count; + } + break; +#ifdef VGM_USE_MPEG + case 0x7: + /* MPEG */ + { + mpeg_codec_data *mpeg_data = NULL; + struct mpg123_frameinfo mi; + coding_t ct; + + if (vgmstream->sample_rate == 47999) + vgmstream->sample_rate = 48000; + + mpeg_data = init_mpeg_codec_data(streamFile, start_offset, vgmstream->sample_rate, vgmstream->channels, &ct, NULL, NULL); + if (!mpeg_data) goto fail; + vgmstream->codec_data = mpeg_data; + + if (MPG123_OK != mpg123_info(mpeg_data->m, &mi)) goto fail; + + vgmstream->coding_type = ct; + vgmstream->layout_type = layout_mpeg; + if (mi.vbr != MPG123_CBR) goto fail; + vgmstream->num_samples = mpeg_bytes_to_samples(read_32bit(meta_offset+0,streamFile), &mi); + vgmstream->num_samples -= vgmstream->num_samples%576; + if (loop_flag) { + vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi); + vgmstream->loop_start_sample -= vgmstream->loop_start_sample%576; + vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, &mi); + vgmstream->loop_end_sample -= vgmstream->loop_end_sample%576; + } + vgmstream->interleave_block_size = 0; + } + break; +#endif + case 0xC: + /* MS ADPCM */ + vgmstream->coding_type = coding_MSADPCM; + vgmstream->layout_type = layout_none; + vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile); + vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bit(meta_offset+0,streamFile), vgmstream->interleave_block_size, vgmstream->channels); + + if (loop_flag) { + vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels); + vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels); + } + break; + case 0xA: + /* GC/Wii DSP ADPCM */ + { + STREAMFILE * file; + int i; + const off_t interleave_size = 0x800; + const off_t stride_size = interleave_size * channel_count; + + size_t total_size; + + scd_int_codec_data * data = NULL; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_scd_int; + + /* a normal DSP header... */ + vgmstream->num_samples = read_32bitBE(start_offset+0,streamFile); + total_size = (read_32bitBE(start_offset+4,streamFile)+1)/2; + + if (loop_flag) { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end+1; + } + + /* verify other channel headers */ + for (i = 1; i < channel_count; i++) { + if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples || + (read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) { + goto fail; + } + + } + + /* the primary streamfile we'll be using */ + file = streamFile->open(streamFile,filename,stride_size); + if (!file) + goto fail; + + vgmstream->ch[0].streamfile = file; + + data = malloc(sizeof(scd_int_codec_data)); + data->substream_count = channel_count; + data->substreams = calloc(channel_count, sizeof(VGMSTREAM *)); + data->intfiles = calloc(channel_count, sizeof(STREAMFILE *)); + + vgmstream->codec_data = data; + + for (i=0;isubstreams[i] = init_vgmstream_ngc_dsp_std(intfile); + data->intfiles[i] = intfile; + if (!data->substreams[i]) + goto fail; + + /* TODO: only handles mono substreams, though that's all we have with DSP */ + /* save start things so we can restart for seeking/looping */ + /* copy the channels */ + memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1); + /* copy the whole VGMSTREAM */ + memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM)); + + } + + } + break; + default: + goto fail; + } + + vgmstream->meta_type = meta_SQEX_SCD; + + /* open the file for reading */ + if (vgmstream->layout_type != layout_scd_int) + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +static STREAMFILE *open_scdint_impl(SCDINTSTREAMFILE *streamfile,const char * const filename,size_t buffersize) +{ + SCDINTSTREAMFILE *newfile; + + if (strcmp(filename, streamfile->filename)) + return NULL; + + newfile = malloc(sizeof(SCDINTSTREAMFILE)); + if (!newfile) + return NULL; + + memcpy(newfile,streamfile,sizeof(SCDINTSTREAMFILE)); + return &newfile->sf; +} + +static void close_scdint(SCDINTSTREAMFILE *streamfile) +{ + free(streamfile); + return; +} + +static size_t get_size_scdint(SCDINTSTREAMFILE *streamfile) +{ + return streamfile->total_size; +} + +static size_t get_offset_scdint(SCDINTSTREAMFILE *streamfile) +{ + return streamfile->current_logical_offset; +} + +static void get_name_scdint(SCDINTSTREAMFILE *streamfile, char *buffer, size_t length) +{ + strncpy(buffer,streamfile->filename,length); + buffer[length-1]='\0'; +} + +static size_t read_scdint(SCDINTSTREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length) +{ + size_t sz = 0; + + while (length > 0) + { + off_t to_read; + off_t length_available; + off_t block_num; + off_t intrablock_offset; + off_t physical_offset; + + + block_num = offset / streamfile->interleave_block_size; + intrablock_offset = offset % streamfile->interleave_block_size; + streamfile->current_logical_offset = offset; + physical_offset = streamfile->start_physical_offset + block_num * streamfile->stride_size + intrablock_offset; + + length_available = + streamfile->interleave_block_size - intrablock_offset; + + if (length < length_available) + { + to_read = length; + } + else + { + to_read = length_available; + } + + if (to_read > 0) + { + size_t bytes_read; + + bytes_read = read_streamfile(dest, + physical_offset, + to_read, streamfile->real_file); + + sz += bytes_read; + + streamfile->current_logical_offset = offset + bytes_read; + + if (bytes_read != to_read) + { + /* an error which we will not attempt to handle here */ + return sz; + } + + dest += bytes_read; + offset += bytes_read; + length -= bytes_read; + } + } + + return sz; +} + +/* start_offset is for *this* interleaved stream */ +static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size) +{ + SCDINTSTREAMFILE * scd = malloc(sizeof(SCDINTSTREAMFILE)); + + if (!scd) + return NULL; + + scd->sf.read = (void*)read_scdint; + scd->sf.get_size = (void*)get_size_scdint; + scd->sf.get_offset = (void*)get_offset_scdint; + scd->sf.get_name = (void*)get_name_scdint; + scd->sf.get_realname = (void*)get_name_scdint; + scd->sf.open = (void*)open_scdint_impl; + scd->sf.close = (void*)close_scdint; + + scd->real_file = file; + scd->filename = filename; + scd->start_physical_offset = start_offset; + scd->current_logical_offset = 0; + scd->interleave_block_size = interleave_block_size; + scd->stride_size = stride_size; + scd->total_size = total_size; + + return &scd->sf; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c b/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c new file mode 100644 index 000000000..03b88c5b6 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ss_stream.c @@ -0,0 +1,204 @@ +#include "meta.h" +#include "../util.h" + +/* SS_STREAM + + SS_STREAM is format used by various UBI Soft Games + + 2008-11-15 - Fastelbja : First version ... + + + Some infos, sorry for messing up the meta (regards, manako) + +Splinter Cell - *.SS0; PC (except Music_*.SS0) +Splinter Cell: Pandora Tomorrow - *.SS0, *.LS0; PC +Splinter Cell: Chaos Theory - *.SS0, *.LS0; PC +Splinter Cell: Double Agent - *.SS0, *.LS0; PC + +UbiSoft Old Simple Stream (version 3) +UbiSoft Simple Stream (version 5) +UbiSoft Old Interleaved Stream (version 2) +UbiSoft Interleaved Stream (version 8 ) + +Note: if the version number is 3, then all values in this file are big-endian. If the version is 5, then all values are little-endian. + +Header: +byte {1} - Version number (3 or 5) +byte {3} - Unknown +byte {4} - Unknown +uint32 {4} - Unknown +uint16 {2} - Unknown +uint16 {2} - Number of extra uncompressed samples before the data (always 10) +int16 {2} - First left sample for decompression +byte {1} - First left index for decompression +byte {1} - Unknown +int16 {2} - First right sample for decompression +byte {1} - First right index for decompression +byte {1} - Unknown +byte {4} - Unknown + +Extra Uncompressed Samples: +if the sound is mono: +int16 {Number of extra uncompressed samples * 2} - Uncompressed samples + +if the sound is stereo: +int16 {Number of extra uncompressed samples * 4} - Uncompressed samples + +Data: +byte {?} - Compressed data + + + +And here is the format of the old interleaved streams: + +Code: +Little-endian + +uint32 {4} - Signature (2) +uint32 {4} - Number of Layers (always 3) +uint32 {4} - Total File Size +uint32 {4} - Unknown (always 20) +uint32 {4} - Unknown (always 1104) +uint32 {4} - Average Block Size (always 361) + +For Each Block: { + uint32 {4} - Block Index (begins at 1) + uint32 {4} - Unknown (always 20) + + For Each Layer (Chunk): { + uint32 {4} - Layer Chunk Size + } + + For Each Layer (Chunk): { + uint32 {Layer Chunk Size} - Chunk of an Encapsulated UbiSoft Old Simple Stream + } +} + + +And the new interleaved streams: + +Code: +Little-endian + +uint16 {2} - Signature (8) +uint16 {2} - Unknown +uint32 {4} - Unknown +uint32 {4} - Number of Layers +uint32 {4} - Number of Blocks +uint32 {4} - Number of Bytes after This to the Headers +uint32 {4} - The Sum of (Number of Layers * 4) Plus the Header Lengths +uint32 {4} - Average Sum of Chunk Data Lengths + +For Each Layer: { + uint32 {4} - Layer Header Size +} + +For Each Layer: { + uint32 {Layer Header Size} - Header of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis) +} + +For Each Block: { + uint32 {4} - Signature (3) + uint32 {4} - Number of bytes from the start of this block to the next block, 0 if no more blocks + + For Each Layer (Chunk): { + uint32 {4} - Layer Chunk Size + } + + For Each Layer (Chunk): { + uint32 {Layer Chunk Size} - Chunk of an Encapsulated Stream (PCM, UbiSoft Simple Stream, Ogg Vorbis) + } +} + + +*/ + +VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag=0; + int channels; + int channel_count; + int freq_flag; + off_t start_offset; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ss3",filename_extension(filename)) && + strcasecmp("ss7",filename_extension(filename))) goto fail; + + loop_flag = 0; + freq_flag = read_8bit(0x08,streamFile); + + if (read_8bit(0x0C,streamFile) == 0) { + channels = 1; + } else { + channels = read_8bit(0x0C,streamFile)*2; + } + + channel_count = channels; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = 48000; + + +#if 0 + if (!strcasecmp("ss3",filename_extension(filename))) { + vgmstream->sample_rate = 32000; + } else if (!strcasecmp("ss7",filename_extension(filename))) { + vgmstream->sample_rate = 48000; + } +#endif + + start_offset = (read_8bit(0x07,streamFile)+5); + +#if 0 + if (channel_count == 1){ + start_offset = 0x3C; + } else if (channel_count == 2) { + start_offset = 0x44; + } +#endif + + if(channel_count==1) + vgmstream->coding_type = coding_IMA; + else + vgmstream->coding_type = coding_EACS_IMA; + + vgmstream->num_samples = (int32_t)((get_streamfile_size(streamFile)-start_offset)* 2 / vgmstream->channels); + vgmstream->layout_type = layout_none; + + vgmstream->meta_type = meta_XBOX_WAVM; + vgmstream->get_high_nibble=0; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].offset = start_offset; + } else if (channel_count == 2) { + vgmstream->ch[i].offset = start_offset; + } + + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + vgmstream->ch[i].adpcm_history1_32=(int32_t)read_16bitLE(0x10+i*4,streamFile); + vgmstream->ch[i].adpcm_step_index =(int)read_8bit(0x12+i*4,streamFile); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/str_asr.c b/Frameworks/vgmstream/vgmstream/src/meta/str_asr.c new file mode 100644 index 000000000..f1184e41e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/str_asr.c @@ -0,0 +1,97 @@ +#include "meta.h" +#include "../util.h" + +/* STR -ASR (from Donkey Kong Jet Race) */ +VGMSTREAM * init_vgmstream_str_asr(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename)) && /* PCM Files */ + strcasecmp("asr",filename_extension(filename))) /* DSP Files */ + goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x4B4E4F4E && /* "KNON" */ + read_32bitBE(0x04,streamFile) != 0x00000000 && /* "0x0" */ + read_32bitBE(0x08,streamFile) != 0x57494920) goto fail; /* "WII\0x20" */ + + + loop_flag = (read_32bitBE(0x44,streamFile)!=0); + channel_count = 2; + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x40,streamFile); + + switch (read_32bitBE(0x20,streamFile)) { + case 0x4B415354: /* KAST - DSP encoding */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0x3C,streamFile))*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile))*14/8/channel_count; + vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile))*14/8/channel_count; + } + vgmstream->interleave_block_size = 0x10; + break; + case 0x4B505354: /* KPST - PCM encoding */ + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = (read_32bitBE(0x3C,streamFile))/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile))/2/channel_count; + vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile))/2/channel_count; + } + vgmstream->interleave_block_size = 0x10; + break; + default: + goto fail; + } + + /* Interleave and Layout settings */ + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_STR_ASR; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x8C+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xEC+i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/str_snds.c b/Frameworks/vgmstream/vgmstream/src/meta/str_snds.c new file mode 100644 index 000000000..b731f27cd --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/str_snds.c @@ -0,0 +1,155 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" + +/* 3DO format, .str extension and possibly a CTRL header, blocks and + * AIFF-C style format specifier. Blocks are not IFF-compliant. Interesting + * blocks are all SNDS + */ + +VGMSTREAM * init_vgmstream_str_snds(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int channel_count; + int loop_flag = 0; + off_t SHDR_offset = -1; + int FoundSHDR = 0; + int CTRL_size = -1; + + size_t file_size; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check for opening CTRL or SNDS chunk */ + if (read_32bitBE(0x0,streamFile) != 0x4354524c && /* CTRL */ + read_32bitBE(0x0,streamFile) != 0x534e4453 && // SNDS + read_32bitBE(0x0,streamFile) != 0x53484452) // SHDR + goto fail; + + file_size = get_streamfile_size(streamFile); + + /* scan chunks until we find a SNDS containing a SHDR */ + { + off_t current_chunk; + + current_chunk = 0; + + while (!FoundSHDR && current_chunk < file_size) { + if (current_chunk < 0) goto fail; + + if (current_chunk+read_32bitBE(current_chunk+4,streamFile) >= + file_size) goto fail; + + switch (read_32bitBE(current_chunk,streamFile)) + { + case 0x4354524C: /* CTRL */ + /* to distinguish between styles */ + CTRL_size = read_32bitBE(current_chunk+4,streamFile); + break; + case 0x534e4453: /* SNDS */ + switch (read_32bitBE(current_chunk+16,streamFile)) + { + case 0x53484452: /* SHDR */ + FoundSHDR = 1; + SHDR_offset = current_chunk+16; + break; + + default: + break; + } + break; + case 0x53484452: /* SHDR */ + switch (read_32bitBE(current_chunk+0x7C, streamFile)) + { + case 0x4354524C: /* CTRL */ + // to distinguish between styles + CTRL_size = read_32bitBE(current_chunk + 0x80, streamFile); + break; + + default: + break; + } + break; + default: + /* ignore others for now */ + break; + } + + current_chunk += read_32bitBE(current_chunk+4,streamFile); + } + } + + if (!FoundSHDR) goto fail; + + /* details */ + channel_count = read_32bitBE(SHDR_offset+0x20,streamFile); + loop_flag = 0; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if ((CTRL_size == 0x1C) || + (CTRL_size == 0x0B) || + (CTRL_size == -1)) + { + vgmstream->num_samples = + read_32bitBE(SHDR_offset+0x2c,streamFile)-1; /* sample count? */ + } + else { + vgmstream->num_samples = + read_32bitBE(SHDR_offset+0x2c,streamFile) /* frame count? */ + * 0x10; + } + + vgmstream->num_samples/=vgmstream->channels; + + vgmstream->sample_rate = read_32bitBE(SHDR_offset+0x1c,streamFile); + switch (read_32bitBE(SHDR_offset+0x24,streamFile)) { + case 0x53445832: /* SDX2 */ + if (channel_count > 1) { + vgmstream->coding_type = coding_SDX2_int; + vgmstream->interleave_block_size = 1; + } else + vgmstream->coding_type = coding_SDX2; + break; + default: + goto fail; + } + vgmstream->layout_type = layout_str_snds_blocked; + vgmstream->meta_type = meta_STR_SNDS; + + /* channels and loop flag are set by allocate_vgmstream */ + if (loop_flag) { + /* just guessin', no way to set loop flag anyway */ + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + /* open the file for reading by each channel */ + { + int i; + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[0].streamfile) goto fail; + for (i=0;ich[i].streamfile = vgmstream->ch[0].streamfile; + } + } + + /* start me up */ + str_snds_block_update(0,vgmstream); + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/stx.c b/Frameworks/vgmstream/vgmstream/src/meta/stx.c new file mode 100644 index 000000000..ea8c845aa --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/stx.c @@ -0,0 +1,70 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_stx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + const int loop_flag = 0; + const int channel_count = 2; /* .stx seems to be stereo only */ + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("stx",filename_extension(filename))) goto fail; + + /* length of data */ + if (read_32bitBE(0x00,streamFile) != + get_streamfile_size(streamFile) - 0x20) goto fail; + + /* bits per sample? */ + if (read_16bitBE(0x0a,streamFile) != 4) goto fail; + + /* samples per frame? */ + if (read_16bitBE(0x0c,streamFile) != 0x10) goto fail; + + /* ?? */ + if (read_16bitBE(0x0e,streamFile) != 0x1E) goto fail; + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x04,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile); + /* channels and loop flag are set by allocate_vgmstream */ + + vgmstream->coding_type = coding_NGC_AFC; + vgmstream->layout_type = layout_interleave; + vgmstream->meta_type = meta_STX; + + /* frame-level interleave (9 bytes) */ + vgmstream->interleave_block_size = 9; + + /* open the file for reading by each channel */ + { + STREAMFILE *chstreamfile; + int i; + + /* both channels use same buffer, as interleave is so small */ + chstreamfile = streamFile->open(streamFile,filename,9*channel_count*0x100); + if (!chstreamfile) goto fail; + + for (i=0;ich[i].streamfile = chstreamfile; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + 0x20 + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/svs.c b/Frameworks/vgmstream/vgmstream/src/meta/svs.c new file mode 100644 index 000000000..f78b6f0c2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/svs.c @@ -0,0 +1,69 @@ +#include "meta.h" +#include "../util.h" + +/* SVS (from Unlimited Saga) */ +/* probably Square Vag Stream */ +VGMSTREAM * init_vgmstream_svs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("svs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x53565300) /* "SVS\0" */ + goto fail; + + loop_flag = (read_32bitLE(0x08,streamFile)!=0); + /* 63.SVS has start and end on the same sample, which crashes stuff */ + if (read_32bitLE(0x08,streamFile)==read_32bitLE(0x0c,streamFile)) + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x40; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x40)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x08,streamFile)-1)*28; + vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-1)*28; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_PS2_SVS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/thp.c b/Frameworks/vgmstream/vgmstream/src/meta/thp.c new file mode 100644 index 000000000..b4b9d2407 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/thp.c @@ -0,0 +1,103 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* THP (Just play audio from .thp movie file) + by fastelbja */ + +VGMSTREAM * init_vgmstream_thp(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + + char filename[PATH_LIMIT]; + off_t start_offset; + + uint32_t maxAudioSize=0; + + uint32_t numComponents; + off_t componentTypeOffset; + off_t componentDataOffset; + + char thpVersion; + + int loop_flag; + int channel_count=-1; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("thp",filename_extension(filename)) && + strcasecmp("dsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x54485000) + goto fail; + + maxAudioSize = read_32bitBE(0x0C,streamFile); + thpVersion = read_8bit(0x06,streamFile); + + if(maxAudioSize==0) // no sound + goto fail; + + loop_flag = 0; // allways unloop + + /* fill in the vital statistics */ + if(thpVersion==0x10) { + start_offset = read_32bitBE(0x24,streamFile); + /* No idea what's up with this */ + if (start_offset == 0) + start_offset = read_32bitBE(0x28,streamFile); + } else + start_offset = read_32bitBE(0x28,streamFile); + + // Get info from the first block + componentTypeOffset = read_32bitBE(0x20,streamFile); + numComponents = read_32bitBE(componentTypeOffset ,streamFile); + componentDataOffset=componentTypeOffset+0x14; + componentTypeOffset+=4; + + for(i=0;ichannels=channel_count; + vgmstream->sample_rate=read_32bitBE(componentDataOffset+4,streamFile); + vgmstream->num_samples=read_32bitBE(componentDataOffset+8,streamFile); + break; + } else { + if(thpVersion==0x10) + componentDataOffset+=0x0c; + else + componentDataOffset+=0x08; + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + } + } + + vgmstream->thpNextFrameSize=read_32bitBE(0x18,streamFile); + thp_block_update(start_offset,vgmstream); + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_thp_blocked; + vgmstream->meta_type = meta_THP; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/tun.c b/Frameworks/vgmstream/vgmstream/src/meta/tun.c new file mode 100644 index 000000000..533ed0aff --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/tun.c @@ -0,0 +1,59 @@ +#include "meta.h" +#include "../util.h" + +/* TUN (from LEGO Racers (PC)) */ +VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tun",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x414C5020) /* "ALP " */ + goto fail; + + channel_count = 2; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x10; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 22050; + vgmstream->coding_type = coding_DVI_IMA; + vgmstream->num_samples = (get_streamfile_size(streamFile)) - 0x10; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 1; + vgmstream->meta_type = meta_TUN; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ubi_ckd.c b/Frameworks/vgmstream/vgmstream/src/meta/ubi_ckd.c new file mode 100644 index 000000000..a0576b731 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ubi_ckd.c @@ -0,0 +1,85 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Ubisoft CKD (Rayman Origins - Wii) */ +VGMSTREAM * init_vgmstream_ubi_ckd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ckd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x0,streamFile) != 0x52494646) /* RIFF */ + goto fail; + if (read_32bitBE(0x26,streamFile) != 0x6473704C) /* dspL */ + goto fail; + + loop_flag = 0; + channel_count = read_16bitBE(0x16,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (read_16bitBE(0x16,streamFile) == 1) { + start_offset = 0x96; + vgmstream->num_samples = (read_32bitBE(0x92,streamFile))*28/16/channel_count; + } + else { + start_offset = 0xFE; + vgmstream->num_samples = (read_32bitBE(0xFA,streamFile))*28/16/channel_count; + } + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x18,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (read_32bitBE(0xFA,streamFile))*28/16/channel_count; + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 8; + vgmstream->meta_type = meta_UBI_CKD; + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x4A+i*2,streamFile); + } + if (vgmstream->channels) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xB2+i*2,streamFile); + } + } + } + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vgs.c b/Frameworks/vgmstream/vgmstream/src/meta/vgs.c new file mode 100644 index 000000000..a2d8616ad --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/vgs.c @@ -0,0 +1,100 @@ +#include "meta.h" +#include "../util.h" + +/* VGS (from Guitar Hero Encore - Rocks the 80s) */ +VGMSTREAM * init_vgmstream_vgs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_flag; + int channel_flag_offset; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vgs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56675321) /* "VgS!" */ + goto fail; + + loop_flag = 0; + channel_flag_offset = get_streamfile_size(streamFile)-0x10; + channel_flag = read_32bitBE(channel_flag_offset,streamFile); + + /* Only seen files up to 5 channels, but just + to be sure we will look up to 8 chanels */ + switch (channel_flag) { + case 0x00800000: + channel_count = 1; + break; + case 0x00810000: + channel_count = 2; + break; + case 0x00820000: + channel_count = 3; + break; + case 0x00830000: + channel_count = 4; + break; + case 0x00840000: + channel_count = 5; + break; + case 0x00850000: + channel_count = 6; + break; + case 0x00860000: + channel_count = 7; + break; + case 0x00870000: + channel_count = 8; + break; + default: + goto fail; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x80; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x08,streamFile); + vgmstream->coding_type = coding_PSX_badflags; + vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)*channel_count*0x10)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile)*channel_count*0x10)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + vgmstream->meta_type = meta_VGS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/vs.c b/Frameworks/vgmstream/vgmstream/src/meta/vs.c new file mode 100644 index 000000000..9fe5ec34b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/vs.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* VS (from Men in Black) */ +VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int i; + + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vs",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0xC8000000) /* "0xC8000000" */ + goto fail; + + loop_flag = 0; + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x08; + vgmstream->channels = channel_count; + vgmstream->interleave_block_size=0x10; + vgmstream->sample_rate = read_32bitLE(0x04,streamFile); + vgmstream->coding_type = coding_PSX; + +#if 0 + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = (read_32bitLE(0x0c,streamFile)-start_offset); + } +#endif + + vgmstream->layout_type = layout_vs_blocked; + vgmstream->meta_type = meta_VS; + + + /* open the file for reading */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,0x2000); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* Calc num_samples */ + vs_block_update(start_offset,vgmstream); + vgmstream->num_samples=0; + + do { + vgmstream->num_samples += vgmstream->current_block_size*28/16; + vs_block_update(vgmstream->next_block_offset,vgmstream); + } while (vgmstream->next_block_offsetget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vsf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x56534600) /* "VSF" */ + goto fail; + + loop_flag = (read_32bitLE(0x1c,streamFile)==0x13); + if(read_32bitLE(0x8,streamFile)==0x0) + channel_count = 1; + else + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = read_32bitLE(0x10,streamFile)*28; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile)*28; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x400; + vgmstream->meta_type = meta_PS2_VSF; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + +/* VSF with SMSS header (from Tiny Toon Adventures: Defenders of the Universe */ +VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("vsf",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x534D5353) /* "SMSS" */ + goto fail; + + + loop_flag = read_32bitLE(0x18,streamFile); + channel_count = read_32bitLE(0x0c,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PSX; + vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitLE(0x18,streamFile)*2)*28/16/channel_count; + vgmstream->loop_end_sample = (read_32bitLE(0x1c,streamFile)*2)*28/16/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x8,streamFile); + vgmstream->meta_type = meta_PS2_VSF_TTA; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_bns.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_bns.c new file mode 100644 index 000000000..34cfda301 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_bns.c @@ -0,0 +1,153 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util.h" + +/* BNS - Wii "Banner Sound" disc jingle */ +VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t BNS_offset; + uint32_t info_offset=0,data_offset=0; + uint32_t channel_info_offset_list_offset; + int channel_count; + int loop_flag; + uint16_t sample_rate; + uint32_t sample_count, loop_start; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("bns",filename_extension(filename))) goto fail; + + // check header + BNS_offset = 0; + if (read_32bitBE(BNS_offset,streamFile) == 0x494D4435) // IMD5 + { + // Skip IMD5 header if present + BNS_offset = 0x20; + } + + if (read_32bitBE(BNS_offset+0x00,streamFile) != 0x424E5320) goto fail; // "BNS " + if ((uint32_t)read_32bitBE(BNS_offset+0x04,streamFile) != 0xFEFF0100u) goto fail; + + // find chunks, verify + { + // file size as claimed by header + uint32_t header_file_size = read_32bitBE(BNS_offset+0x08,streamFile); + + uint32_t header_size = read_16bitBE(BNS_offset+0xc,streamFile); + uint16_t chunk_count = read_16bitBE(BNS_offset+0xe,streamFile); + + int i; + + // assume BNS is the last thing in the file + if (header_file_size + BNS_offset != get_streamfile_size(streamFile)) + goto fail; + + for (i = 0; i < chunk_count; i++) { + uint32_t chunk_info_offset = BNS_offset+0x10+i*8; + uint32_t chunk_offset, chunk_size; + + // ensure chunk info is within header + if (chunk_info_offset+8 > BNS_offset+header_size) goto fail; + + chunk_offset = BNS_offset + (uint32_t)read_32bitBE(chunk_info_offset,streamFile); + chunk_size = (uint32_t)read_32bitBE(chunk_info_offset+4,streamFile); + + // ensure chunk is within file + if (chunk_offset < BNS_offset+header_size || + chunk_offset+chunk_size > BNS_offset+header_file_size) goto fail; + + // ensure chunk size in header matches that listed in chunk + // Note: disabled for now, as the Homebrew Channel BNS has a DATA + // chunk that doesn't include the header size + //if ((uint32_t)read_32bitBE(chunk_offset+4,streamFile) != chunk_size) goto fail; + + // handle each chunk type + switch (read_32bitBE(chunk_offset,streamFile)) { + case 0x494E464F: // INFO + info_offset = chunk_offset+8; + break; + case 0x44415441: // DATA + data_offset = chunk_offset+8; + break; + default: + goto fail; + } + } + + /* need both INFO and DATA */ + if (!info_offset || !data_offset) goto fail; + } + + /* parse out basic stuff in INFO */ + { + /* only seen this zero, specifies DSP format? */ + if (read_8bit(info_offset+0x00,streamFile) != 0) goto fail; + + loop_flag = read_8bit(info_offset+0x01,streamFile); + channel_count = read_8bit(info_offset+0x02,streamFile); + + /* only seen zero, padding? */ + if (read_8bit(info_offset+0x03,streamFile) != 0) goto fail; + + sample_rate = (uint16_t)read_16bitBE(info_offset+0x04,streamFile); + + /* only seen this zero, padding? */ + if (read_16bitBE(info_offset+0x06,streamFile) != 0) goto fail; + + loop_start = read_32bitBE(info_offset+0x08,streamFile); + + sample_count = read_32bitBE(info_offset+0x0c,streamFile); + + channel_info_offset_list_offset = info_offset + (uint32_t)read_32bitBE(info_offset+0x10,streamFile); + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = sample_rate; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = sample_count; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_WII_BNS; + + if (loop_flag) + { + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = sample_count; + } + + /* open the file for reading */ + { + int i; + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=channel_data_offset; + + for (j=0;j<16;j++) + vgmstream->ch[i].adpcm_coef[j] = + read_16bitBE(channel_dsp_offset+j*2,streamFile); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_mus.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_mus.c new file mode 100644 index 000000000..2f36e5381 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_mus.c @@ -0,0 +1,124 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" +#include "../util.h" + +/* .mus, as seen in Star Wars The Force Unleashed for Wii */ +/* Doesn't seem to be working quite right yet, coef table looks odd */ +VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + off_t start_offset; + off_t interleave; + + int i; + struct { + uint16_t gain; + uint16_t initial_ps; + uint16_t initial_hist1; + uint16_t initial_hist2; + uint16_t loop_ps; + /* + uint16_t loop_hist1; + uint16_t loop_hist2; + */ + } channel[2]; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("mus",filename_extension(filename))) goto fail; + + start_offset = read_32bitBE(0x08,streamFile); + interleave = read_32bitBE(0x04,streamFile); + + for (i=0;i<2;i++) + { + channel[i].gain = read_16bitBE(0x30+i*0x2e,streamFile); + channel[i].initial_ps = read_16bitBE(0x32+i*0x2e,streamFile); + channel[i].initial_hist1 = read_16bitBE(0x34+i*0x2e,streamFile); + channel[i].initial_hist2 = read_16bitBE(0x36+i*0x2e,streamFile); + channel[i].loop_ps = read_16bitBE(0x38+i*0x2e,streamFile); + } + + /* check initial predictor/scale */ + if (channel[0].initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) + goto fail; + if (channel[1].initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) + goto fail; + + /* check type==0 and gain==0 */ + if (channel[0].gain || + channel[1].gain) + goto fail; + +#if 0 + if (ch0_header.loop_flag) { + off_t loop_off; + /* check loop predictor/scale */ + loop_off = ch0_header.loop_start_offset/16*8; + loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); + if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) + goto fail; + if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) + goto fail; + } +#endif + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(2,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->num_samples = read_32bitBE(0x0,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(0x6c,streamFile); + + /* TODO: adjust for interleave? */ +#if 0 + vgmstream->loop_start_sample = dsp_nibbles_to_samples( + ch0_header.loop_start_offset); + vgmstream->loop_end_sample = dsp_nibbles_to_samples( + ch0_header.loop_end_offset)+1; +#endif + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + vgmstream->meta_type = meta_DSP_WII_MUS; + + /* coeffs */ + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10 + i*2,streamFile); + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3e + i*2,streamFile); + } + + /* initial history */ + /* always 0 that I've ever seen, but for completeness... */ + vgmstream->ch[0].adpcm_history1_16 = channel[0].initial_hist1; + vgmstream->ch[0].adpcm_history2_16 = channel[0].initial_hist2; + vgmstream->ch[1].adpcm_history1_16 = channel[1].initial_hist1; + vgmstream->ch[1].adpcm_history2_16 = channel[1].initial_hist2; + + vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,interleave); + if (!vgmstream->ch[0].streamfile) goto fail; + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,interleave); + if (!vgmstream->ch[1].streamfile) goto fail; + + /* open the file for reading */ + for (i=0;i<2;i++) { + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+i*interleave; + } + + return vgmstream; + +fail: + /* clean up anything we may have opened */ + if (vgmstream) { + if (vgmstream->ch[0].streamfile) close_streamfile(vgmstream->ch[0].streamfile); + close_vgmstream(vgmstream); + } + return NULL; +} + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_ras.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_ras.c new file mode 100644 index 000000000..d84bc94b2 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_ras.c @@ -0,0 +1,92 @@ +#include "meta.h" +#include "../util.h" + +/* RAS (from Donkey Kong Country Returns) */ +VGMSTREAM * init_vgmstream_wii_ras(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ras",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x5241535F) /* "RAS_" */ + goto fail; + + loop_flag = 0; + if (read_32bitBE(0x30,streamFile) != 0 || + read_32bitBE(0x34,streamFile) != 0 || + read_32bitBE(0x38,streamFile) != 0 || + read_32bitBE(0x3C,streamFile) != 0) { + loop_flag = 1; + } + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitBE(0x18,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x14,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x1c,streamFile)/channel_count/8*14; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x20,streamFile); + vgmstream->meta_type = meta_WII_RAS; + + if (loop_flag) { + // loop is block + samples into block + vgmstream->loop_start_sample = + read_32bitBE(0x30,streamFile)*vgmstream->interleave_block_size/8*14 + + read_32bitBE(0x34,streamFile); + vgmstream->loop_end_sample = + read_32bitBE(0x38,streamFile)*vgmstream->interleave_block_size/8*14 + + read_32bitBE(0x3C,streamFile); + } + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x40+i*2,streamFile); + } + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x70+i*2,streamFile); + } + } else { + goto fail; + } + + /* open the file for reading */ + { + int i; + for (i=0;ilayout_type==layout_interleave_shortblock) + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + vgmstream->interleave_block_size); + else + vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename, + 0x1000); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + start_offset + i*vgmstream->interleave_block_size; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c new file mode 100644 index 000000000..9ef2531af --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_smp.c @@ -0,0 +1,75 @@ +#include "meta.h" +#include "../util.h" + +/* SMP (Mushroom Men: The Spore Wars ) */ +VGMSTREAM * init_vgmstream_wii_smp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("smp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x05000000) /* 0x05000000 */ + goto fail; + + loop_flag = 0; + channel_count = read_32bitLE(0x28,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x1C,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x30,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitLE(0x34,streamFile)/2; + if (loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = read_32bitLE(0x34,streamFile)/2; + } + + /* We have no interleave, so we have no layout */ + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_WII_SMP; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + /*Retrieving the coef table... + This game has an exception, the coefs are stored in Little Endian... */ + { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitLE(0x50+i*2,streamFile); + } + } + + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_sng.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_sng.c new file mode 100644 index 000000000..6eb14267b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_sng.c @@ -0,0 +1,125 @@ +#include "meta.h" +#include "../util.h" + +/* SNG (from Excite Truck [WII]) */ +VGMSTREAM * init_vgmstream_wii_sng(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int i; + int loop_flag; + int channel_count; + int coef1; + int coef2; + int first_block_len; + int second_channel_start; + int dataBuffer = 0; + int Founddata = 0; + size_t file_size; + off_t current_chunk; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sng",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x30545352) /* "0STR" */ + goto fail; + if (read_32bitBE(0x04,streamFile) != 0x34000000) /* 0x34000000 */ + goto fail; + if (read_32bitBE(0x08,streamFile) != 0x08000000) /* 0x08000000" */ + goto fail; + if (read_32bitBE(0x0C,streamFile) != 0x01000000) /* 0x01000000 */ + goto fail; + if (read_32bitLE(0x10,streamFile) != (get_streamfile_size(streamFile))) + goto fail; + + loop_flag = (read_32bitLE(0x130,streamFile) !=0); /* not sure */ + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x180; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x110,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitLE(0x100,streamFile)/16*14*2; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x130,streamFile)/16*14; + vgmstream->loop_end_sample = read_32bitBE(0x134,streamFile)/16*14; + } + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_WII_SNG; + + + /* scan file until we find a "data" string */ + first_block_len = read_32bitLE(0x100,streamFile); + file_size = get_streamfile_size(streamFile); + { + current_chunk = first_block_len; + /* Start at 0 and loop until we reached the + file size, or until we found a "data string */ + while (!Founddata && current_chunk < file_size) { + dataBuffer = (read_32bitLE(current_chunk,streamFile)); + if (dataBuffer == first_block_len) { /* The value from the first block length */ + /* if "data" string found, retrieve the needed infos */ + Founddata = 1; + second_channel_start = current_chunk+0x80; + /* We will cancel the search here if we have a match */ + break; + } + /* else we will increase the search offset by 1 */ + current_chunk = current_chunk + 1; + } + } + + coef1 = 0x13C; + if (Founddata == 0) { + goto fail; + } else if (Founddata == 1) { + coef2 = current_chunk+0x3C; + } + + + for (i=0;i<16;i++) + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(coef1+i*2,streamFile); + if (channel_count == 2) { + for (i=0;i<16;i++) + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(coef2+i*2,streamFile); + } + + /* open the file for reading */ + { + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + /* The first channel */ + vgmstream->ch[0].channel_start_offset= + vgmstream->ch[0].offset=start_offset; + + /* The second channel */ + if (channel_count == 2) { + vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + + if (!vgmstream->ch[1].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[1].offset=second_channel_start; + } + } +} + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_str.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_str.c new file mode 100644 index 000000000..460a5bad9 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_str.c @@ -0,0 +1,90 @@ +#include "meta.h" +#include "../util.h" + +VGMSTREAM * init_vgmstream_wii_str(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + STREAMFILE * infileSTH = NULL; + char filename[PATH_LIMIT]; + + char * filenameSTH = NULL; + + int i, j, channel_count, loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("str",filename_extension(filename))) goto fail; + + /* check for .MIH file */ + filenameSTH=(char *)malloc(strlen(filename)+1); + + if (!filenameSTH) goto fail; + + strcpy(filenameSTH,filename); + strcpy(filenameSTH+strlen(filenameSTH)-3,"sth"); + + infileSTH = streamFile->open(streamFile,filenameSTH,STREAMFILE_DEFAULT_BUFFER_SIZE); + + /* STH File is necessary, so we can't confuse those file */ + /* with others .STR file as it is a very common extension */ + if (!infileSTH) goto fail; + + if(read_32bitLE(0x2C,infileSTH)!=0) + goto fail; + + channel_count = read_32bitBE(0x70,infileSTH); + + if(channel_count==1) + loop_flag = (read_32bitBE(0xD4,infileSTH)==0x00740000); + else + loop_flag = (read_32bitBE(0x124,infileSTH)==0x00740000); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x38,infileSTH); + + vgmstream->interleave_block_size=0x8000; + vgmstream->num_samples=read_32bitBE(0x34,infileSTH); + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + + vgmstream->meta_type = meta_WII_STR; + + if(loop_flag) { + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + } + + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset+=(off_t)(vgmstream->interleave_block_size*i); + + for(j=0; j<16; j++) { + vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(0xAC+(j*2)+(i*0x50),infileSTH); + } + } + } + + close_streamfile(infileSTH); infileSTH=NULL; + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (infileSTH) close_streamfile(infileSTH); + if (filenameSTH) {free(filenameSTH); filenameSTH=NULL;} + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wii_sts.c b/Frameworks/vgmstream/vgmstream/src/meta/wii_sts.c new file mode 100644 index 000000000..5f5f2f948 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wii_sts.c @@ -0,0 +1,87 @@ +#include "meta.h" +#include "../util.h" + +/* STS + + STS (found in Shikigami No Shiro 3) + Don't confuse with ps2 .STS (EXST) format, this one is for WII +*/ + +VGMSTREAM * init_vgmstream_wii_sts(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i,j; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("sts",filename_extension(filename))) goto fail; + + /* First bytes contain the size of the file (-4) */ + if(read_32bitBE(0x0,streamFile)!=get_streamfile_size(streamFile)-4) + goto fail; + + loop_flag = (read_32bitLE(0x4C,streamFile)!=0xFFFFFFFF); + channel_count=read_8bit(0x8,streamFile)+1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0A,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + + if(vgmstream->channels==1) + vgmstream->num_samples = (read_32bitBE(0x0,streamFile)+4-0x70)/8*14; + else + vgmstream->num_samples = (read_32bitBE(0x0,streamFile)+4-0x50-0x26)/8*14/2; + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_STS_WII; + + if(loop_flag) { + vgmstream->loop_start_sample=read_32bitLE(0x24,streamFile); + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* setting coef tables */ + if(vgmstream->channels==1) + start_offset = 0x70; + else + start_offset = 0x50; + + // First channel + for(j=0;j<16;j++) { + vgmstream->ch[0].adpcm_coef[j]=read_16bitBE(0x1E + (j*2),streamFile); + } + + // Second channel ? + if(vgmstream->channels==2) { + start_offset+=read_32bitBE(0x1a,streamFile); + for(j=0;j<16;j++) { + vgmstream->ch[1].adpcm_coef[j]=read_16bitBE(start_offset+(j*2),streamFile); + } + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0x50+(i*(start_offset+0x26-0x50)); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wpd.c b/Frameworks/vgmstream/vgmstream/src/meta/wpd.c new file mode 100644 index 000000000..3bb37a2d4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wpd.c @@ -0,0 +1,59 @@ +#include "meta.h" +#include "../util.h" + +/* WPD (from Shuffle! (PC)) */ +VGMSTREAM * init_vgmstream_wpd(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int channel_count; + int loop_flag; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wpd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x20445057) /* " DPW" */ + goto fail; + + channel_count = read_32bitLE(0x4,streamFile); + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x30; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (read_32bitLE(0x14,streamFile))/2/channel_count; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + vgmstream->meta_type = meta_WPD; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c b/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c new file mode 100644 index 000000000..01effa480 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ws_aud.c @@ -0,0 +1,132 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* Westwood Studios .aud (WS-AUD) */ + +VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + coding_t coding_type = -1; + off_t format_offset; + + int channel_count; + int new_type = 0; /* if 0 is old type */ + + int bytes_per_sample = 0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("aud",filename_extension(filename))) goto fail; + + /* check for 0x0000DEAF chunk marker for first chunk */ + if (read_32bitLE(0x10,streamFile)==0x0000DEAF) { /* new */ + new_type = 1; + } else if (read_32bitLE(0x0C,streamFile)==0x0000DEAF) { /* old */ + new_type = 0; + } else goto fail; + + if (new_type) + format_offset = 0xa; + else + format_offset = 0x6; + + /* get channel count */ + if (read_8bit(format_offset,streamFile) & 1) + channel_count = 2; + else + channel_count = 1; + + if (channel_count == 2) goto fail; /* TODO: not yet supported (largely + because not yet seen) */ + + /* get output format */ + if (read_8bit(format_offset+1,streamFile) & 2) + bytes_per_sample = 2; + else + bytes_per_sample = 1; + + /* check codec type */ + switch (read_8bit(format_offset+1,streamFile)) { + case 1: /* Westwood custom */ + coding_type = coding_WS; + /* shouldn't happen? */ + if (bytes_per_sample != 1) goto fail; + break; + case 99: /* IMA ADPCM */ + coding_type = coding_IMA; + break; + default: + goto fail; + break; + } + + /* build the VGMSTREAM */ + + vgmstream = allocate_vgmstream(channel_count,0); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + if (new_type) { + vgmstream->num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count; + } else { + /* Doh, no output size in old type files. We have to read through the + * file looking at chunk headers! Crap! */ + int32_t out_size = 0; + off_t current_offset = 0x8; + off_t file_size = get_streamfile_size(streamFile); + + while (current_offset < file_size) { + int16_t chunk_size; + chunk_size = read_16bitLE(current_offset,streamFile); + out_size += read_16bitLE(current_offset+2,streamFile); + /* while we're here might as well check for valid chunks */ + if (read_32bitLE(current_offset+4,streamFile) != 0x0000DEAF) goto fail; + current_offset+=8+chunk_size; + } + + vgmstream->num_samples = out_size/bytes_per_sample/channel_count; + } + + /* they tend to not actually have data for the last odd sample */ + if (vgmstream->num_samples & 1) vgmstream->num_samples--; + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile); + + vgmstream->coding_type = coding_type; + if (new_type) { + vgmstream->meta_type = meta_WS_AUD; + } else { + vgmstream->meta_type = meta_WS_AUD_old; + } + + vgmstream->layout_type = layout_ws_aud_blocked; + + /* open the file for reading by each channel */ + { + int i; + STREAMFILE * file; + + file = streamFile->open(streamFile,filename, + STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + + for (i=0;ich[i].streamfile = file; + } + } + + /* start me up */ + if (new_type) { + ws_aud_block_update(0xc,vgmstream); + } else { + ws_aud_block_update(0x8,vgmstream); + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/wvs.c b/Frameworks/vgmstream/vgmstream/src/meta/wvs.c new file mode 100644 index 000000000..163d93cf4 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/wvs.c @@ -0,0 +1,152 @@ +#include "meta.h" +#include "../util.h" + +/* + WVS (found in Metal Arms - Glitch in the System) + XBOX and GameCube +*/ + +VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wvs",filename_extension(filename))) goto fail; + + if((read_16bitLE(0x0C,streamFile)!=0x69) && + (read_16bitLE(0x08,streamFile)!=0x4400) && + (read_32bitLE(0x0,streamFile)!=get_streamfile_size(streamFile)+0x20)) + goto fail; + + /* Loop seems to be set if offset(0x0A) == 0x472C */ + loop_flag = (read_16bitLE(0x0A,streamFile)==0x472C); + + /* Always stereo files */ + channel_count=read_16bitLE(0x0E,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + /* allways 2 channels @ 44100 Hz */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = read_32bitLE(0,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_XBOX_WVS; + + if(loop_flag) { + vgmstream->loop_start_sample=0; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0x20; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +/* + WVS (found in Metal Arms - Glitch in the System) +*/ +VGMSTREAM * init_vgmstream_ngc_wvs(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wvs",filename_extension(filename))) goto fail; + + if ((read_32bitBE(0x14,streamFile)*read_32bitBE(0x00,streamFile)+0x60) + != (get_streamfile_size(streamFile))) + { + goto fail; + } + + loop_flag = read_32bitBE(0x10,streamFile); + channel_count = read_32bitBE(0x00,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x60; + + if (channel_count == 1) { + vgmstream->sample_rate = 22050; + } else if (channel_count == 2) { + vgmstream->sample_rate = 44100; + } + + vgmstream->channels = channel_count; + + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/8/channel_count*14; //(read_32bitBE(0x0C,streamFile)-start_offset)/8/channel_count*14; + if (loop_flag) { + vgmstream->loop_start_sample = (read_32bitBE(0x10,streamFile)*2)/8/channel_count*14; + vgmstream->loop_end_sample = (read_32bitBE(0x14,streamFile)*2)/8/channel_count*14; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile); + vgmstream->meta_type = meta_NGC_WVS; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i,c; + for (c=0;cch[c].adpcm_coef[i] = + read_16bitBE(0x18+c*0x20 +i*2,streamFile); + } + } + } + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c b/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c new file mode 100644 index 000000000..44bb321e0 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/x360_tra.c @@ -0,0 +1,61 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* TRA + + TRA is an headerless format which can be found on DefJam Rapstar (X360) + known extensions : WAVM + + 2010-12-03 - Fastelbja : First version ... +*/ +VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("tra",filename_extension(filename))) goto fail; + + /* No loop on wavm */ + loop_flag = 0; + + /* Always stereo files */ + channel_count=2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + /* allways 2 channels @ 44100 Hz */ + vgmstream->channels = 2; + vgmstream->sample_rate = 24000; + + vgmstream->coding_type = coding_DVI_IMA; + vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) - ((get_streamfile_size(streamFile)/0x204)*4)); + vgmstream->layout_type = layout_tra_blocked; + + vgmstream->meta_type = meta_X360_TRA; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + tra_block_update(0,vgmstream); + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c new file mode 100644 index 000000000..6a62ec3c1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_hlwav.c @@ -0,0 +1,64 @@ +#include "meta.h" +#include "../util.h" + +/* HLWAV (from Half Life 2 [XBOX]) */ +VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("hlwav",filename_extension(filename))) goto fail; + + /* check header and size */ + if ((read_32bitBE(0x00,streamFile) != 0x14000000)) goto fail; + if (((read_32bitLE(0x4,streamFile) + (read_32bitLE(0x8,streamFile))) != get_streamfile_size(streamFile))) goto fail; + + loop_flag = (read_32bitLE(0xC,streamFile)!= 0xFFFFFFFF); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x8,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = 22050; + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = read_32bitLE(0x4,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile)/2/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0xC,streamFile)/2/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + vgmstream->meta_type = meta_XBOX_HLWAV; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c new file mode 100644 index 000000000..08721d659 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_ims.c @@ -0,0 +1,61 @@ +#include "meta.h" +#include "../util.h" +#include "../layout/layout.h" + +/* matx + + MATX (found in Matrix) +*/ + +VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("matx",filename_extension(filename))) goto fail; + + loop_flag = 0; + channel_count=read_16bitLE(0x4,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_16bitLE(0x06,streamFile) & 0xffff; + vgmstream->coding_type = coding_XBOX; + + vgmstream->layout_type = layout_matx_blocked; + vgmstream->meta_type = meta_XBOX_MATX; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + /* Calc num_samples */ + matx_block_update(0,vgmstream); + vgmstream->num_samples=0; + + do { + vgmstream->num_samples += vgmstream->current_block_size/36*64; + matx_block_update(vgmstream->next_block_offset,vgmstream); + } while (vgmstream->next_block_offsetget_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("stma",filename_extension(filename))) goto fail; + + if(read_32bitBE(0x0,streamFile)!=0x53544D41) + goto fail; + + loop_flag = ((read_32bitLE(0x20,streamFile)==1) || (read_32bitLE(0x18,streamFile)>read_32bitLE(0x1C,streamFile))); + + /* Seems that the loop flag is not allways well defined */ + /* Some of the tracks should loop, but without flag set */ + channel_count=read_32bitLE(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); + vgmstream->coding_type = coding_INT_DVI_IMA; + vgmstream->num_samples = read_32bitLE(0x18,streamFile)*2/vgmstream->channels; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size=0x40; + vgmstream->meta_type = meta_XBOX_STMA; + + if(loop_flag) { + vgmstream->loop_start_sample=read_32bitLE(0x24,streamFile); + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0x800+(i*vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c new file mode 100644 index 000000000..cc2392868 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_wavm.c @@ -0,0 +1,61 @@ +#include "meta.h" +#include "../util.h" + +/* WAVM + + WAVM is an headerless format which can be found on XBOX + known extensions : WAVM + + 2008-05-23 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("wavm",filename_extension(filename))) goto fail; + + /* No loop on wavm */ + loop_flag = 0; + + /* Always stereo files */ + channel_count=2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + /* allways 2 channels @ 44100 Hz */ + vgmstream->channels = 2; + vgmstream->sample_rate = 44100; + + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels); + vgmstream->layout_type = layout_none; + + vgmstream->meta_type = meta_XBOX_WAVM; + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} \ No newline at end of file diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c new file mode 100644 index 000000000..337674c7f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xmu.c @@ -0,0 +1,65 @@ +#include "meta.h" +#include "../util.h" + +/* XMU + + XMU (found in Alter Echo) +*/ + +VGMSTREAM * init_vgmstream_xbox_xmu(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xmu",filename_extension(filename))) goto fail; + + if((read_32bitBE(0x00,streamFile)!=0x584D5520) && + (read_32bitBE(0x08,streamFile)!=0x46524D54)) + goto fail; + + /* No Loop found atm */ + loop_flag = read_8bit(0x16,streamFile);; + + /* Always stereo files */ + channel_count=read_8bit(0x14,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = read_32bitLE(0x7FC,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_XBOX_XMU; + + if(loop_flag) { + vgmstream->loop_start_sample=0; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0x800; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c new file mode 100644 index 000000000..a17298c3a --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xvas.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../util.h" + +/* XVAS + + XVAS (found in TMNT 2 & TMNT 3)) +*/ + +VGMSTREAM * init_vgmstream_xbox_xvas(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + int i; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xvas",filename_extension(filename))) goto fail; + + if((read_32bitLE(0x00,streamFile)!=0x69) && + (read_32bitLE(0x08,streamFile)!=0x48)) + goto fail; + + /* No Loop found atm */ + loop_flag = (read_32bitLE(0x14,streamFile)==read_32bitLE(0x24,streamFile)); + + /* Always stereo files */ + channel_count=read_32bitLE(0x04,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x0c,streamFile); + + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = read_32bitLE(0x24,streamFile); + vgmstream->num_samples -= ((vgmstream->num_samples/0x20000)*0x20); + vgmstream->num_samples = vgmstream->num_samples / 36 * 64 / vgmstream->channels; + + vgmstream->layout_type = layout_xvas_blocked; + vgmstream->meta_type = meta_XBOX_XVAS; + + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile); + vgmstream->loop_start_sample -= ((vgmstream->loop_start_sample/0x20000)*0x20); + vgmstream->loop_start_sample = vgmstream->loop_start_sample / 36 * 64 / vgmstream->channels; + vgmstream->loop_end_sample=vgmstream->num_samples; + } + + /* open the file for reading by each channel */ + { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = 0x800; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + + xvas_block_update(0x800,vgmstream); + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c new file mode 100644 index 000000000..45f55c52f --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xbox_xwav.c @@ -0,0 +1,107 @@ +#include "meta.h" +#include "../util.h" + +/* XWAV + + XWAV use the common RIFF/WAVE format with Codec ID = 0x0069 + It has been renamed to xwav to avoid vgmstream to handle all RIFF/WAV format + known extensions : XWAV + + 2008-05-24 - Fastelbja : First version ... +*/ + +VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + + int loop_flag=0; + int channel_count; + off_t start_offset; + int i,j=0; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xwav",filename_extension(filename))) goto fail; + + /* Check for headers */ + if(!((read_32bitBE(0x00,streamFile)==0x52494646) && + (read_32bitBE(0x08,streamFile)==0x57415645) && + (read_32bitBE(0x0C,streamFile)==0x666D7420) && + (read_16bitLE(0x14,streamFile)==0x0069))) + goto fail; + + /* No loop on wavm */ + if(read_32bitBE(0x28,streamFile)==0x77736D70) + loop_flag = 1; + else + loop_flag = 0; + + /* Always stereo files */ + channel_count=read_16bitLE(0x16,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* hack for loop wave found on Dynasty warriors */ + if(loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x4C,streamFile); + vgmstream->loop_end_sample = vgmstream->loop_start_sample + read_32bitLE(0x50,streamFile); + } + + /* fill in the vital statistics */ + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x18,streamFile); + + /* search for "data" */ + start_offset=0x1C; + + do { + if(read_32bitBE(start_offset,streamFile)==0x64617461) + break; + start_offset+=4; + } while (start_offset<(off_t)get_streamfile_size(streamFile)); + + if(start_offset>=(off_t)get_streamfile_size(streamFile)) + goto fail; + + start_offset+=4; + + vgmstream->coding_type = coding_XBOX; + vgmstream->num_samples = read_32bitLE(start_offset,streamFile) / 36 * 64 / vgmstream->channels; + vgmstream->layout_type = layout_none; + + vgmstream->meta_type = meta_XBOX_RIFF; + + /* open the file for reading by each channel */ + + { + if(channel_count>2) { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = start_offset+4; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } else { + for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,36); + vgmstream->ch[i].offset = start_offset+4; + + if (!vgmstream->ch[i].streamfile) goto fail; + } + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xss.c b/Frameworks/vgmstream/vgmstream/src/meta/xss.c new file mode 100644 index 000000000..eecf7a197 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xss.c @@ -0,0 +1,72 @@ +#include "meta.h" +#include "../util.h" + +/* XSS (found in Dino Crisis 3) */ +VGMSTREAM * init_vgmstream_xss(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xss",filename_extension(filename))) goto fail; + + /* check header */ + if ((uint16_t)read_16bitLE(0x15A,streamFile) != 0x10) + goto fail; + if (read_32bitLE(0x154,streamFile) / read_32bitLE(0x150,streamFile) != + (uint16_t)read_16bitLE(0x158,streamFile)) + goto fail; + + loop_flag = (read_32bitLE(0x144,streamFile)!=0); + channel_count = (uint16_t)read_16bitLE(0x14E,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x150,streamFile); + vgmstream->coding_type = coding_PCM16LE; + vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(0x144,streamFile)/2/channel_count; + vgmstream->loop_end_sample = read_32bitLE(0x148,streamFile)/2/channel_count; + } + + if (vgmstream->channels == 1) { + vgmstream->layout_type = layout_none; + } else if (vgmstream->channels > 1) { + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + } + + vgmstream->meta_type = meta_XSS; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/xwb.c b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c new file mode 100644 index 000000000..78d00dd75 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/xwb.c @@ -0,0 +1,169 @@ +#include "meta.h" +#include "../util.h" + +/* XWB - XACT Wave Bank (Main format on the XBOX console) */ + +VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + int loop_flag = 0; + int channel_count; + int coding; + int coding_flag; + int num_samples; + int header_start; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xwb",filename_extension(filename))) goto fail; + + + /* check header */ + if ((read_32bitBE(0x00,streamFile) != 0x57424E44) && /* WBND */ + (read_32bitBE(0x00,streamFile) != 0x444E4257)) /* DNBW */ + goto fail; + /* check if the file is been used as container */ + if (read_32bitBE(0x2C,streamFile) != 0x01000000) + goto fail; + + header_start = read_32bitLE(0x10,streamFile); + loop_flag = (read_32bitLE(header_start+0x10,streamFile) != 0x0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x20,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = (((uint32_t)read_32bitLE(header_start+0x4, streamFile)) << 8 >> 12) / 2; + + coding_flag = (uint16_t)(read_16bitLE(header_start+0x2,streamFile)); + switch (coding_flag) { + case 0: + coding = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + num_samples = read_32bitLE(header_start+0xC,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(header_start+10,streamFile)/2/channel_count; + vgmstream->loop_end_sample = read_32bitLE(header_start+0xC,streamFile)/2/channel_count; + } + break; + case 1: + coding = coding_XBOX; + vgmstream->layout_type = layout_none; + num_samples = read_32bitLE(header_start+0xC,streamFile)/36/channel_count*64; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitLE(header_start+0x10,streamFile)/36/channel_count*64; + vgmstream->loop_end_sample = read_32bitLE(header_start+0xC,streamFile)/36/channel_count*64; + } + break; + default: + goto fail; + } + + vgmstream->coding_type = coding; + vgmstream->num_samples = num_samples; + vgmstream->meta_type = meta_XWB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + + if (vgmstream->coding_type == coding_XBOX) { + /* xbox interleaving is a little odd */ + vgmstream->ch[i].channel_start_offset=start_offset; + } else { + vgmstream->ch[i].channel_start_offset= + start_offset+vgmstream->interleave_block_size*i; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + +VGMSTREAM * init_vgmstream_xwb2(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag = 0; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xwb",filename_extension(filename))) goto fail; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("xwb",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x444E4257) /* WBND */ + goto fail; + + loop_flag = (read_32bitBE(0xA4,streamFile)!=0); + channel_count = 2; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x800; + vgmstream->channels = channel_count; + vgmstream->sample_rate = 44100; + vgmstream->coding_type = coding_PCM16BE; + vgmstream->num_samples = read_32bitBE(0xA0,streamFile)/2/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0xA4,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0xA0,streamFile)/2/channel_count; + } + + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + vgmstream->meta_type = meta_XWB; + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} + + diff --git a/Frameworks/vgmstream/vgmstream/src/meta/ydsp.c b/Frameworks/vgmstream/vgmstream/src/meta/ydsp.c new file mode 100644 index 000000000..d4c46aa0b --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/ydsp.c @@ -0,0 +1,92 @@ +#include "meta.h" +#include "../util.h" + +/* YDSP (from WWE Day of Reckoning) */ +VGMSTREAM * init_vgmstream_ydsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int loop_flag; + int channel_count; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("ydsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x59445350) /* "YDSP" */ + goto fail; + + loop_flag = (read_32bitBE(0xB0,streamFile)!=0x0); + channel_count = (uint16_t)read_16bitBE(0x10,streamFile); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x120; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->meta_type = meta_YDSP; + + vgmstream->num_samples = (read_32bitBE(0x08,streamFile))*14/8/channel_count; + + if (loop_flag) + { + vgmstream->loop_start_sample = read_32bitBE(0xB0,streamFile); + vgmstream->loop_end_sample = read_32bitBE(0xB4,streamFile); + } + + if (channel_count == 1) + { + vgmstream->layout_type = layout_none; + } + else if (channel_count == 2) + { + vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); + vgmstream->layout_type = layout_interleave; + } + + + + /* open the file for reading */ + + if (vgmstream->coding_type == coding_NGC_DSP) + { + int i; + for (i=0;i<16;i++) + { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); + } + if (vgmstream->channels == 2) + { + for (i=0;i<16;i++) + { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x44+i*2,streamFile); + } + } + } + + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zsd.c b/Frameworks/vgmstream/vgmstream/src/meta/zsd.c new file mode 100644 index 000000000..245e49ef7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/zsd.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../util.h" + +/* ZSD (Dragon Booster) */ +VGMSTREAM * init_vgmstream_zsd(STREAMFILE *streamFile) { + + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + off_t start_offset; + + int loop_flag; + int channel_count; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("zsd",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x5A534400) goto fail; + + loop_flag = 0; + channel_count = 1; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = read_32bitLE(0x20,streamFile); + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitLE(0x10,streamFile); + vgmstream->coding_type = coding_PCM8; + vgmstream->num_samples = read_32bitLE(0x18,streamFile)/channel_count; + vgmstream->interleave_block_size=0x0; + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_ZSD; + + + /* open the file for reading */ + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset=start_offset+ + vgmstream->interleave_block_size*i; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c b/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c new file mode 100644 index 000000000..5b73520d7 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/meta/zwdsp.c @@ -0,0 +1,93 @@ +#include "meta.h" +#include "../util.h" + +/* ZWDSP (hcs' custom DSP files from Zack & Wiki) */ +VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + char filename[PATH_LIMIT]; + int second_channel_start; + int loop_flag; + int channel_count = 2; + off_t start_offset; + + /* check extension, case insensitive */ + streamFile->get_name(streamFile,filename,sizeof(filename)); + if (strcasecmp("zwdsp",filename_extension(filename))) goto fail; + + /* check header */ + if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */ + goto fail; + + /* Retrieve the loop flag, some files have 0x0 and some 0x02 as "no loop" */ + + switch (read_32bitBE(0x10, streamFile)) { + case 0: + case 2: + loop_flag = 0; + break; + default: + loop_flag = 1; + } + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + start_offset = 0x90; + vgmstream->channels = channel_count; + vgmstream->sample_rate = read_32bitBE(0x08,streamFile); + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->num_samples = read_32bitBE(0x18,streamFile)*14/8/channel_count; + if (loop_flag) { + vgmstream->loop_start_sample = read_32bitBE(0x10,streamFile)*14/8/channel_count; + vgmstream->loop_end_sample = read_32bitBE(0x14,streamFile)*14/8/channel_count; + // frequently end sample is one more than total samples in file + if (vgmstream->loop_end_sample > vgmstream->num_samples) + { + vgmstream->loop_end_sample = vgmstream->num_samples; + } + } + + + vgmstream->layout_type = layout_none; + vgmstream->meta_type = meta_ZWDSP; + + + if (vgmstream->coding_type == coding_NGC_DSP) { + int i; + for (i=0;i<16;i++) { + vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); + } + if (vgmstream->channels == 2) { + for (i=0;i<16;i++) { + vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x60+i*2,streamFile); + } + } + } + + second_channel_start = (get_streamfile_size(streamFile)+start_offset)/2; + { + int i; + STREAMFILE * file; + file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!file) goto fail; + for (i=0;ich[i].streamfile = file; + + vgmstream->ch[0].channel_start_offset=start_offset; + if (channel_count == 2) { + if (second_channel_start == -1) goto fail; + vgmstream->ch[1].channel_start_offset=second_channel_start; + } + vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset; + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/Frameworks/vgmstream/vgmstream/src/streamfile.c b/Frameworks/vgmstream/vgmstream/src/streamfile.c new file mode 100644 index 000000000..b76604cd5 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/streamfile.c @@ -0,0 +1,272 @@ +#ifndef _MSC_VER +#include +#endif +#include "streamfile.h" +#include "util.h" + +typedef struct { + STREAMFILE sf; + FILE * infile; + off_t offset; + size_t validsize; + uint8_t * buffer; + size_t buffersize; + char name[260]; +#ifdef PROFILE_STREAMFILE + size_t bytes_read; + int error_count; +#endif +} STDIOSTREAMFILE; + +static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char * const filename, size_t buffersize); + +static size_t read_the_rest(uint8_t * dest, off_t offset, size_t length, STDIOSTREAMFILE * streamfile) { + size_t length_read_total=0; + + /* is the beginning at least there? */ + if (offset >= streamfile->offset && offset < streamfile->offset+streamfile->validsize) { + size_t length_read; + off_t offset_into_buffer = offset-streamfile->offset; + length_read = streamfile->validsize-offset_into_buffer; + memcpy(dest,streamfile->buffer+offset_into_buffer,length_read); + length_read_total += length_read; + length -= length_read; + offset += length_read; + dest += length_read; + } + + /* TODO: What would make more sense here is to read the whole request + * at once into the dest buffer, as it must be large enough, and then + * copy some part of that into our own buffer. + * The destination buffer is supposed to be much smaller than the + * STREAMFILE buffer, though. Maybe we should only ever return up + * to the buffer size to avoid having to deal with things like this + * which are outside of my intended use. + */ + /* read as much of the beginning of the request as possible, proceed */ + while (length>0) { + size_t length_to_read; + size_t length_read=0; + streamfile->validsize=0; + if (fseeko(streamfile->infile,offset,SEEK_SET)) return length_read; + streamfile->offset=offset; + + /* decide how much must be read this time */ + if (length>streamfile->buffersize) length_to_read=streamfile->buffersize; + else length_to_read=length; + + /* always try to fill the buffer */ + length_read = fread(streamfile->buffer,1,streamfile->buffersize,streamfile->infile); + streamfile->validsize=length_read; + +#ifdef PROFILE_STREAMFILE + if (ferror(streamfile->infile)) { + clearerr(streamfile->infile); + streamfile->error_count++; + } + + streamfile->bytes_read += length_read; +#endif + + /* if we can't get enough to satisfy the request we give up */ + if (length_read < length_to_read) { + memcpy(dest,streamfile->buffer,length_read); + length_read_total+=length_read; + return length_read_total; + } + + /* use the new buffer */ + memcpy(dest,streamfile->buffer,length_to_read); + length_read_total+=length_to_read; + length-=length_to_read; + dest+=length_to_read; + offset+=length_to_read; + } + + return length_read_total; +} + +static size_t read_stdio(STDIOSTREAMFILE *streamfile,uint8_t * dest, off_t offset, size_t length) +{ + // read + if (!streamfile || !dest || length<=0) return 0; + + /* if entire request is within the buffer */ + if (offset >= streamfile->offset && offset+length <= streamfile->offset+streamfile->validsize) { + memcpy(dest,streamfile->buffer+(offset-streamfile->offset),length); + return length; + } + + { + size_t length_read = read_the_rest(dest,offset,length,streamfile); +#if PROFILE_STREAMFILE + if (length_read < length) + streamfile->error_count++; +#endif + return length_read; + } +} + +static void close_stdio(STDIOSTREAMFILE * streamfile) { + fclose(streamfile->infile); + free(streamfile->buffer); + free(streamfile); +} + +static size_t get_size_stdio(STDIOSTREAMFILE * streamfile) { + fseeko(streamfile->infile,0,SEEK_END); + return ftello(streamfile->infile); +} + +static off_t get_offset_stdio(STDIOSTREAMFILE *streamFile) { + return streamFile->offset; +} + +static void get_name_stdio(STDIOSTREAMFILE *streamfile,char *buffer,size_t length) { + strncpy(buffer,streamfile->name,length); + buffer[length-1]='\0'; +} + +#ifdef PROFILE_STREAMFILE +static size_t get_bytes_read_stdio(STDIOSTREAMFILE *streamFile) { + return streamFile->bytes_read; +} +static size_t get_error_count_stdio(STDIOSTREAMFILE *streamFile) { + return streamFile->error_count; +} +#endif + +static STREAMFILE *open_stdio(STDIOSTREAMFILE *streamFile,const char * const filename,size_t buffersize) { + int newfd; + FILE *newfile; + STREAMFILE *newstreamFile; + + if (!filename) + return NULL; + // if same name, duplicate the file pointer we already have open + if (!strcmp(streamFile->name,filename)) { + if (((newfd = dup(fileno(streamFile->infile))) >= 0) && + (newfile = fdopen( newfd, "rb" ))) + { + newstreamFile = open_stdio_streamfile_buffer_by_FILE(newfile,filename,buffersize); + if (newstreamFile) { + return newstreamFile; + } + // failure, close it and try the default path (which will probably fail a second time) + fclose(newfile); + } + } + // a normal open, open a new file + return open_stdio_streamfile_buffer(filename,buffersize); +} + +static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char * const filename, size_t buffersize) { + uint8_t * buffer; + STDIOSTREAMFILE * streamfile; + + buffer = calloc(buffersize,1); + if (!buffer) { + return NULL; + } + + streamfile = calloc(1,sizeof(STDIOSTREAMFILE)); + if (!streamfile) { + free(buffer); + return NULL; + } + + streamfile->sf.read = (void*)read_stdio; + streamfile->sf.get_size = (void*)get_size_stdio; + streamfile->sf.get_offset = (void*)get_offset_stdio; + streamfile->sf.get_name = (void*)get_name_stdio; + streamfile->sf.get_realname = (void*)get_name_stdio; + streamfile->sf.open = (void*)open_stdio; + streamfile->sf.close = (void*)close_stdio; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = (void*)get_bytes_read_stdio; + streamfile->sf.get_error_count = (void*)get_error_count_stdio; +#endif + + streamfile->infile = infile; + streamfile->buffersize = buffersize; + streamfile->buffer = buffer; + + strncpy(streamfile->name,filename,sizeof(streamfile->name)); + streamfile->name[sizeof(streamfile->name)-1] = '\0'; + + return &streamfile->sf; +} + +STREAMFILE * open_stdio_streamfile_buffer(const char * const filename, size_t buffersize) { + FILE * infile; + STREAMFILE *streamFile; + + infile = fopen(filename,"rb"); + if (!infile) return NULL; + + streamFile = open_stdio_streamfile_buffer_by_FILE(infile,filename,buffersize); + if (!streamFile) { + fclose(infile); + } + + return streamFile; +} + +/* Read a line into dst. The source files are MS-DOS style, + * separated (not terminated) by CRLF. Return 1 if the full line was + * retrieved (if it could fit in dst), 0 otherwise. In any case the result + * will be properly terminated. The CRLF will be removed if there is one. + * Return the number of bytes read (including CRLF line ending). Note that + * this is not the length of the string, and could be larger than the buffer. + * *line_done_ptr is set to 1 if the complete line was read into dst, + * otherwise it is set to 0. line_done_ptr can be NULL if you aren't + * interested in this info. + */ +size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, + STREAMFILE * infile, int *line_done_ptr) +{ + int i; + off_t file_length = get_streamfile_size(infile); + /* how many bytes over those put in the buffer were read */ + int extra_bytes = 0; + + if (line_done_ptr) *line_done_ptr = 0; + + for (i=0;i +#include +#include +#include +#include "streamtypes.h" +#include "util.h" + +#if defined(__MSVCRT__) || defined(_MSC_VER) +#include +#define fseeko fseek +#define ftello ftell +#define dup _dup +#ifdef fileno +#undef fileno +#endif +#define fileno _fileno +#define fdopen _fdopen +#endif + +#if defined(XBMC) +#define fseeko fseek +#endif + +#define STREAMFILE_DEFAULT_BUFFER_SIZE 0x400 + +typedef struct _STREAMFILE { + size_t (*read)(struct _STREAMFILE *,uint8_t * dest, off_t offset, size_t length); + size_t (*get_size)(struct _STREAMFILE *); + off_t (*get_offset)(struct _STREAMFILE *); + // for dual-file support + void (*get_name)(struct _STREAMFILE *,char *name,size_t length); + // for when the "name" is encoded specially, this is the actual user + // visible name + void (*get_realname)(struct _STREAMFILE *,char *name,size_t length); + struct _STREAMFILE * (*open)(struct _STREAMFILE *,const char * const filename,size_t buffersize); + + void (*close)(struct _STREAMFILE *); +#ifdef PROFILE_STREAMFILE + size_t (*get_bytes_read)(struct _STREAMFILE *); + int (*get_error_count)(struct _STREAMFILE *); + +#endif +} STREAMFILE; + +/* close a file, destroy the STREAMFILE object */ +static inline void close_streamfile(STREAMFILE * streamfile) { + streamfile->close(streamfile); +} + +/* read from a file +* +* returns number of bytes read +*/ +static inline size_t read_streamfile(uint8_t * dest, off_t offset, size_t length, STREAMFILE * streamfile) { + return streamfile->read(streamfile,dest,offset,length); +} + +/* return file size */ +static inline size_t get_streamfile_size(STREAMFILE * streamfile) { + return streamfile->get_size(streamfile); +} + +#ifdef PROFILE_STREAMFILE +/* return how many bytes we read into buffers */ +static inline size_t get_streamfile_bytes_read(STREAMFILE * streamfile) { + if (streamfile->get_bytes_read) + return streamfile->get_bytes_read(streamfile); + else + return 0; +} + +/* return how many times we encountered a read error */ +static inline int get_streamfile_error_count(STREAMFILE * streamfile) { + if (streamfile->get_error_count) + return streamfile->get_error_count(streamfile); + else + return 0; +} +#endif + +/* Sometimes you just need an int, and we're doing the buffering. +* Note, however, that if these fail to read they'll return -1, +* so that should not be a valid value or there should be some backup. */ +static inline int16_t read_16bitLE(off_t offset, STREAMFILE * streamfile) { + uint8_t buf[2]; + + if (read_streamfile(buf,offset,2,streamfile)!=2) return -1; + return get_16bitLE(buf); +} +static inline int16_t read_16bitBE(off_t offset, STREAMFILE * streamfile) { + uint8_t buf[2]; + + if (read_streamfile(buf,offset,2,streamfile)!=2) return -1; + return get_16bitBE(buf); +} +static inline int32_t read_32bitLE(off_t offset, STREAMFILE * streamfile) { + uint8_t buf[4]; + + if (read_streamfile(buf,offset,4,streamfile)!=4) return -1; + return get_32bitLE(buf); +} +static inline int32_t read_32bitBE(off_t offset, STREAMFILE * streamfile) { + uint8_t buf[4]; + + if (read_streamfile(buf,offset,4,streamfile)!=4) return -1; + return get_32bitBE(buf); +} + +static inline int8_t read_8bit(off_t offset, STREAMFILE * streamfile) { + uint8_t buf[1]; + + if (read_streamfile(buf,offset,1,streamfile)!=1) return -1; + return buf[0]; +} + +/* open file with a set buffer size, create a STREAMFILE object +* +* Returns pointer to new STREAMFILE or NULL if open failed +*/ +STREAMFILE * open_stdio_streamfile_buffer(const char * const filename, size_t buffersize); + +/* open file with a default buffer size, create a STREAMFILE object +* +* Returns pointer to new STREAMFILE or NULL if open failed +*/ +static inline STREAMFILE * open_stdio_streamfile(const char * const filename) { + return open_stdio_streamfile_buffer(filename,STREAMFILE_DEFAULT_BUFFER_SIZE); +} + +size_t get_streamfile_dos_line(int dst_length, char * dst, off_t offset, + STREAMFILE * infile, int *line_done_ptr); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/streamtypes.h b/Frameworks/vgmstream/vgmstream/src/streamtypes.h new file mode 100644 index 000000000..e87e4d393 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/streamtypes.h @@ -0,0 +1,20 @@ +/* + * streamtypes.h - widely used type definitions + */ + + +#ifndef _STREAMTYPES_H +#define _STREAMTYPES_H + +#ifdef _MSC_VER +#include +#define inline _inline +#define strcasecmp _stricmp +#define snprintf _snprintf +#else +#include +#endif + +typedef int16_t sample; + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/util.c b/Frameworks/vgmstream/vgmstream/src/util.c new file mode 100644 index 000000000..68371461e --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/util.c @@ -0,0 +1,189 @@ +#include +#include "util.h" +#include "streamtypes.h" + +int check_sample_rate(int32_t sr) { + return !(sr<1000 || sr>96000); +} + +const char * filename_extension(const char * filename) { + const char * ext; + + /* You know what would be nice? strrchrnul(). + * Instead I have to do it myself. */ + ext = strrchr(filename,'.'); + if (ext==NULL) ext=filename+strlen(filename); /* point to null, i.e. an empty string for the extension */ + else ext=ext+1; /* skip the dot */ + + return ext; +} + +void interleave_channel(sample * outbuffer, sample * inbuffer, int32_t sample_count, int channel_count, int channel_number) { + int32_t insample,outsample; + + if (channel_count==1) { + memcpy(outbuffer,inbuffer,sizeof(sample)*sample_count); + return; + } + + for (insample=0,outsample=channel_number;insample> 8; +} + +void put_32bitLE(uint8_t * buf, int32_t i) { + buf[0] = (uint8_t)(i & 0xFF); + buf[1] = (uint8_t)((i >> 8) & 0xFF); + buf[2] = (uint8_t)((i >> 16) & 0xFF); + buf[3] = (uint8_t)((i >> 24) & 0xFF); +} + +void put_16bitBE(uint8_t * buf, int16_t i) { + buf[0] = i >> 8; + buf[1] = (i & 0xFF); +} + +void put_32bitBE(uint8_t * buf, int32_t i) { + buf[0] = (uint8_t)((i >> 24) & 0xFF); + buf[1] = (uint8_t)((i >> 16) & 0xFF); + buf[2] = (uint8_t)((i >> 8) & 0xFF); + buf[3] = (uint8_t)(i & 0xFF); +} + +/* make a header for PCM .wav */ +/* buffer must be 0x2c bytes */ +void make_wav_header(uint8_t * buf, int32_t sample_count, int32_t sample_rate, int channels) { + size_t bytecount; + + bytecount = sample_count*channels*sizeof(sample); + + /* RIFF header */ + memcpy(buf+0, "RIFF", 4); + /* size of RIFF */ + put_32bitLE(buf+4, (int32_t)(bytecount+0x2c-8)); + + /* WAVE header */ + memcpy(buf+8, "WAVE", 4); + + /* WAVE fmt chunk */ + memcpy(buf+0xc, "fmt ", 4); + /* size of WAVE fmt chunk */ + put_32bitLE(buf+0x10, 0x10); + + /* compression code 1=PCM */ + put_16bitLE(buf+0x14, 1); + + /* channel count */ + put_16bitLE(buf+0x16, channels); + + /* sample rate */ + put_32bitLE(buf+0x18, sample_rate); + + /* bytes per second */ + put_32bitLE(buf+0x1c, sample_rate*channels*sizeof(sample)); + + /* block align */ + put_16bitLE(buf+0x20, (int16_t)(channels*sizeof(sample))); + + /* significant bits per sample */ + put_16bitLE(buf+0x22, sizeof(sample)*8); + + /* PCM has no extra format bytes, so we don't even need to specify a count */ + + /* WAVE data chunk */ + memcpy(buf+0x24, "data", 4); + /* size of WAVE data chunk */ + put_32bitLE(buf+0x28, (int32_t)bytecount); +} + +void swap_samples_le(sample *buf, int count) { + int i; + for (i=0;i>8; + uint8_t *p = (uint8_t*)&(buf[i]); + p[0] = b0; + p[1] = b1; + } +} + +/* length is maximum length of dst. dst will always be null-terminated if + * length > 0 */ +void concatn(int length, char * dst, const char * src) { + int i,j; + if (length <= 0) return; + for (i=0;i 1 */ +void concatn_doublenull(int length, char * dst, const char * src) { + int i,j; + if (length <= 1) return; + for (i=0;i0) i++; + for (j=0;i 1, if src won't fit, truncate */ +void concatn_fitting_doublenull(int length, char * dst, const char * src) { + int i,j,k; + if (length <= 1) return; + for (i=0;i0) i++; + k = i; + for (j=0;i>4;*/ + return nibble_to_int[n>>4]; +} + +static inline int get_low_nibble_signed(uint8_t n) { + /*return (n&7)-(n&8);*/ + return nibble_to_int[n&0xf]; +} + +/* return true for a good sample rate */ +int check_sample_rate(int32_t sr); + +/* return a file's extension (a pointer to the first character of the + * extension in the original filename or the ending null byte if no extension + */ +const char * filename_extension(const char * filename); + +static inline int clamp16(int32_t val) { + if (val>32767) return 32767; + if (val<-32768) return -32768; + return val; +} + +/* make a header for PCM .wav */ +/* buffer must be 0x2c bytes */ +void make_wav_header(uint8_t * buf, int32_t sample_count, int32_t sample_rate, int channels); +void swap_samples_le(sample *buf, int count); + +void concatn(int length, char * dst, const char * src); +void concatn_doublenull(int length, char * dst, const char * src); +void concatn_fitting_doublenull(int length, char * dst, const char * src); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c new file mode 100644 index 000000000..09f703812 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.c @@ -0,0 +1,3223 @@ +#ifdef _MSC_VER +#define _CRT_SECURE_NO_DEPRECATE +#endif + +#include +#include +#include +#include "vgmstream.h" +#include "meta/meta.h" +#include "layout/layout.h" +#include "coding/coding.h" + +/* + * List of functions that will recognize files. These should correspond pretty + * directly to the metadata types + */ +VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = { + init_vgmstream_adx, + init_vgmstream_brstm, + init_vgmstream_nds_strm, + init_vgmstream_agsc, + init_vgmstream_ngc_adpdtk, + init_vgmstream_rsf, + init_vgmstream_afc, + init_vgmstream_ast, + init_vgmstream_halpst, + init_vgmstream_rs03, + init_vgmstream_ngc_dsp_std, + init_vgmstream_Cstr, + init_vgmstream_gcsw, + init_vgmstream_ps2_ads, + init_vgmstream_ps2_npsf, + init_vgmstream_rwsd, + init_vgmstream_cdxa, + init_vgmstream_ps2_rxw, + init_vgmstream_ps2_int, + init_vgmstream_ngc_dsp_stm, + init_vgmstream_ps2_exst, + init_vgmstream_ps2_svag, + init_vgmstream_ps2_mib, + init_vgmstream_ngc_mpdsp, + init_vgmstream_ps2_mic, + init_vgmstream_ngc_dsp_std_int, + init_vgmstream_raw, + init_vgmstream_ps2_vag, + init_vgmstream_psx_gms, + init_vgmstream_ps2_str, + init_vgmstream_ps2_ild, + init_vgmstream_ps2_pnb, + init_vgmstream_xbox_wavm, + init_vgmstream_xbox_xwav, + init_vgmstream_ngc_str, + init_vgmstream_ea, + init_vgmstream_caf, + init_vgmstream_ps2_vpk, + init_vgmstream_genh, +#ifdef VGM_USE_VORBIS + init_vgmstream_ogg_vorbis, + init_vgmstream_sli_ogg, + init_vgmstream_sfl, +#endif +#if 0 + init_vgmstream_mp4_aac, +#endif +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + init_vgmstream_akb, +#endif + init_vgmstream_sadb, + init_vgmstream_ps2_bmdx, + init_vgmstream_wsi, + init_vgmstream_aifc, + init_vgmstream_str_snds, + init_vgmstream_ws_aud, +#ifdef VGM_USE_MPEG + init_vgmstream_ahx, +#endif + init_vgmstream_ivb, + init_vgmstream_amts, + init_vgmstream_svs, + init_vgmstream_riff, + init_vgmstream_rifx, + init_vgmstream_pos, + init_vgmstream_nwa, + init_vgmstream_eacs, + init_vgmstream_xss, + init_vgmstream_sl3, + init_vgmstream_hgc1, + init_vgmstream_aus, + init_vgmstream_rws, + init_vgmstream_fsb1, + // init_vgmstream_fsb2, + init_vgmstream_fsb3, + init_vgmstream_fsb4, + init_vgmstream_fsb4_wav, + init_vgmstream_rwx, + init_vgmstream_xwb, + init_vgmstream_xwb2, + init_vgmstream_xa30, + init_vgmstream_musc, + init_vgmstream_musx_v004, + init_vgmstream_musx_v005, + init_vgmstream_musx_v006, + init_vgmstream_musx_v010, + init_vgmstream_musx_v201, + init_vgmstream_leg, + init_vgmstream_filp, + init_vgmstream_ikm, + init_vgmstream_sfs, + init_vgmstream_bg00, + init_vgmstream_dvi, + init_vgmstream_kcey, + init_vgmstream_ps2_rstm, + init_vgmstream_acm, + init_vgmstream_mus_acm, + init_vgmstream_ps2_kces, + init_vgmstream_ps2_dxh, + init_vgmstream_ps2_psh, + init_vgmstream_pcm_scd, + init_vgmstream_pcm_ps2, + init_vgmstream_ps2_rkv, + init_vgmstream_ps2_psw, + init_vgmstream_ps2_vas, + init_vgmstream_ps2_tec, + init_vgmstream_ps2_enth, + init_vgmstream_sdt, + init_vgmstream_aix, + init_vgmstream_ngc_tydsp, + init_vgmstream_ngc_swd, + init_vgmstream_capdsp, + init_vgmstream_xbox_wvs, + init_vgmstream_ngc_wvs, + init_vgmstream_dc_str, + init_vgmstream_dc_str_v2, + init_vgmstream_xbox_stma, + init_vgmstream_xbox_matx, + init_vgmstream_de2, + init_vgmstream_vs, + init_vgmstream_dc_str, + init_vgmstream_dc_str_v2, + init_vgmstream_xbox_xmu, + init_vgmstream_xbox_xvas, + init_vgmstream_ngc_bh2pcm, + init_vgmstream_sat_sap, + init_vgmstream_dc_idvi, + init_vgmstream_ps2_rnd, + init_vgmstream_wii_idsp, + init_vgmstream_kraw, + init_vgmstream_ps2_omu, + init_vgmstream_ps2_xa2, + //init_vgmstream_idsp, + init_vgmstream_idsp2, + init_vgmstream_idsp3, + init_vgmstream_idsp4, + init_vgmstream_ngc_ymf, + init_vgmstream_sadl, + init_vgmstream_ps2_ccc, + init_vgmstream_psx_fag, + init_vgmstream_ps2_mihb, + init_vgmstream_ngc_pdt, + init_vgmstream_wii_mus, + init_vgmstream_dc_asd, + init_vgmstream_naomi_spsd, + + init_vgmstream_rsd2vag, + init_vgmstream_rsd2pcmb, + init_vgmstream_rsd2xadp, + init_vgmstream_rsd3vag, + init_vgmstream_rsd3gadp, + init_vgmstream_rsd3pcm, + init_vgmstream_rsd3pcmb, + init_vgmstream_rsd4pcmb, + init_vgmstream_rsd4pcm, + init_vgmstream_rsd4radp, + init_vgmstream_rsd4vag, + init_vgmstream_rsd6vag, + init_vgmstream_rsd6wadp, + init_vgmstream_rsd6xadp, + init_vgmstream_rsd6radp, + init_vgmstream_bgw, + init_vgmstream_spw, + init_vgmstream_ps2_ass, + init_vgmstream_waa_wac_wad_wam, + init_vgmstream_seg, + init_vgmstream_nds_strm_ffta2, + init_vgmstream_str_asr, + init_vgmstream_zwdsp, + init_vgmstream_gca, + init_vgmstream_spt_spd, + init_vgmstream_ish_isd, + init_vgmstream_gsp_gsb, + init_vgmstream_ydsp, + init_vgmstream_msvp, + init_vgmstream_ngc_ssm, + init_vgmstream_ps2_joe, + init_vgmstream_vgs, + init_vgmstream_dc_dcsw_dcs, + init_vgmstream_wii_smp, + init_vgmstream_emff_ps2, + init_vgmstream_emff_ngc, + init_vgmstream_ss_stream, + init_vgmstream_thp, + init_vgmstream_wii_sts, + init_vgmstream_ps2_p2bt, + init_vgmstream_ps2_gbts, + init_vgmstream_wii_sng, + init_vgmstream_ngc_dsp_iadp, + init_vgmstream_aax, + init_vgmstream_utf_dsp, + init_vgmstream_ngc_ffcc_str, + init_vgmstream_sat_baka, + init_vgmstream_nds_swav, + init_vgmstream_ps2_vsf, + init_vgmstream_nds_rrds, + init_vgmstream_ps2_tk5, + init_vgmstream_ps2_vsf_tta, + init_vgmstream_ads, + init_vgmstream_wii_str, + init_vgmstream_ps2_mcg, + init_vgmstream_zsd, + init_vgmstream_ps2_vgs, + init_vgmstream_RedSpark, + init_vgmstream_ivaud, + init_vgmstream_wii_wsd, + init_vgmstream_wii_ndp, + init_vgmstream_ps2_sps, + init_vgmstream_ps2_xa2_rrp, + init_vgmstream_nds_hwas, + init_vgmstream_ngc_lps, + init_vgmstream_ps2_snd, + init_vgmstream_naomi_adpcm, + init_vgmstream_sd9, + init_vgmstream_2dx9, + init_vgmstream_dsp_ygo, + init_vgmstream_ps2_vgv, + init_vgmstream_ngc_gcub, + init_vgmstream_maxis_xa, + init_vgmstream_ngc_sck_dsp, + init_vgmstream_apple_caff, + init_vgmstream_pc_mxst, + init_vgmstream_sab, + init_vgmstream_exakt_sc, + init_vgmstream_wii_bns, + init_vgmstream_wii_was, + init_vgmstream_pona_3do, + init_vgmstream_pona_psx, + init_vgmstream_xbox_hlwav, + init_vgmstream_stx, + init_vgmstream_ps2_stm, + init_vgmstream_myspd, + init_vgmstream_his, + init_vgmstream_ps2_ast, + init_vgmstream_dmsg, + init_vgmstream_ngc_dsp_aaap, + init_vgmstream_ngc_dsp_konami, + init_vgmstream_ps2_ster, + init_vgmstream_ps2_wb, + init_vgmstream_bnsf, +#ifdef VGM_USE_G7221 + init_vgmstream_s14_sss, +#endif + init_vgmstream_ps2_gcm, + init_vgmstream_ps2_smpl, + init_vgmstream_ps2_msa, + init_vgmstream_ps2_voi, + init_vgmstream_ps2_khv, + init_vgmstream_pc_smp, + init_vgmstream_ngc_bo2, + init_vgmstream_dsp_ddsp, + init_vgmstream_p3d, + init_vgmstream_ps2_tk1, + init_vgmstream_ps2_adsc, + init_vgmstream_ngc_dsp_mpds, + init_vgmstream_dsp_str_ig, + init_vgmstream_psx_mgav, + init_vgmstream_ngc_dsp_sth_str1, + init_vgmstream_ngc_dsp_sth_str2, + init_vgmstream_ngc_dsp_sth_str3, + init_vgmstream_ps2_b1s, + init_vgmstream_ps2_wad, + init_vgmstream_dsp_xiii, + init_vgmstream_dsp_cabelas, + init_vgmstream_ps2_adm, + init_vgmstream_ps2_lpcm, + init_vgmstream_dsp_bdsp, + init_vgmstream_ps2_vms, + init_vgmstream_ps2_xau, + init_vgmstream_gh3_bar, + init_vgmstream_ffw, + init_vgmstream_dsp_dspw, + init_vgmstream_ps2_jstm, + init_vgmstream_ps3_xvag, + init_vgmstream_ps3_cps, + init_vgmstream_sqex_scd, + init_vgmstream_ngc_nst_dsp, + init_vgmstream_baf, + init_vgmstream_ps3_msf, + init_vgmstream_fsb_mpeg, + init_vgmstream_nub_vag, + init_vgmstream_ps3_past, + init_vgmstream_ps3_sgh_sgb, + init_vgmstream_ngca, + init_vgmstream_wii_ras, + init_vgmstream_ps2_spm, + init_vgmstream_x360_tra, + init_vgmstream_ps2_iab, + init_vgmstream_ps2_strlr, + init_vgmstream_lsf_n1nj4n, + init_vgmstream_ps3_vawx, + init_vgmstream_pc_snds, + init_vgmstream_ps2_wmus, + init_vgmstream_hyperscan_kvag, + init_vgmstream_ios_psnd, + init_vgmstream_bos_adp, + init_vgmstream_eb_sfx, + init_vgmstream_eb_sf0, + init_vgmstream_ps3_klbs, + init_vgmstream_ps3_sgx, + init_vgmstream_ps2_mtaf, + init_vgmstream_tun, + init_vgmstream_wpd, + init_vgmstream_ps3_sgd, + init_vgmstream_mn_str, + init_vgmstream_ps2_mss, + init_vgmstream_ps2_hsf, + init_vgmstream_ps3_ivag, + init_vgmstream_ps2_2pfs, + init_vgmstream_xnbm, + init_vgmstream_rsd6oogv, + init_vgmstream_ubi_ckd, + init_vgmstream_ps2_vbk, + init_vgmstream_otm, + init_vgmstream_bcstm, +}; + +#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])) + +/* internal version with all parameters */ +VGMSTREAM * init_vgmstream_internal(STREAMFILE *streamFile, int do_dfs) { + int i; + + if (!streamFile) + return NULL; + + /* try a series of formats, see which works */ + for (i=0;isample_rate)) { + close_vgmstream(vgmstream); + continue; + } + + /* dual file stereo */ + if (do_dfs && ( + (vgmstream->meta_type == meta_DSP_STD) || + (vgmstream->meta_type == meta_PS2_VAGp) || + (vgmstream->meta_type == meta_GENH) || + (vgmstream->meta_type == meta_KRAW) || + (vgmstream->meta_type == meta_PS2_MIB) || + (vgmstream->meta_type == meta_NGC_LPS) || + (vgmstream->meta_type == meta_DSP_YGO) || + (vgmstream->meta_type == meta_DSP_AGSC) || + (vgmstream->meta_type == meta_PS2_SMPL) || + (vgmstream->meta_type == meta_NGCA) || + (vgmstream->meta_type == meta_NUB_VAG) || + (vgmstream->meta_type == meta_SPT_SPD) || + (vgmstream->meta_type == meta_EB_SFX) + ) && vgmstream->channels == 1) { + try_dual_file_stereo(vgmstream, streamFile); + } + + /* save start things so we can restart for seeking */ + /* copy the channels */ + memcpy(vgmstream->start_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); + /* copy the whole VGMSTREAM */ + memcpy(vgmstream->start_vgmstream,vgmstream,sizeof(VGMSTREAM)); + + return vgmstream; + } + } + + return NULL; +} + +/* format detection and VGMSTREAM setup, uses default parameters */ +VGMSTREAM * init_vgmstream(const char * const filename) { + VGMSTREAM *vgmstream = NULL; + STREAMFILE *streamFile = open_stdio_streamfile(filename); + if (streamFile) { + vgmstream = init_vgmstream_from_STREAMFILE(streamFile); + close_streamfile(streamFile); + } + return vgmstream; +} + +VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile) { + return init_vgmstream_internal(streamFile,1); +} + +/* Reset a VGMSTREAM to its state at the start of playback. + * Note that this does not reset the constituent STREAMFILES. */ +void reset_vgmstream(VGMSTREAM * vgmstream) { + /* copy the vgmstream back into itself */ + memcpy(vgmstream,vgmstream->start_vgmstream,sizeof(VGMSTREAM)); + + /* copy the initial channels */ + memcpy(vgmstream->ch,vgmstream->start_ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); + + /* loop_ch is not zeroed here because there is a possibility of the + * init_vgmstream_* function doing something tricky and precomputing it. + * Otherwise hit_loop will be 0 and it will be copied over anyway when we + * really hit the loop start. */ + +#ifdef VGM_USE_VORBIS + if (vgmstream->coding_type==coding_ogg_vorbis) { + ogg_vorbis_codec_data *data = vgmstream->codec_data; + + OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file); + + ov_pcm_seek(ogg_vorbis_file, 0); + } +#endif +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + if (vgmstream->coding_type==coding_MP4_AAC) { + mp4_aac_codec_data *data = vgmstream->codec_data; + data->sampleId = 0; + data->sample_ptr = data->samples_per_frame; + data->samples_discard = 0; + } +#endif +#ifdef VGM_USE_MPEG + if (vgmstream->layout_type==layout_mpeg || + vgmstream->layout_type==layout_fake_mpeg) { + off_t input_offset; + mpeg_codec_data *data = vgmstream->codec_data; + + /* input_offset is ignored as we can assume it will be 0 for a seek + * to sample 0 */ + mpg123_feedseek(data->m,0,SEEK_SET,&input_offset); + data->buffer_full = data->buffer_used = 0; + } +#endif +#ifdef VGM_USE_G7221 + if (vgmstream->coding_type==coding_G7221 || + vgmstream->coding_type==coding_G7221C) { + g7221_codec_data *data = vgmstream->codec_data; + int i; + + for (i = 0; i < vgmstream->channels; i++) + { + g7221_reset(data[i].handle); + } + } +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS + if (vgmstream->coding_type==coding_AT3plus) { + maiatrac3plus_codec_data *data = vgmstream->codec_data; + + if (data->handle) Atrac3plusDecoder_closeContext(data->handle); + data->handle = Atrac3plusDecoder_openContext(); + data->samples_discard = 0; + } +#endif + + if (vgmstream->coding_type==coding_ACM) { + mus_acm_codec_data *data = vgmstream->codec_data; + int i; + + data->current_file = 0; + for (i=0;ifile_count;i++) { + acm_reset(data->files[i]); + } + } + + if (vgmstream->layout_type==layout_aix) { + aix_codec_data *data = vgmstream->codec_data; + int i; + + data->current_segment = 0; + for (i=0;isegment_count*data->stream_count;i++) + { + reset_vgmstream(data->adxs[i]); + } + } + + if (vgmstream->layout_type==layout_aax) { + aax_codec_data *data = vgmstream->codec_data; + int i; + + data->current_segment = 0; + for (i=0;isegment_count;i++) + { + reset_vgmstream(data->adxs[i]); + } + } + + if ( + vgmstream->coding_type == coding_NWA0 || + vgmstream->coding_type == coding_NWA1 || + vgmstream->coding_type == coding_NWA2 || + vgmstream->coding_type == coding_NWA3 || + vgmstream->coding_type == coding_NWA4 || + vgmstream->coding_type == coding_NWA5 + ) { + nwa_codec_data *data = vgmstream->codec_data; + reset_nwa(data->nwa); + } + + if (vgmstream->layout_type==layout_scd_int) { + scd_int_codec_data *data = vgmstream->codec_data; + int i; + + for (i=0;isubstream_count;i++) + { + reset_vgmstream(data->substreams[i]); + } + } + +} + +/* simply allocate memory for the VGMSTREAM and its channels */ +VGMSTREAM * allocate_vgmstream(int channel_count, int looped) { + VGMSTREAM * vgmstream; + VGMSTREAM * start_vgmstream; + VGMSTREAMCHANNEL * channels; + VGMSTREAMCHANNEL * start_channels; + VGMSTREAMCHANNEL * loop_channels; + + if (channel_count <= 0) return NULL; + + vgmstream = calloc(1,sizeof(VGMSTREAM)); + if (!vgmstream) return NULL; + + vgmstream->ch = NULL; + vgmstream->start_ch = NULL; + vgmstream->loop_ch = NULL; + vgmstream->start_vgmstream = NULL; + vgmstream->codec_data = NULL; + + start_vgmstream = calloc(1,sizeof(VGMSTREAM)); + if (!start_vgmstream) { + free(vgmstream); + return NULL; + } + vgmstream->start_vgmstream = start_vgmstream; + start_vgmstream->start_vgmstream = start_vgmstream; + + channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL)); + if (!channels) { + free(vgmstream); + free(start_vgmstream); + return NULL; + } + vgmstream->ch = channels; + vgmstream->channels = channel_count; + + start_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL)); + if (!start_channels) { + free(vgmstream); + free(start_vgmstream); + free(channels); + return NULL; + } + vgmstream->start_ch = start_channels; + + if (looped) { + loop_channels = calloc(channel_count,sizeof(VGMSTREAMCHANNEL)); + if (!loop_channels) { + free(vgmstream); + free(start_vgmstream); + free(channels); + free(start_channels); + return NULL; + } + vgmstream->loop_ch = loop_channels; + } + + vgmstream->loop_flag = looped; + + return vgmstream; +} + +void close_vgmstream(VGMSTREAM * vgmstream) { + int i,j; + if (!vgmstream) return; + +#ifdef VGM_USE_VORBIS + if (vgmstream->coding_type==coding_ogg_vorbis) { + ogg_vorbis_codec_data *data = vgmstream->codec_data; + if (vgmstream->codec_data) { + OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file); + + ov_clear(ogg_vorbis_file); + + close_streamfile(data->ov_streamfile.streamfile); + free(vgmstream->codec_data); + vgmstream->codec_data = NULL; + } + } +#endif + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + if (vgmstream->coding_type==coding_MP4_AAC) { + mp4_aac_codec_data *data = vgmstream->codec_data; + if (vgmstream->codec_data) { + if (data->h_aacdecoder) aacDecoder_Close(data->h_aacdecoder); + if (data->h_mp4file) MP4Close(data->h_mp4file, 0); + if (data->if_file.streamfile) close_streamfile(data->if_file.streamfile); + free(vgmstream->codec_data); + vgmstream->codec_data = NULL; + } + } +#endif + +#ifdef VGM_USE_MPEG + if (vgmstream->layout_type==layout_fake_mpeg|| + vgmstream->layout_type==layout_mpeg) { + mpeg_codec_data *data = vgmstream->codec_data; + + if (data) { + mpg123_delete(data->m); + free(vgmstream->codec_data); + vgmstream->codec_data = NULL; + /* The astute reader will note that a call to mpg123_exit is never + * made. While is is evilly breaking our contract with mpg123, it + * doesn't actually do anything except set the "initialized" flag + * to 0. And if we exit we run the risk of turning it off when + * someone else in another thread is using it. */ + } + } +#endif + +#ifdef VGM_USE_G7221 + if (vgmstream->coding_type == coding_G7221 || + vgmstream->coding_type == coding_G7221C) { + + g7221_codec_data *data = vgmstream->codec_data; + + if (data) + { + int i; + + for (i = 0; i < vgmstream->channels; i++) + { + g7221_free(data[i].handle); + } + free(data); + } + + vgmstream->codec_data = NULL; + } +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS + if (vgmstream->coding_type == coding_AT3plus) { + maiatrac3plus_codec_data *data = vgmstream->codec_data; + + if (data) + { + if (data->handle) Atrac3plusDecoder_closeContext(data->handle); + free(data); + } + } +#endif + + if (vgmstream->coding_type==coding_ACM) { + mus_acm_codec_data *data = vgmstream->codec_data; + + if (data) { + if (data->files) { + int i; + for (i=0; ifile_count; i++) { + /* shouldn't be duplicates */ + if (data->files[i]) { + acm_close(data->files[i]); + data->files[i] = NULL; + } + } + free(data->files); + data->files = NULL; + } + + free(vgmstream->codec_data); + vgmstream->codec_data = NULL; + } + } + + if (vgmstream->layout_type==layout_aix) { + aix_codec_data *data = vgmstream->codec_data; + + if (data) { + if (data->adxs) { + int i; + for (i=0;isegment_count*data->stream_count;i++) { + + /* note that the AIX close_streamfile won't do anything but + * deallocate itself, there is only one open file and that + * is in vgmstream->ch[0].streamfile */ + close_vgmstream(data->adxs[i]); + } + free(data->adxs); + } + if (data->sample_counts) { + free(data->sample_counts); + } + + free(data); + } + vgmstream->codec_data = NULL; + } + if (vgmstream->layout_type==layout_aax) { + aax_codec_data *data = vgmstream->codec_data; + + if (data) { + if (data->adxs) { + int i; + for (i=0;isegment_count;i++) { + + /* note that the AAX close_streamfile won't do anything but + * deallocate itself, there is only one open file and that + * is in vgmstream->ch[0].streamfile */ + close_vgmstream(data->adxs[i]); + } + free(data->adxs); + } + if (data->sample_counts) { + free(data->sample_counts); + } + + free(data); + } + vgmstream->codec_data = NULL; + } + + if ( + vgmstream->coding_type == coding_NWA0 || + vgmstream->coding_type == coding_NWA1 || + vgmstream->coding_type == coding_NWA2 || + vgmstream->coding_type == coding_NWA3 || + vgmstream->coding_type == coding_NWA4 || + vgmstream->coding_type == coding_NWA5 + ) { + nwa_codec_data *data = vgmstream->codec_data; + + close_nwa(data->nwa); + + free(data); + + vgmstream->codec_data = NULL; + } + + if (vgmstream->layout_type==layout_scd_int) { + scd_int_codec_data *data = vgmstream->codec_data; + + if (data) { + if (data->substreams) { + int i; + for (i=0;isubstream_count;i++) { + + /* note that the scd_int close_streamfile won't do anything + * but deallocate itself, there is only one open file and + * that is in vgmstream->ch[0].streamfile */ + close_vgmstream(data->substreams[i]); + close_streamfile(data->intfiles[i]); + } + free(data->substreams); + free(data->intfiles); + } + + free(data); + } + vgmstream->codec_data = NULL; + } + + /* now that the special cases have had their chance, clean up the standard items */ + for (i=0;ichannels;i++) { + if (vgmstream->ch[i].streamfile) { + close_streamfile(vgmstream->ch[i].streamfile); + /* Multiple channels might have the same streamfile. Find the others + * that are the same as this and clear them so they won't be closed + * again. */ + for (j=0;jchannels;j++) { + if (i!=j && vgmstream->ch[j].streamfile == + vgmstream->ch[i].streamfile) { + vgmstream->ch[j].streamfile = NULL; + } + } + vgmstream->ch[i].streamfile = NULL; + } + } + + if (vgmstream->loop_ch) free(vgmstream->loop_ch); + if (vgmstream->start_ch) free(vgmstream->start_ch); + if (vgmstream->ch) free(vgmstream->ch); + /* the start_vgmstream is considered just data */ + if (vgmstream->start_vgmstream) free(vgmstream->start_vgmstream); + + free(vgmstream); +} + +int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream) { + if (vgmstream->loop_flag) { + return vgmstream->loop_start_sample+(vgmstream->loop_end_sample-vgmstream->loop_start_sample)*looptimes+(fadedelayseconds+fadeseconds)*vgmstream->sample_rate; + } else return vgmstream->num_samples; +} + +void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { + switch (vgmstream->layout_type) { + case layout_interleave: + case layout_interleave_shortblock: + render_vgmstream_interleave(buffer,sample_count,vgmstream); + break; +#ifdef VGM_USE_VORBIS + case layout_ogg_vorbis: +#endif +#ifdef VGM_USE_MPEG + case layout_fake_mpeg: + case layout_mpeg: +#endif + case layout_dtk_interleave: + case layout_none: + render_vgmstream_nolayout(buffer,sample_count,vgmstream); + break; + case layout_mxch_blocked: + case layout_ast_blocked: + case layout_halpst_blocked: + case layout_xa_blocked: + case layout_ea_blocked: + case layout_eacs_blocked: + case layout_caf_blocked: + case layout_wsi_blocked: + case layout_str_snds_blocked: + case layout_ws_aud_blocked: + case layout_matx_blocked: + case layout_de2_blocked: + case layout_vs_blocked: + case layout_emff_ps2_blocked: + case layout_emff_ngc_blocked: + case layout_gsb_blocked: + case layout_xvas_blocked: + case layout_thp_blocked: + case layout_filp_blocked: + case layout_ivaud_blocked: + case layout_psx_mgav_blocked: + case layout_ps2_adm_blocked: + case layout_dsp_bdsp_blocked: + case layout_tra_blocked: + case layout_ps2_iab_blocked: + case layout_ps2_strlr_blocked: + render_vgmstream_blocked(buffer,sample_count,vgmstream); + break; + case layout_interleave_byte: + render_vgmstream_interleave_byte(buffer,sample_count,vgmstream); + break; + case layout_acm: + case layout_mus_acm: + render_vgmstream_mus_acm(buffer,sample_count,vgmstream); + break; + case layout_aix: + render_vgmstream_aix(buffer,sample_count,vgmstream); + break; + case layout_aax: + render_vgmstream_aax(buffer,sample_count,vgmstream); + break; + case layout_scd_int: + render_vgmstream_scd_int(buffer,sample_count,vgmstream); + break; + } +} + +int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { + switch (vgmstream->coding_type) { + case coding_CRI_ADX: + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: + case coding_L5_555: + return 32; + case coding_NGC_DSP: + return 14; + case coding_PCM16LE: + case coding_PCM16LE_int: + case coding_PCM16LE_XOR_int: + case coding_PCM16BE: + case coding_PCM8: + case coding_PCM8_U: + case coding_PCM8_int: + case coding_PCM8_SB_int: + case coding_PCM8_U_int: +#ifdef VGM_USE_VORBIS + case coding_ogg_vorbis: +#endif +#ifdef VGM_USE_MPEG + case coding_fake_MPEG2_L2: + case coding_MPEG1_L1: + case coding_MPEG1_L2: + case coding_MPEG1_L3: + case coding_MPEG2_L1: + case coding_MPEG2_L2: + case coding_MPEG2_L3: + case coding_MPEG25_L1: + case coding_MPEG25_L2: + case coding_MPEG25_L3: +#endif + case coding_SDX2: + case coding_SDX2_int: + case coding_CBD2: + case coding_ACM: + case coding_NWA0: + case coding_NWA1: + case coding_NWA2: + case coding_NWA3: + case coding_NWA4: + case coding_NWA5: + case coding_SASSC: + return 1; + case coding_NDS_IMA: + case coding_DAT4_IMA: + return (vgmstream->interleave_block_size-4)*2; + case coding_NGC_DTK: + return 28; + case coding_G721: + case coding_DVI_IMA: + case coding_EACS_IMA: + case coding_SNDS_IMA: + case coding_IMA: + return 1; + case coding_INT_IMA: + case coding_INT_DVI_IMA: + case coding_AICA: + return 2; + case coding_NGC_AFC: + case coding_FFXI: + return 16; + case coding_PSX: + case coding_PSX_badflags: + case coding_invert_PSX: + case coding_XA: + return 28; + case coding_XBOX: + case coding_INT_XBOX: + case coding_BAF_ADPCM: + return 64; + case coding_EAXA: + return 28; + case coding_MAXIS_ADPCM: + case coding_EA_ADPCM: + return 14*vgmstream->channels; + case coding_WS: + /* only works if output sample size is 8 bit, which is always + is for WS ADPCM */ + return vgmstream->ws_output_size; + case coding_MSADPCM: + return (vgmstream->interleave_block_size-(7-1)*vgmstream->channels)*2/vgmstream->channels; + case coding_APPLE_IMA4: + return 64; + case coding_MS_IMA: + case coding_RAD_IMA: + return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels; + case coding_RAD_IMA_mono: + return 32; + case coding_NDS_PROCYON: + return 30; +#ifdef VGM_USE_G7221 + case coding_G7221C: + return 32000/50; + case coding_G7221: + return 16000/50; +#endif + case coding_LSF: + return 54; + case coding_MTAF: + return 0x80*2; +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + case coding_MP4_AAC: + return ((mp4_aac_codec_data*)vgmstream->codec_data)->samples_per_frame; +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: + return 2048 - ((maiatrac3plus_codec_data*)vgmstream->codec_data)->samples_discard; +#endif + default: + return 0; + } +} + +int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream) { + switch (vgmstream->coding_type) { + case coding_NDS_IMA: + return (vgmstream->interleave_smallblock_size-4)*2; + default: + return get_vgmstream_samples_per_frame(vgmstream); + } +} + +int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { + switch (vgmstream->coding_type) { + case coding_CRI_ADX: + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: + case coding_L5_555: + return 18; + case coding_NGC_DSP: + return 8; + case coding_PCM16LE: + case coding_PCM16LE_int: + case coding_PCM16LE_XOR_int: + case coding_PCM16BE: + return 2; + case coding_PCM8: + case coding_PCM8_U: + case coding_PCM8_int: + case coding_PCM8_SB_int: + case coding_PCM8_U_int: + case coding_SDX2: + case coding_SDX2_int: + case coding_CBD2: + case coding_NWA0: + case coding_NWA1: + case coding_NWA2: + case coding_NWA3: + case coding_NWA4: + case coding_NWA5: + case coding_SASSC: + return 1; + case coding_MS_IMA: + case coding_RAD_IMA: + case coding_NDS_IMA: + case coding_DAT4_IMA: + return vgmstream->interleave_block_size; + case coding_RAD_IMA_mono: + return 0x14; + case coding_NGC_DTK: + return 32; + case coding_EACS_IMA: + return 1; + case coding_DVI_IMA: + case coding_IMA: + case coding_G721: + case coding_SNDS_IMA: + return 0; + case coding_NGC_AFC: + case coding_FFXI: + return 9; + case coding_PSX: + case coding_PSX_badflags: + case coding_invert_PSX: + case coding_NDS_PROCYON: + return 16; + case coding_XA: + return 14*vgmstream->channels; + case coding_XBOX: + case coding_INT_XBOX: + return 36; + case coding_MAXIS_ADPCM: + return 15*vgmstream->channels; + case coding_EA_ADPCM: + return 30; + case coding_EAXA: + return 1; // the frame is variant in size + case coding_WS: + return vgmstream->current_block_size; + case coding_INT_IMA: + case coding_INT_DVI_IMA: + case coding_AICA: + return 1; + case coding_APPLE_IMA4: + return 34; + case coding_BAF_ADPCM: + return 33; + case coding_LSF: + return 28; +#ifdef VGM_USE_G7221 + case coding_G7221C: + case coding_G7221: +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: +#endif + case coding_MSADPCM: + case coding_MTAF: + return vgmstream->interleave_block_size; + default: + return 0; + } +} + +int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream) { + switch (vgmstream->coding_type) { + case coding_NDS_IMA: + return vgmstream->interleave_smallblock_size; + default: + return get_vgmstream_frame_size(vgmstream); + } +} + +void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel) { + + switch (vgmstream->coding_type) { + case coding_NGC_DSP: + decode_ngc_dsp_mem(&vgmstream->ch[channel], + buffer+samples_written*vgmstream->channels+channel, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do, data); + break; + default: + break; + } +} + +void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer) { + int chan; + + switch (vgmstream->coding_type) { + case coding_CRI_ADX: + for (chan=0;chanchannels;chan++) { + decode_adx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + + break; + case coding_CRI_ADX_enc_8: + case coding_CRI_ADX_enc_9: + for (chan=0;chanchannels;chan++) { + decode_adx_enc(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + + break; + case coding_NGC_DSP: + for (chan=0;chanchannels;chan++) { + decode_ngc_dsp(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM16LE: + for (chan=0;chanchannels;chan++) { + decode_pcm16LE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM16LE_int: + for (chan=0;chanchannels;chan++) { + decode_pcm16LE_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM16LE_XOR_int: + for (chan=0;chanchannels;chan++) { + decode_pcm16LE_XOR_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM16BE: + for (chan=0;chanchannels;chan++) { + decode_pcm16BE(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM8: + for (chan=0;chanchannels;chan++) { + decode_pcm8(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM8_U: + for (chan=0;chanchannels;chan++) { + decode_pcm8_unsigned(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM8_int: + for (chan=0;chanchannels;chan++) { + decode_pcm8_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM8_SB_int: + for (chan=0;chanchannels;chan++) { + decode_pcm8_sb_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PCM8_U_int: + for (chan=0;chanchannels;chan++) { + decode_pcm8_unsigned_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_NDS_IMA: + for (chan=0;chanchannels;chan++) { + decode_nds_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_DAT4_IMA: + for (chan=0;chanchannels;chan++) { + decode_dat4_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_XBOX: + for (chan=0;chanchannels;chan++) { + decode_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_INT_XBOX: + for (chan=0;chanchannels;chan++) { + decode_int_xbox_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_MS_IMA: + for (chan=0;chanchannels;chan++) { + decode_ms_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_RAD_IMA: + for (chan=0;chanchannels;chan++) { + decode_rad_ima(vgmstream,&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_RAD_IMA_mono: + for (chan=0;chanchannels;chan++) { + decode_rad_ima_mono(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_NGC_DTK: + for (chan=0;chanchannels;chan++) { + decode_ngc_dtk(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_G721: + for (chan=0;chanchannels;chan++) { + decode_g721(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_NGC_AFC: + for (chan=0;chanchannels;chan++) { + decode_ngc_afc(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_PSX: + for (chan=0;chanchannels;chan++) { + if(vgmstream->skip_last_channel) + { + if(chan!=vgmstream->channels-1) { + decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + + } else { + decode_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + } + break; + case coding_PSX_badflags: + for (chan=0;chanchannels;chan++) { + decode_psx_badflags(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_invert_PSX: + for (chan=0;chanchannels;chan++) { + decode_invert_psx(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_FFXI: + for (chan=0;chanchannels;chan++) { + decode_ffxi_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_BAF_ADPCM: + for (chan=0;chanchannels;chan++) { + decode_baf_adpcm(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_XA: + for (chan=0;chanchannels;chan++) { + decode_xa(vgmstream,buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_EAXA: + for (chan=0;chanchannels;chan++) { + decode_eaxa(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_EA_ADPCM: + for (chan=0;chanchannels;chan++) { + decode_ea_adpcm(vgmstream,buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_MAXIS_ADPCM: + for (chan=0;chanchannels;chan++) { + decode_maxis_adpcm(vgmstream,buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; +#ifdef VGM_USE_VORBIS + case coding_ogg_vorbis: + decode_ogg_vorbis(vgmstream->codec_data, + buffer+samples_written*vgmstream->channels,samples_to_do, + vgmstream->channels); + break; +#endif +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + case coding_MP4_AAC: + decode_mp4_aac(vgmstream->codec_data, + buffer+samples_written*vgmstream->channels,samples_to_do, + vgmstream->channels); + break; +#endif + case coding_SDX2: + for (chan=0;chanchannels;chan++) { + decode_sdx2(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_SDX2_int: + for (chan=0;chanchannels;chan++) { + decode_sdx2_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_CBD2: + for (chan=0;chanchannels;chan++) { + decode_cbd2(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_CBD2_int: + for (chan=0;chanchannels;chan++) { + decode_cbd2_int(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_DVI_IMA: + case coding_INT_DVI_IMA: + for (chan=0;chanchannels;chan++) { + decode_dvi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_EACS_IMA: + for (chan=0;chanchannels;chan++) { + decode_eacs_ima(vgmstream,buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_IMA: + case coding_INT_IMA: + for (chan=0;chanchannels;chan++) { + decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_APPLE_IMA4: + for (chan=0;chanchannels;chan++) { + decode_apple_ima4(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_SNDS_IMA: + for (chan=0;chanchannels;chan++) { + decode_snds_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do,chan); + } + break; + case coding_WS: + for (chan=0;chanchannels;chan++) { + decode_ws(vgmstream,chan,buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; +#ifdef VGM_USE_MPEG + case coding_fake_MPEG2_L2: + decode_fake_mpeg2_l2( + &vgmstream->ch[0], + vgmstream->codec_data, + buffer+samples_written*vgmstream->channels,samples_to_do); + break; + case coding_MPEG1_L1: + case coding_MPEG1_L2: + case coding_MPEG1_L3: + case coding_MPEG2_L1: + case coding_MPEG2_L2: + case coding_MPEG2_L3: + case coding_MPEG25_L1: + case coding_MPEG25_L2: + case coding_MPEG25_L3: + decode_mpeg( + &vgmstream->ch[0], + vgmstream->codec_data, + buffer+samples_written*vgmstream->channels,samples_to_do, + vgmstream->channels); + break; +#endif +#ifdef VGM_USE_G7221 + case coding_G7221: + case coding_G7221C: + for (chan=0;chanchannels;chan++) { + decode_g7221(vgmstream, + buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels, + samples_to_do, + chan); + } + break; +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: + for (chan=0;chanchannels;chan++) { + decode_at3plus(vgmstream, + buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels, + samples_to_do, + chan); + } + break; +#endif + case coding_ACM: + /* handled in its own layout, here to quiet compiler */ + break; + case coding_NWA0: + case coding_NWA1: + case coding_NWA2: + case coding_NWA3: + case coding_NWA4: + case coding_NWA5: + decode_nwa(((nwa_codec_data*)vgmstream->codec_data)->nwa, + buffer+samples_written*vgmstream->channels, + samples_to_do + ); + break; + case coding_MSADPCM: + if (vgmstream->channels == 2) { + decode_msadpcm_stereo(vgmstream, + buffer+samples_written*vgmstream->channels, + vgmstream->samples_into_block, + samples_to_do); + } + else if (vgmstream->channels == 1) + { + decode_msadpcm_mono(vgmstream, + buffer+samples_written*vgmstream->channels, + vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_AICA: + for (chan=0;chanchannels;chan++) { + decode_aica(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_NDS_PROCYON: + for (chan=0;chanchannels;chan++) { + decode_nds_procyon(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_L5_555: + for (chan=0;chanchannels;chan++) { + decode_l5_555(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + + break; + case coding_SASSC: + for (chan=0;chanchannels;chan++) { + decode_SASSC(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + + break; + case coding_LSF: + for (chan=0;chanchannels;chan++) { + decode_lsf(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; + case coding_MTAF: + for (chan=0;chanchannels;chan++) { + decode_mtaf(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels, vgmstream->samples_into_block, samples_to_do, + chan, vgmstream->channels); + } + break; + } +} + +int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream) { + int samples_to_do; + int samples_left_this_block; + + samples_left_this_block = samples_this_block - vgmstream->samples_into_block; + samples_to_do = samples_left_this_block; + + /* fun loopy crap */ + /* Why did I think this would be any simpler? */ + if (vgmstream->loop_flag) { + /* are we going to hit the loop end during this block? */ + if (vgmstream->current_sample+samples_left_this_block > vgmstream->loop_end_sample) { + /* only do to just before it */ + samples_to_do = vgmstream->loop_end_sample-vgmstream->current_sample; + } + + /* are we going to hit the loop start during this block? */ + if (!vgmstream->hit_loop && vgmstream->current_sample+samples_left_this_block > vgmstream->loop_start_sample) { + /* only do to just before it */ + samples_to_do = vgmstream->loop_start_sample-vgmstream->current_sample; + } + + } + + /* if it's a framed encoding don't do more than one frame */ + if (samples_per_frame>1 && (vgmstream->samples_into_block%samples_per_frame)+samples_to_do>samples_per_frame) samples_to_do=samples_per_frame-(vgmstream->samples_into_block%samples_per_frame); + + return samples_to_do; +} + +/* return 1 if we just looped */ +int vgmstream_do_loop(VGMSTREAM * vgmstream) { +/* if (vgmstream->loop_flag) {*/ + /* is this the loop end? */ + if (vgmstream->current_sample==vgmstream->loop_end_sample) { + /* against everything I hold sacred, preserve adpcm + * history through loop for certain types */ + if (vgmstream->meta_type == meta_DSP_STD || + vgmstream->meta_type == meta_DSP_RS03 || + vgmstream->meta_type == meta_DSP_CSTR || + vgmstream->coding_type == coding_PSX || + vgmstream->coding_type == coding_invert_PSX || + vgmstream->coding_type == coding_PSX_badflags) { + int i; + for (i=0;ichannels;i++) { + vgmstream->loop_ch[i].adpcm_history1_16 = vgmstream->ch[i].adpcm_history1_16; + vgmstream->loop_ch[i].adpcm_history2_16 = vgmstream->ch[i].adpcm_history2_16; + vgmstream->loop_ch[i].adpcm_history1_32 = vgmstream->ch[i].adpcm_history1_32; + vgmstream->loop_ch[i].adpcm_history2_32 = vgmstream->ch[i].adpcm_history2_32; + } + } +#ifdef DEBUG + { + int i; + for (i=0;ichannels;i++) { + fprintf(stderr,"ch%d hist: %04x %04x loop hist: %04x %04x\n",i, + vgmstream->ch[i].adpcm_history1_16,vgmstream->ch[i].adpcm_history2_16, + vgmstream->loop_ch[i].adpcm_history1_16,vgmstream->loop_ch[i].adpcm_history2_16); + fprintf(stderr,"ch%d offset: %x loop offset: %x\n",i, + vgmstream->ch[i].offset, + vgmstream->loop_ch[i].offset); + } + } +#endif + +#ifdef VGM_USE_VORBIS + if (vgmstream->coding_type==coding_ogg_vorbis) { + ogg_vorbis_codec_data *data = + (ogg_vorbis_codec_data *)(vgmstream->codec_data); + OggVorbis_File *ogg_vorbis_file = &(data->ogg_vorbis_file); + + ov_pcm_seek_lap(ogg_vorbis_file, vgmstream->loop_sample); + } +#endif +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + if (vgmstream->coding_type==coding_MP4_AAC) { + mp4_aac_codec_data *data = (mp4_aac_codec_data *)(vgmstream->codec_data); + data->sampleId = 0; + data->sample_ptr = data->samples_per_frame; + data->samples_discard = vgmstream->loop_sample; + } +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + if (vgmstream->coding_type==coding_AT3plus) { + int blocks_to_skip = vgmstream->loop_sample / 2048; + int samples_to_discard = vgmstream->loop_sample % 2048; + maiatrac3plus_codec_data *data = (maiatrac3plus_codec_data *)(vgmstream->codec_data); + vgmstream->loop_ch[0].offset = + vgmstream->loop_ch[0].channel_start_offset + + vgmstream->interleave_block_size * blocks_to_skip; + data->samples_discard = samples_to_discard; + } +#endif +#ifdef VGM_USE_MPEG + /* won't work for fake MPEG */ + if (vgmstream->layout_type==layout_mpeg) { + off_t input_offset; + mpeg_codec_data *data = vgmstream->codec_data; + + mpg123_feedseek(data->m,vgmstream->loop_sample, + SEEK_SET,&input_offset); + vgmstream->loop_ch[0].offset = + vgmstream->loop_ch[0].channel_start_offset + input_offset; + data->buffer_full = data->buffer_used = 0; + } +#endif + + if (vgmstream->coding_type == coding_NWA0 || + vgmstream->coding_type == coding_NWA1 || + vgmstream->coding_type == coding_NWA2 || + vgmstream->coding_type == coding_NWA3 || + vgmstream->coding_type == coding_NWA4 || + vgmstream->coding_type == coding_NWA5) + { + nwa_codec_data *data = vgmstream->codec_data; + + seek_nwa(data->nwa, vgmstream->loop_sample); + } + + /* restore! */ + memcpy(vgmstream->ch,vgmstream->loop_ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); + vgmstream->current_sample=vgmstream->loop_sample; + vgmstream->samples_into_block=vgmstream->loop_samples_into_block; + vgmstream->current_block_size=vgmstream->loop_block_size; + vgmstream->current_block_offset=vgmstream->loop_block_offset; + vgmstream->next_block_offset=vgmstream->loop_next_block_offset; + + return 1; + } + + + /* is this the loop start? */ + if (!vgmstream->hit_loop && vgmstream->current_sample==vgmstream->loop_start_sample) { + /* save! */ + memcpy(vgmstream->loop_ch,vgmstream->ch,sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); + + vgmstream->loop_sample=vgmstream->current_sample; + vgmstream->loop_samples_into_block=vgmstream->samples_into_block; + vgmstream->loop_block_size=vgmstream->current_block_size; + vgmstream->loop_block_offset=vgmstream->current_block_offset; + vgmstream->loop_next_block_offset=vgmstream->next_block_offset; + vgmstream->hit_loop=1; + } + /*}*/ + return 0; +} + +/* build a descriptive string */ +void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { +#define TEMPSIZE 256 + char temp[TEMPSIZE]; + + if (!vgmstream) { + snprintf(temp,TEMPSIZE,"NULL VGMSTREAM"); + concatn(length,desc,temp); + return; + } + + snprintf(temp,TEMPSIZE,"sample rate %d Hz\n" + "channels: %d\n", + vgmstream->sample_rate,vgmstream->channels); + concatn(length,desc,temp); + + if (vgmstream->loop_flag) { + snprintf(temp,TEMPSIZE,"loop start: %d samples (%.4f seconds)\n" + "loop end: %d samples (%.4f seconds)\n", + vgmstream->loop_start_sample, + (double)vgmstream->loop_start_sample/vgmstream->sample_rate, + vgmstream->loop_end_sample, + (double)vgmstream->loop_end_sample/vgmstream->sample_rate); + concatn(length,desc,temp); + } + + snprintf(temp,TEMPSIZE,"stream total samples: %d (%.4f seconds)\n", + vgmstream->num_samples, + (double)vgmstream->num_samples/vgmstream->sample_rate); + concatn(length,desc,temp); + + snprintf(temp,TEMPSIZE,"encoding: "); + concatn(length,desc,temp); + + switch (vgmstream->coding_type) { + case coding_PCM16BE: + snprintf(temp,TEMPSIZE,"Big Endian 16-bit PCM"); + break; + case coding_PCM16LE: + snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM"); + break; + case coding_PCM16LE_int: + snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM with 2 byte interleave"); + break; + case coding_PCM16LE_XOR_int: + snprintf(temp,TEMPSIZE,"Little Endian 16-bit PCM with 2 byte interleave and XOR obfuscation"); + break; + case coding_PCM8: + snprintf(temp,TEMPSIZE,"8-bit PCM"); + break; + case coding_PCM8_U: + snprintf(temp,TEMPSIZE,"8-bit unsigned PCM"); + break; + case coding_PCM8_U_int: + snprintf(temp,TEMPSIZE,"8-bit unsigned PCM with 1 byte interleave"); + break; + case coding_PCM8_int: + snprintf(temp,TEMPSIZE,"8-bit PCM with 1 byte interleave"); + break; + case coding_PCM8_SB_int: + snprintf(temp,TEMPSIZE,"8-bit PCM with sign bit, 1 byte interleave"); + break; + case coding_NGC_DSP: + snprintf(temp,TEMPSIZE,"Gamecube \"DSP\" 4-bit ADPCM"); + break; + case coding_CRI_ADX: + snprintf(temp,TEMPSIZE,"CRI ADX 4-bit ADPCM"); + break; + case coding_CRI_ADX_enc_8: + snprintf(temp,TEMPSIZE,"encrypted (type 8) CRI ADX 4-bit ADPCM"); + break; + case coding_CRI_ADX_enc_9: + snprintf(temp,TEMPSIZE,"encrypted (type 9) CRI ADX 4-bit ADPCM"); + break; + case coding_NDS_IMA: + snprintf(temp,TEMPSIZE,"NDS-style 4-bit IMA ADPCM"); + break; + case coding_DAT4_IMA: + snprintf(temp,TEMPSIZE,"Eurocom DAT4 4-bit IMA ADPCM"); + break; + case coding_NGC_DTK: + snprintf(temp,TEMPSIZE,"Gamecube \"ADP\"/\"DTK\" 4-bit ADPCM"); + break; + case coding_G721: + snprintf(temp,TEMPSIZE,"CCITT G.721 4-bit ADPCM"); + break; + case coding_NGC_AFC: + snprintf(temp,TEMPSIZE,"Gamecube \"AFC\" 4-bit ADPCM"); + break; + case coding_PSX: + snprintf(temp,TEMPSIZE,"Playstation 4-bit ADPCM"); + break; + case coding_PSX_badflags: + snprintf(temp,TEMPSIZE,"Playstation 4-bit ADPCM with bad flags"); + break; + case coding_invert_PSX: + snprintf(temp,TEMPSIZE,"BMDX \"encrypted\" Playstation 4-bit ADPCM"); + break; + case coding_FFXI: + snprintf(temp,TEMPSIZE,"FFXI Playstation-ish 4-bit ADPCM"); + break; + case coding_BAF_ADPCM: + snprintf(temp,TEMPSIZE,"Bizarre Creations Playstation-ish 4-bit ADPCM"); + break; + case coding_XA: + snprintf(temp,TEMPSIZE,"CD-ROM XA 4-bit ADPCM"); + break; + case coding_XBOX: + snprintf(temp,TEMPSIZE,"XBOX 4-bit IMA ADPCM"); + break; + case coding_INT_XBOX: + snprintf(temp,TEMPSIZE,"XBOX Interleaved 4-bit IMA ADPCM"); + break; + case coding_EAXA: + snprintf(temp,TEMPSIZE,"Electronic Arts XA Based 4-bit ADPCM"); + break; + case coding_EA_ADPCM: + snprintf(temp,TEMPSIZE,"Electronic Arts XA Based (R1) 4-bit ADPCM"); + break; +#ifdef VGM_USE_VORBIS + case coding_ogg_vorbis: + snprintf(temp,TEMPSIZE,"Vorbis"); + break; +#endif + case coding_SDX2: + snprintf(temp,TEMPSIZE,"Squareroot-delta-exact (SDX2) 8-bit DPCM"); + break; + case coding_SDX2_int: + snprintf(temp,TEMPSIZE,"Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"); + break; + case coding_CBD2: + snprintf(temp,TEMPSIZE,"Cuberoot-delta-exact (CBD2) 8-bit DPCM"); + break; + case coding_CBD2_int: + snprintf(temp,TEMPSIZE,"Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"); + break; + case coding_DVI_IMA: + snprintf(temp,TEMPSIZE,"Intel DVI 4-bit IMA ADPCM"); + break; + case coding_INT_DVI_IMA: + snprintf(temp,TEMPSIZE,"Interleaved Intel DVI 4-bit IMA ADPCM"); + break; + case coding_EACS_IMA: + snprintf(temp,TEMPSIZE,"EACS 4-bit IMA ADPCM"); + break; + case coding_MAXIS_ADPCM: + snprintf(temp,TEMPSIZE,"Maxis XA (EA ADPCM Variant)"); + break; + case coding_INT_IMA: + snprintf(temp,TEMPSIZE,"Interleaved 4-bit IMA ADPCM"); + break; + case coding_IMA: + snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM"); + break; + case coding_MS_IMA: + snprintf(temp,TEMPSIZE,"Microsoft 4-bit IMA ADPCM"); + break; + case coding_RAD_IMA: + snprintf(temp,TEMPSIZE,"\"Radical\" 4-bit IMA ADPCM"); + break; + case coding_RAD_IMA_mono: + snprintf(temp,TEMPSIZE,"\"Radical\" 4-bit IMA ADPCM (mono)"); + break; + case coding_APPLE_IMA4: + snprintf(temp,TEMPSIZE,"Apple Quicktime 4-bit IMA ADPCM"); + break; + case coding_SNDS_IMA: + snprintf(temp,TEMPSIZE,"Heavy Iron .snds 4-bit IMA ADPCM"); + break; + case coding_WS: + snprintf(temp,TEMPSIZE,"Westwood Studios DPCM"); + break; +#ifdef VGM_USE_MPEG + case coding_fake_MPEG2_L2: + snprintf(temp,TEMPSIZE,"MPEG-2 Layer II Audio"); + break; + case coding_MPEG1_L1: + snprintf(temp,TEMPSIZE,"MPEG-1 Layer I Audio"); + break; + case coding_MPEG1_L2: + snprintf(temp,TEMPSIZE,"MPEG-1 Layer II Audio"); + break; + case coding_MPEG1_L3: + snprintf(temp,TEMPSIZE,"MPEG-1 Layer III Audio (MP3)"); + break; + case coding_MPEG2_L1: + snprintf(temp,TEMPSIZE,"MPEG-2 Layer I Audio"); + break; + case coding_MPEG2_L2: + snprintf(temp,TEMPSIZE,"MPEG-2 Layer II Audio"); + break; + case coding_MPEG2_L3: + snprintf(temp,TEMPSIZE,"MPEG-2 Layer III Audio (MP3)"); + break; + case coding_MPEG25_L1: + snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer I Audio"); + break; + case coding_MPEG25_L2: + snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer II Audio"); + break; + case coding_MPEG25_L3: + snprintf(temp,TEMPSIZE,"MPEG-2.5 Layer III Audio (MP3)"); + break; +#endif +#ifdef VGM_USE_G7221 + case coding_G7221: + snprintf(temp,TEMPSIZE,"ITU G.722.1 (Polycom Siren 7)"); + break; + case coding_G7221C: + snprintf(temp,TEMPSIZE,"ITU G.722.1 annex C (Polycom Siren 14)"); + break; +#endif +#ifdef VGM_USE_MAIATRAC3PLUS + case coding_AT3plus: + snprintf(temp,TEMPSIZE,"ATRAC3plus"); + break; +#endif + case coding_ACM: + snprintf(temp,TEMPSIZE,"InterPlay ACM"); + break; + case coding_NWA0: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 0"); + break; + case coding_NWA1: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 1"); + break; + case coding_NWA2: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 2"); + break; + case coding_NWA3: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 3"); + break; + case coding_NWA4: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 4"); + break; + case coding_NWA5: + snprintf(temp,TEMPSIZE,"NWA DPCM Level 5"); + break; + case coding_MSADPCM: + snprintf(temp,TEMPSIZE,"Microsoft 4-bit ADPCM"); + break; + case coding_AICA: + snprintf(temp,TEMPSIZE,"Yamaha AICA 4-bit ADPCM"); + break; + case coding_NDS_PROCYON: + snprintf(temp,TEMPSIZE,"Procyon Studio Digital Sound Elements NDS 4-bit APDCM"); + break; + case coding_L5_555: + snprintf(temp,TEMPSIZE,"Level-5 0x555 4-bit ADPCM"); + break; + case coding_SASSC: + snprintf(temp,TEMPSIZE,"Activision / EXAKT SASSC 8-bit DPCM"); + break; + case coding_LSF: + snprintf(temp,TEMPSIZE,"lsf 4-bit ADPCM"); + break; + case coding_MTAF: + snprintf(temp,TEMPSIZE,"Konami MTAF 4-bit ADPCM"); + break; + default: + snprintf(temp,TEMPSIZE,"CANNOT DECODE"); + } + concatn(length,desc,temp); + + snprintf(temp,TEMPSIZE,"\nlayout: "); + concatn(length,desc,temp); + + switch (vgmstream->layout_type) { + case layout_none: + snprintf(temp,TEMPSIZE,"flat (no layout)"); + break; + case layout_interleave: + snprintf(temp,TEMPSIZE,"interleave"); + break; + case layout_interleave_shortblock: + snprintf(temp,TEMPSIZE,"interleave with short last block"); + break; + case layout_interleave_byte: + snprintf(temp,TEMPSIZE,"sub-frame interleave"); + break; + case layout_dtk_interleave: + snprintf(temp,TEMPSIZE,"ADP/DTK nibble interleave"); + break; + case layout_mxch_blocked: + snprintf(temp,TEMPSIZE,"MxCh blocked"); + break; + case layout_ast_blocked: + snprintf(temp,TEMPSIZE,"AST blocked"); + break; + case layout_halpst_blocked: + snprintf(temp,TEMPSIZE,"HALPST blocked"); + break; + case layout_xa_blocked: + snprintf(temp,TEMPSIZE,"CD-ROM XA"); + break; + case layout_ea_blocked: + snprintf(temp,TEMPSIZE,"Electronic Arts Audio Blocks"); + break; + case layout_eacs_blocked: + snprintf(temp,TEMPSIZE,"Electronic Arts (Old Version) Audio Blocks"); + break; + case layout_caf_blocked: + snprintf(temp,TEMPSIZE,"CAF blocked"); + break; + case layout_wsi_blocked: + snprintf(temp,TEMPSIZE,".wsi blocked"); + break; + case layout_xvas_blocked: + snprintf(temp,TEMPSIZE,".xvas blocked"); + break; +#ifdef VGM_USE_VORBIS + case layout_ogg_vorbis: + snprintf(temp,TEMPSIZE,"Ogg"); + break; +#endif + case layout_str_snds_blocked: + snprintf(temp,TEMPSIZE,".str SNDS blocked"); + break; + case layout_ws_aud_blocked: + snprintf(temp,TEMPSIZE,"Westwood Studios .aud blocked"); + break; + case layout_matx_blocked: + snprintf(temp,TEMPSIZE,"Matrix .matx blocked"); + break; + case layout_de2_blocked: + snprintf(temp,TEMPSIZE,"de2 blocked"); + break; + case layout_vs_blocked: + snprintf(temp,TEMPSIZE,"vs blocked"); + break; + case layout_emff_ps2_blocked: + snprintf(temp,TEMPSIZE,"EMFF (PS2) blocked"); + break; + case layout_emff_ngc_blocked: + snprintf(temp,TEMPSIZE,"EMFF (NGC/WII) blocked"); + break; + case layout_gsb_blocked: + snprintf(temp,TEMPSIZE,"GSB blocked"); + break; + case layout_thp_blocked: + snprintf(temp,TEMPSIZE,"THP Movie Audio blocked"); + break; + case layout_filp_blocked: + snprintf(temp,TEMPSIZE,"FILp blocked"); + break; + case layout_psx_mgav_blocked: + snprintf(temp,TEMPSIZE,"MGAV blocked"); + break; + case layout_ps2_adm_blocked: + snprintf(temp,TEMPSIZE,"ADM blocked"); + break; + case layout_dsp_bdsp_blocked: + snprintf(temp,TEMPSIZE,"DSP blocked"); + break; +#ifdef VGM_USE_MPEG + case layout_fake_mpeg: + snprintf(temp,TEMPSIZE,"MPEG Audio stream with incorrect frame headers"); + break; + case layout_mpeg: + snprintf(temp,TEMPSIZE,"MPEG Audio stream"); + break; +#endif + case layout_acm: + snprintf(temp,TEMPSIZE,"ACM blocked"); + break; + case layout_mus_acm: + snprintf(temp,TEMPSIZE,"multiple ACM files, ACM blocked"); + break; + case layout_aix: + snprintf(temp,TEMPSIZE,"AIX interleave, internally 18-byte interleaved"); + break; + case layout_aax: + snprintf(temp,TEMPSIZE,"AAX blocked, 18-byte interleaved"); + break; + case layout_ivaud_blocked: + snprintf(temp,TEMPSIZE,"GTA IV blocked"); + break; + case layout_ps2_iab_blocked: + snprintf(temp,TEMPSIZE,"IAB blocked"); + break; + case layout_ps2_strlr_blocked: + snprintf(temp,TEMPSIZE,"The Bouncer STR blocked"); + break; + case layout_tra_blocked: + snprintf(temp,TEMPSIZE,"TRA blocked"); + break; + case layout_scd_int: + snprintf(temp,TEMPSIZE,"SCD multistream interleave"); + break; + default: + snprintf(temp,TEMPSIZE,"INCONCEIVABLE"); + } + concatn(length,desc,temp); + + snprintf(temp,TEMPSIZE,"\n"); + concatn(length,desc,temp); + + if (vgmstream->layout_type == layout_interleave || vgmstream->layout_type == layout_interleave_shortblock || vgmstream->layout_type == layout_interleave_byte) { + snprintf(temp,TEMPSIZE,"interleave: %#x bytes\n", + (int32_t)vgmstream->interleave_block_size); + concatn(length,desc,temp); + + if (vgmstream->layout_type == layout_interleave_shortblock) { + snprintf(temp,TEMPSIZE,"last block interleave: %#x bytes\n", + (int32_t)vgmstream->interleave_smallblock_size); + concatn(length,desc,temp); + } + } + + snprintf(temp,TEMPSIZE,"metadata from: "); + concatn(length,desc,temp); + + switch (vgmstream->meta_type) { + case meta_RSTM: + snprintf(temp,TEMPSIZE,"Nintendo RSTM header"); + break; + case meta_STRM: + snprintf(temp,TEMPSIZE,"Nintendo STRM header"); + break; + case meta_ADX_03: + snprintf(temp,TEMPSIZE,"CRI ADX header type 03"); + break; + case meta_ADX_04: + snprintf(temp,TEMPSIZE,"CRI ADX header type 04"); + break; + case meta_ADX_05: + snprintf(temp,TEMPSIZE,"CRI ADX header type 05"); + break; + case meta_AIX: + snprintf(temp,TEMPSIZE,"CRI AIX header"); + break; + case meta_AAX: + snprintf(temp,TEMPSIZE,"CRI AAX header"); + break; + case meta_UTF_DSP: + snprintf(temp,TEMPSIZE,"CRI ADPCM_WII header"); + break; + case meta_DSP_AGSC: + snprintf(temp,TEMPSIZE,"Retro Studios AGSC header"); + break; + case meta_NGC_ADPDTK: + snprintf(temp,TEMPSIZE,"assumed Nintendo ADP by .adp extension and valid first frame"); + break; + case meta_RSF: + snprintf(temp,TEMPSIZE,"assumed Retro Studios RSF by .rsf extension and valid first bytes"); + break; + case meta_AFC: + snprintf(temp,TEMPSIZE,"Nintendo AFC header"); + break; + case meta_AST: + snprintf(temp,TEMPSIZE,"Nintendo AST header"); + break; + case meta_HALPST: + snprintf(temp,TEMPSIZE,"HAL Laboratory HALPST header"); + break; + case meta_DSP_RS03: + snprintf(temp,TEMPSIZE,"Retro Studios RS03 header"); + break; + case meta_DSP_STD: + snprintf(temp,TEMPSIZE,"Standard Nintendo DSP header"); + break; + case meta_DSP_CSTR: + snprintf(temp,TEMPSIZE,"Namco Cstr header"); + break; + case meta_GCSW: + snprintf(temp,TEMPSIZE,"GCSW header"); + break; + case meta_PS2_SShd: + snprintf(temp,TEMPSIZE,"SShd header"); + break; + case meta_PS2_NPSF: + snprintf(temp,TEMPSIZE,"Namco Production Sound File (NPSF) header"); + break; + case meta_RWSD: + snprintf(temp,TEMPSIZE,"Nintendo RWSD header (single stream)"); + break; + case meta_RWAR: + snprintf(temp,TEMPSIZE,"Nintendo RWAR header (single RWAV stream)"); + break; + case meta_RWAV: + snprintf(temp,TEMPSIZE,"Nintendo RWAV header"); + break; + case meta_CWAV: + snprintf(temp,TEMPSIZE,"Nintendo CWAV header"); + break; + case meta_PSX_XA: + snprintf(temp,TEMPSIZE,"RIFF/CDXA header"); + break; + case meta_PS2_RXW: + snprintf(temp,TEMPSIZE,"RXWS header)"); + break; + case meta_PS2_RAW: + snprintf(temp,TEMPSIZE,"assumed RAW Interleaved PCM by .int extension"); + break; + case meta_PS2_OMU: + snprintf(temp,TEMPSIZE,"Alter Echo OMU Header"); + break; + case meta_DSP_STM: + snprintf(temp,TEMPSIZE,"Nintendo STM header"); + break; + case meta_PS2_EXST: + snprintf(temp,TEMPSIZE,"EXST header"); + break; + case meta_PS2_SVAG: + snprintf(temp,TEMPSIZE,"Konami SVAG header"); + break; + case meta_PS2_MIB: + snprintf(temp,TEMPSIZE,"assumed MIB Interleaved file by .mib extension"); + break; + case meta_PS2_MIB_MIH: + snprintf(temp,TEMPSIZE,"assumed MIB with MIH Info Header file by .mib+.mih extension"); + break; + case meta_DSP_MPDSP: + snprintf(temp,TEMPSIZE,"Single DSP header stereo by .mpdsp extension"); + break; + case meta_PS2_MIC: + snprintf(temp,TEMPSIZE,"assume KOEI MIC file by .mic extension"); + break; + case meta_DSP_JETTERS: + snprintf(temp,TEMPSIZE,"Double DSP header stereo by _lr.dsp extension"); + break; + case meta_DSP_MSS: + snprintf(temp,TEMPSIZE,"Double DSP header stereo by .mss extension"); + break; + case meta_DSP_GCM: + snprintf(temp,TEMPSIZE,"Double DSP header stereo by .gcm extension"); + break; + case meta_DSP_WII_IDSP: + snprintf(temp,TEMPSIZE,"Wii IDSP Double DSP header"); + break; + case meta_RSTM_SPM: + snprintf(temp,TEMPSIZE,"Nintendo RSTM header and .brstmspm extension"); + break; + case meta_RAW: + snprintf(temp,TEMPSIZE,"assumed RAW PCM file by .raw extension"); + break; + case meta_PS2_VAGi: + snprintf(temp,TEMPSIZE,"Sony VAG Interleaved header (VAGi)"); + break; + case meta_PS2_VAGp: + snprintf(temp,TEMPSIZE,"Sony VAG Mono header (VAGp)"); + break; + case meta_PS2_VAGs: + snprintf(temp,TEMPSIZE,"Sony VAG Stereo header (VAGp)"); + break; + case meta_PS2_VAGm: + snprintf(temp,TEMPSIZE,"Sony VAG Mono header (VAGm)"); + break; + case meta_PS2_pGAV: + snprintf(temp,TEMPSIZE,"Sony VAG Stereo Little Endian header (pGAV)"); + break; + case meta_PSX_GMS: + snprintf(temp,TEMPSIZE,"assumed Grandia GMS file by .gms extension"); + break; + case meta_PS2_STR: + snprintf(temp,TEMPSIZE,"assumed STR + STH File by .str & .sth extension"); + break; + case meta_PS2_ILD: + snprintf(temp,TEMPSIZE,"ILD header"); + break; + case meta_PS2_PNB: + snprintf(temp,TEMPSIZE,"assumed PNB (PsychoNauts Bgm File) by .pnb extension"); + break; + case meta_XBOX_WAVM: + snprintf(temp,TEMPSIZE,"assumed Xbox WAVM file by .wavm extension"); + break; + case meta_XBOX_RIFF: + snprintf(temp,TEMPSIZE,"Xbox RIFF/WAVE file with 0x0069 Codec ID"); + break; + case meta_DSP_STR: + snprintf(temp,TEMPSIZE,"assumed Conan Gamecube STR File by .str extension"); + break; + case meta_EAXA_R2: + snprintf(temp,TEMPSIZE,"Electronic Arts XA R2"); + break; + case meta_EAXA_R3: + snprintf(temp,TEMPSIZE,"Electronic Arts XA R3"); + break; + case meta_EA_ADPCM: + snprintf(temp,TEMPSIZE,"Electronic Arts XA R1"); + break; + case meta_EA_IMA: + snprintf(temp,TEMPSIZE,"Electronic Arts container with IMA blocks"); + break; + case meta_EAXA_PSX: + snprintf(temp,TEMPSIZE,"Electronic Arts With PSX ADPCM"); + break; + case meta_EA_PCM: + snprintf(temp,TEMPSIZE,"Electronic Arts With PCM"); + break; + case meta_CFN: + snprintf(temp,TEMPSIZE,"Namco CAF Header"); + break; + case meta_PS2_VPK: + snprintf(temp,TEMPSIZE,"VPK Header"); + break; + case meta_GENH: + snprintf(temp,TEMPSIZE,"GENH Generic Header"); + break; +#ifdef VGM_USE_VORBIS + case meta_ogg_vorbis: + snprintf(temp,TEMPSIZE,"Ogg Vorbis"); + break; + case meta_OGG_SLI: + snprintf(temp,TEMPSIZE,"Ogg Vorbis with .sli (start,length) for looping"); + break; + case meta_OGG_SLI2: + snprintf(temp,TEMPSIZE,"Ogg Vorbis with .sli (from,to) for looping"); + break; + case meta_OGG_SFL: + snprintf(temp,TEMPSIZE,"Ogg Vorbis with SFPL for looping"); + break; + case meta_um3_ogg: + snprintf(temp,TEMPSIZE,"Ogg Vorbis, Ultramarine3 \"encryption\""); + break; + case meta_KOVS_ogg: + snprintf(temp,TEMPSIZE,"Ogg Vorbis, KOVS header"); + break; + case meta_psych_ogg: + snprintf(temp,TEMPSIZE,"Ogg Vorbis, Psychic Software obfuscation"); + break; +#endif + case meta_DSP_SADB: + snprintf(temp,TEMPSIZE,"sadb header"); + break; + case meta_SADL: + snprintf(temp,TEMPSIZE,"sadl header"); + break; + case meta_PS2_BMDX: + snprintf(temp,TEMPSIZE,"Beatmania .bmdx header"); + break; + case meta_DSP_WSI: + snprintf(temp,TEMPSIZE,".wsi header"); + break; + case meta_AIFC: + snprintf(temp,TEMPSIZE,"Audio Interchange File Format AIFF-C"); + break; + case meta_AIFF: + snprintf(temp,TEMPSIZE,"Audio Interchange File Format"); + break; + case meta_STR_SNDS: + snprintf(temp,TEMPSIZE,".str SNDS SHDR chunk"); + break; + case meta_WS_AUD: + snprintf(temp,TEMPSIZE,"Westwood Studios .aud header"); + break; + case meta_WS_AUD_old: + snprintf(temp,TEMPSIZE,"Westwood Studios .aud (old) header"); + break; +#ifdef VGM_USE_MPEG + case meta_AHX: + snprintf(temp,TEMPSIZE,"CRI AHX header"); + break; +#endif + case meta_PS2_IVB: + snprintf(temp,TEMPSIZE,"IVB/BVII header"); + break; + case meta_PS2_SVS: + snprintf(temp,TEMPSIZE,"Square SVS header"); + break; + case meta_RIFF_WAVE: + snprintf(temp,TEMPSIZE,"RIFF WAVE header"); + break; + case meta_RIFF_WAVE_POS: + snprintf(temp,TEMPSIZE,"RIFF WAVE header and .pos for looping"); + break; + case meta_NWA: + snprintf(temp,TEMPSIZE,"Visual Art's NWA header"); + break; + case meta_NWA_NWAINFOINI: + snprintf(temp,TEMPSIZE,"Visual Art's NWA header and NWAINFO.INI for looping"); + break; + case meta_NWA_GAMEEXEINI: + snprintf(temp,TEMPSIZE,"Visual Art's NWA header and Gameexe.ini for looping"); + break; + case meta_XSS: + snprintf(temp,TEMPSIZE,"Dino Crisis 3 XSS File"); + break; + case meta_HGC1: + snprintf(temp,TEMPSIZE,"Knights of the Temple 2 hgC1 Header"); + break; + case meta_AUS: + snprintf(temp,TEMPSIZE,"Capcom AUS Header"); + break; + case meta_RWS: + snprintf(temp,TEMPSIZE,"RWS Header"); + break; + case meta_EACS_PC: + snprintf(temp,TEMPSIZE,"EACS Header (PC)"); + break; + case meta_EACS_PSX: + snprintf(temp,TEMPSIZE,"EACS Header (PSX)"); + break; + case meta_EACS_SAT: + snprintf(temp,TEMPSIZE,"EACS Header (SATURN)"); + break; + case meta_SL3: + snprintf(temp,TEMPSIZE,"SL3 Header"); + break; + case meta_FSB1: + snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB1) Header"); + break; + case meta_FSB3_0: + snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB3.0) Header"); + break; + case meta_FSB3_1: + snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB3.1) Header"); + break; + case meta_FSB4: + snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB4) Header"); + break; + case meta_FSB4_WAV: + snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB4) with additional 'WAV' Header"); + break; + case meta_RWX: + snprintf(temp,TEMPSIZE,"RWX Header"); + break; + case meta_XWB: + snprintf(temp,TEMPSIZE,"XWB WBND Header"); + break; + case meta_XA30: + snprintf(temp,TEMPSIZE,"XA30 Header"); + break; + case meta_MUSC: + snprintf(temp,TEMPSIZE,"MUSC Header"); + break; + case meta_MUSX_V004: + snprintf(temp,TEMPSIZE,"MUSX / Version 004 Header"); + break; + case meta_MUSX_V005: + snprintf(temp,TEMPSIZE,"MUSX / Version 005 Header"); + break; + case meta_MUSX_V006: + snprintf(temp,TEMPSIZE,"MUSX / Version 006 Header"); + break; + case meta_MUSX_V010: + snprintf(temp,TEMPSIZE,"MUSX / Version 010 Header"); + break; + case meta_MUSX_V201: + snprintf(temp,TEMPSIZE,"MUSX / Version 201 Header"); + break; + case meta_LEG: + snprintf(temp,TEMPSIZE,"Legaia 2 - Duel Saga LEG Header"); + break; + case meta_FILP: + snprintf(temp,TEMPSIZE,"Bio Hazard - Gun Survivor FILp Header"); + break; + case meta_IKM: + snprintf(temp,TEMPSIZE,"Zwei!! IKM Header"); + break; + case meta_SFS: + snprintf(temp,TEMPSIZE,"Baroque SFS Header"); + break; + case meta_DVI: + snprintf(temp,TEMPSIZE,"DVI Header"); + break; + case meta_KCEY: + snprintf(temp,TEMPSIZE,"KCEYCOMP Header"); + break; + case meta_BG00: + snprintf(temp,TEMPSIZE,"Falcom BG00 Header"); + break; + case meta_PS2_RSTM: + snprintf(temp,TEMPSIZE,"Rockstar Games RSTM Header"); + break; + case meta_ACM: + snprintf(temp,TEMPSIZE,"InterPlay ACM Header"); + break; + case meta_MUS_ACM: + snprintf(temp,TEMPSIZE,"MUS playlist and multiple InterPlay ACM Headered files"); + break; + case meta_PS2_KCES: + snprintf(temp,TEMPSIZE,"Konami KCES Header"); + break; + case meta_PS2_DXH: + snprintf(temp,TEMPSIZE,"Tokobot Plus DXH Header"); + break; + case meta_PS2_PSH: + snprintf(temp,TEMPSIZE,"Dawn of Mana - Seiken Densetsu 4 PSH Header"); + break; + case meta_RIFF_WAVE_labl_Marker: + snprintf(temp,TEMPSIZE,"RIFF WAVE header with loop markers"); + break; + case meta_RIFF_WAVE_smpl: + snprintf(temp,TEMPSIZE,"RIFF WAVE header with sample looping info"); + break; + case meta_RIFX_WAVE: + snprintf(temp,TEMPSIZE,"RIFX WAVE header"); + break; + case meta_RIFX_WAVE_smpl: + snprintf(temp,TEMPSIZE,"RIFX WAVE header with sample looping info"); + break; + case meta_XNBm: + snprintf(temp,TEMPSIZE,"XNBm header"); + break; + case meta_PCM_SCD: + snprintf(temp,TEMPSIZE,"PCM file with custom header (SCD)"); + break; + case meta_PCM_PS2: + snprintf(temp,TEMPSIZE,"PCM file with custom header (PS2)"); + break; + case meta_PS2_RKV: + snprintf(temp,TEMPSIZE,"Legacy of Kain - Blood Omen 2 RKV Header"); + break; + case meta_PS2_PSW: + snprintf(temp,TEMPSIZE,"Rayman Raving Rabbids Riff Container File"); + break; + case meta_PS2_VAS: + snprintf(temp,TEMPSIZE,"Pro Baseball Spirits 5 VAS Header"); + break; + case meta_PS2_TEC: + snprintf(temp,TEMPSIZE,"assumed TECMO badflagged stream by .tec extension"); + break; + case meta_XBOX_WVS: + snprintf(temp,TEMPSIZE,"Metal Arms WVS Header (XBOX)"); + break; + case meta_NGC_WVS: + snprintf(temp,TEMPSIZE,"Metal Arms WVS Header (GameCube)"); + break; + case meta_XBOX_STMA: + snprintf(temp,TEMPSIZE,"Midnight Club 2 STMA Header"); + break; + case meta_XBOX_MATX: + snprintf(temp,TEMPSIZE,"assumed Matrix file by .matx extension"); + break; + case meta_DE2: + snprintf(temp,TEMPSIZE,"gurumin .de2 with embedded funky RIFF"); + break; + case meta_VS: + snprintf(temp,TEMPSIZE,"Men in Black VS Header"); + break; + case meta_DC_STR: + snprintf(temp,TEMPSIZE,"Sega Stream Asset Builder header"); + break; + case meta_DC_STR_V2: + snprintf(temp,TEMPSIZE,"variant of Sega Stream Asset Builder header"); + break; + case meta_XBOX_XMU: + snprintf(temp,TEMPSIZE,"XMU header"); + break; + case meta_XBOX_XVAS: + snprintf(temp,TEMPSIZE,"assumed TMNT file by .xvas extension"); + break; + case meta_PS2_XA2: + snprintf(temp,TEMPSIZE,"Acclaim XA2 Header"); + break; + case meta_DC_IDVI: + snprintf(temp,TEMPSIZE,"IDVI Header"); + break; + case meta_NGC_YMF: + snprintf(temp,TEMPSIZE,"YMF DSP Header"); + break; + case meta_PS2_CCC: + snprintf(temp,TEMPSIZE,"CCC Header"); + break; + case meta_PSX_FAG: + snprintf(temp,TEMPSIZE,"FAG Header"); + break; + case meta_PS2_MIHB: + snprintf(temp,TEMPSIZE,"Merged MIH+MIB"); + break; + case meta_DSP_WII_MUS: + snprintf(temp,TEMPSIZE,"mus header"); + break; + case meta_WII_SNG: + snprintf(temp,TEMPSIZE,"SNG DSP Header"); + break; + case meta_RSD2VAG: + snprintf(temp,TEMPSIZE,"RSD2/VAG Header"); + break; + case meta_RSD2PCMB: + snprintf(temp,TEMPSIZE,"RSD2/PCMB Header"); + break; + case meta_RSD2XADP: + snprintf(temp,TEMPSIZE,"RSD2/XADP Header"); + break; + case meta_RSD3VAG: + snprintf(temp,TEMPSIZE,"RSD3/VAG Header"); + break; + case meta_RSD3GADP: + snprintf(temp,TEMPSIZE,"RSD3/GADP Header"); + break; + case meta_RSD3PCM: + snprintf(temp,TEMPSIZE,"RSD3/PCM Header"); + break; + case meta_RSD3PCMB: + snprintf(temp,TEMPSIZE,"RSD3/PCMB Header"); + break; + case meta_RSD4PCMB: + snprintf(temp,TEMPSIZE,"RSD4/PCMB Header"); + break; + case meta_RSD4PCM: + snprintf(temp,TEMPSIZE,"RSD4/PCM Header"); + break; + case meta_RSD4RADP: + snprintf(temp,TEMPSIZE,"RSD4/RADP Header"); + break; + case meta_RSD4VAG: + snprintf(temp,TEMPSIZE,"RSD4/VAG Header"); + break; + case meta_RSD6XADP: + snprintf(temp,TEMPSIZE,"RSD6/XADP Header"); + break; + case meta_RSD6VAG: + snprintf(temp,TEMPSIZE,"RSD6/VAG Header"); + break; + case meta_RSD6WADP: + snprintf(temp,TEMPSIZE,"RSD6/WADP Header"); + break; + case meta_RSD6RADP: + snprintf(temp,TEMPSIZE,"RSD6/RADP Header"); + break; + case meta_DC_ASD: + snprintf(temp,TEMPSIZE,"ASD Header"); + break; + case meta_NAOMI_SPSD: + snprintf(temp,TEMPSIZE,"SPSD Header"); + break; + case meta_FFXI_BGW: + snprintf(temp,TEMPSIZE,"BGW BGMStream header"); + break; + case meta_FFXI_SPW: + snprintf(temp,TEMPSIZE,"SPW SeWave header"); + break; + case meta_PS2_ASS: + snprintf(temp,TEMPSIZE,"ASS Header"); + break; + case meta_IDSP: + snprintf(temp,TEMPSIZE,"IDSP Header"); + break; + case meta_WAA_WAC_WAD_WAM: + snprintf(temp,TEMPSIZE,"WAA/WAC/WAD/WAM RIFF Header"); + break; + case meta_PS2_SEG: + snprintf(temp,TEMPSIZE,"SEG (PS2) Header"); + break; + case meta_XBOX_SEG: + snprintf(temp,TEMPSIZE,"SEG (XBOX) Header"); + break; + case meta_NDS_STRM_FFTA2: + snprintf(temp,TEMPSIZE,"Final Fantasy Tactics A2 RIFF Header"); + break; + case meta_STR_ASR: + snprintf(temp,TEMPSIZE,"Donkey Kong Jet Race KNON/WII Header"); + break; + case meta_ZWDSP: + snprintf(temp,TEMPSIZE,"Zack and Wiki custom DSP Header"); + break; + case meta_GCA: + snprintf(temp,TEMPSIZE,"GCA DSP Header"); + break; + case meta_SPT_SPD: + snprintf(temp,TEMPSIZE,"SPT+SPD DSP Header"); + break; + case meta_ISH_ISD: + snprintf(temp,TEMPSIZE,"ISH+ISD DSP Header"); + break; + case meta_YDSP: + snprintf(temp,TEMPSIZE,"Yuke's DSP (YDSP) Header"); + break; + case meta_MSVP: + snprintf(temp,TEMPSIZE,"MSVP Header"); + break; + case meta_NGC_SSM: + snprintf(temp,TEMPSIZE,"SSM DSP Header"); + break; + case meta_PS2_JOE: + snprintf(temp,TEMPSIZE,"Disney/Pixar JOE Header"); + break; + case meta_VGS: + snprintf(temp,TEMPSIZE,"Guitar Hero Encore Rocks the 80's Header"); + break; + case meta_DC_DCSW_DCS: + snprintf(temp,TEMPSIZE,"Evil Twin DCS file with helper"); + break; + case meta_WII_SMP: + snprintf(temp,TEMPSIZE,"SMP DSP Header"); + break; + case meta_EMFF_PS2: + case meta_EMFF_NGC: + snprintf(temp,TEMPSIZE,"Eidos Music File Format Header"); + break; + case meta_THP: + snprintf(temp,TEMPSIZE,"THP Movie File Format Header"); + break; + case meta_STS_WII: + snprintf(temp,TEMPSIZE,"Shikigami no Shiro (WII) Header"); + break; + case meta_PS2_P2BT: + snprintf(temp,TEMPSIZE,"Pop'n'Music 7 Header"); + break; + case meta_PS2_GBTS: + snprintf(temp,TEMPSIZE,"Pop'n'Music 9 Header"); + break; + case meta_NGC_DSP_IADP: + snprintf(temp,TEMPSIZE,"IADP Header"); + break; + case meta_RSTM_shrunken: + snprintf(temp,TEMPSIZE,"Nintendo RSTM header, corrupted by Atlus"); + break; + case meta_RIFF_WAVE_MWV: + snprintf(temp,TEMPSIZE,"RIFF WAVE header with .mwv flavoring"); + break; + case meta_RIFF_WAVE_SNS: + snprintf(temp,TEMPSIZE,"RIFF WAVE header with .sns flavoring"); + break; + case meta_FFCC_STR: + snprintf(temp,TEMPSIZE,"Final Fantasy: Crystal Chronicles STR header"); + break; + case meta_SAT_BAKA: + snprintf(temp,TEMPSIZE,"BAKA header from Crypt Killer"); + break; + case meta_NDS_SWAV: + snprintf(temp,TEMPSIZE,"SWAV Header"); + break; + case meta_PS2_VSF: + snprintf(temp,TEMPSIZE,"Musashi: Samurai Legend VSF Header"); + break; + case meta_NDS_RRDS: + snprintf(temp,TEMPSIZE,"Ridger Racer DS Header"); + break; + case meta_PS2_TK5: + snprintf(temp,TEMPSIZE,"Tekken 5 Stream Header"); + break; + case meta_PS2_SND: + snprintf(temp,TEMPSIZE,"Might and Magic SSND Header"); + break; + case meta_PS2_VSF_TTA: + snprintf(temp,TEMPSIZE,"VSF with SMSS Header"); + break; + case meta_ADS: + snprintf(temp,TEMPSIZE,"dhSS Header"); + break; + case meta_WII_STR: + snprintf(temp,TEMPSIZE,"HOTD Overkill - STR+STH WII Header"); + break; + case meta_PS2_MCG: + snprintf(temp,TEMPSIZE,"Gunvari MCG Header"); + break; + case meta_ZSD: + snprintf(temp,TEMPSIZE,"ZSD Header"); + break; + case meta_RedSpark: + snprintf(temp,TEMPSIZE,"RedSpark Header"); + break; + case meta_PC_IVAUD: + snprintf(temp,TEMPSIZE,"assumed GTA IV Audio file by .ivaud extension"); + break; + case meta_DSP_WII_WSD: + snprintf(temp,TEMPSIZE,"Standard Nintendo DSP headers in .wsd"); + break; + case meta_WII_NDP: + snprintf(temp,TEMPSIZE,"Vertigo NDP Header"); + break; + case meta_PS2_SPS: + snprintf(temp,TEMPSIZE,"Ape Escape 2 SPS Header"); + break; + case meta_PS2_XA2_RRP: + snprintf(temp,TEMPSIZE,"Acclaim XA2 Header"); + break; + case meta_NDS_HWAS: + snprintf(temp,TEMPSIZE,"NDS 'HWAS' Header"); + break; + case meta_NGC_LPS: + snprintf(temp,TEMPSIZE,"Rave Master LPS Header"); + break; + case meta_NAOMI_ADPCM: + snprintf(temp,TEMPSIZE,"NAOMI/NAOMI2 Arcade games ADPCM header"); + break; + case meta_SD9: + snprintf(temp,TEMPSIZE,"beatmania IIDX SD9 header"); + break; + case meta_2DX9: + snprintf(temp,TEMPSIZE,"beatmania IIDX 2DX9 header"); + break; + case meta_DSP_YGO: + snprintf(temp,TEMPSIZE,"Konami custom DSP Header"); + break; + case meta_PS2_VGV: + snprintf(temp,TEMPSIZE,"Rune: Viking Warlord VGV Header"); + break; + case meta_NGC_GCUB: + snprintf(temp,TEMPSIZE,"GCub Header"); + break; + case meta_NGC_SCK_DSP: + snprintf(temp,TEMPSIZE,"The Scorpion King SCK Header"); + break; + case meta_NGC_SWD: + snprintf(temp,TEMPSIZE,"PSF + Standard DSP Headers"); + break; + case meta_CAFF: + snprintf(temp,TEMPSIZE,"Apple Core Audio Format Header"); + break; + case meta_PC_MXST: + snprintf(temp,TEMPSIZE,"Lego Island MxSt Header"); + break; + case meta_PC_SOB_SAB: + snprintf(temp,TEMPSIZE,"Worms 4: Mayhem SOB/SAB Header"); + break; + case meta_MAXIS_XA: + snprintf(temp,TEMPSIZE,"Maxis XAI/XAJ Header"); + break; + case meta_EXAKT_SC: + snprintf(temp,TEMPSIZE,"assumed Activision / EXAKT SC by extension"); + break; + case meta_WII_BNS: + snprintf(temp,TEMPSIZE,"Nintendo BNS header"); + break; + case meta_WII_WAS: + snprintf(temp,TEMPSIZE,"WAS (iSWS) DSP header"); + break; + case meta_XBOX_HLWAV: + snprintf(temp,TEMPSIZE,"Half Life 2 bgm header"); + break; + case meta_STX: + snprintf(temp,TEMPSIZE,"Nintendo .stx header"); + break; + case meta_PS2_STM: + snprintf(temp,TEMPSIZE,"Red Dead Revolver .stm (.ps2stm)"); + break; + case meta_MYSPD: + snprintf(temp,TEMPSIZE,"U-Sing .myspd header"); + break; + case meta_HIS: + snprintf(temp,TEMPSIZE,"Her Interactive Sound header"); + break; + case meta_PS2_AST: + snprintf(temp,TEMPSIZE,"KOEI AST header"); + break; + case meta_CAPDSP: + snprintf(temp,TEMPSIZE,"Capcom custom DSP header"); + break; + case meta_DMSG: + snprintf(temp,TEMPSIZE,"RIFF/DMSGsegh header"); + break; + case meta_PONA_3DO: + case meta_PONA_PSX: + snprintf(temp,TEMPSIZE,"Policenauts BGM header"); + break; + case meta_NGC_DSP_AAAP: + snprintf(temp,TEMPSIZE,"Double standard dsp header in 'AAAp'"); + break; + case meta_NGC_DSP_KONAMI: + snprintf(temp,TEMPSIZE,"Konami dsp header"); + break; + case meta_PS2_STER: + snprintf(temp,TEMPSIZE,"STER Header"); + break; + case meta_BNSF: + snprintf(temp,TEMPSIZE,"Namco Bandai BNSF header"); + break; + case meta_PS2_WB: + snprintf(temp,TEMPSIZE,"Shooting Love. ~TRIZEAL~ WB header"); + break; + case meta_S14: + snprintf(temp,TEMPSIZE,"assumed Polycom Siren 14 by .s14 extension"); + break; + case meta_SSS: + snprintf(temp,TEMPSIZE,"assumed Polycom Siren 14 by .sss extension"); + break; + case meta_PS2_GCM: + snprintf(temp,TEMPSIZE,"GCM 'MCG' Header"); + break; + case meta_PS2_SMPL: + snprintf(temp,TEMPSIZE,"Homura 'SMPL' Header"); + break; + case meta_PS2_MSA: + snprintf(temp,TEMPSIZE,"Psyvariar -Complete Edition- MSA header"); + break; + case meta_PC_SMP: + snprintf(temp,TEMPSIZE,"Ghostbusters .smp Header"); + break; + case meta_NGC_PDT: + snprintf(temp,TEMPSIZE,"PDT DSP header"); + break; + case meta_NGC_BO2: + snprintf(temp,TEMPSIZE,"Blood Omen 2 DSP header"); + break; + case meta_P3D: + snprintf(temp,TEMPSIZE,"Prototype P3D Header"); + break; + case meta_PS2_TK1: + snprintf(temp,TEMPSIZE,"Tekken TK5STRM1 Header"); + break; + case meta_PS2_ADSC: + snprintf(temp,TEMPSIZE,"ADSC Header"); + break; + case meta_NGC_DSP_MPDS: + snprintf(temp,TEMPSIZE,"MPDS DSP header"); + break; + case meta_DSP_STR_IG: + snprintf(temp,TEMPSIZE,"Infogrames dual dsp header"); + break; + case meta_PSX_MGAV: + snprintf(temp,TEMPSIZE,"Electronic Arts RVWS header"); + break; + case meta_PS2_B1S: + snprintf(temp,TEMPSIZE,"B1S header"); + break; + case meta_PS2_WAD: + snprintf(temp,TEMPSIZE,"WAD header"); + break; + case meta_DSP_XIII: + snprintf(temp,TEMPSIZE,"XIII dsp header"); + break; + case meta_NGC_DSP_STH_STR: + snprintf(temp,TEMPSIZE,"STH dsp header"); + break; + case meta_DSP_CABELAS: + snprintf(temp,TEMPSIZE,"Cabelas games dsp header"); + break; + case meta_PS2_LPCM: + snprintf(temp,TEMPSIZE,"LPCM header"); + break; + case meta_PS2_VMS: + snprintf(temp,TEMPSIZE,"VMS Header"); + break; + case meta_PS2_XAU: + snprintf(temp,TEMPSIZE,"XAU Header"); + break; + case meta_GH3_BAR: + snprintf(temp,TEMPSIZE,"Guitar Hero III Mobile .bar"); + break; + case meta_FFW: + snprintf(temp,TEMPSIZE,"Freedom Fighters BGM header"); + break; + case meta_DSP_DSPW: + snprintf(temp,TEMPSIZE,"DSPW dsp header"); + break; + case meta_PS2_JSTM: + snprintf(temp,TEMPSIZE,"JSTM Header"); + break; + case meta_PS3_XVAG: + snprintf(temp,TEMPSIZE,"XVAG Header"); + break; + case meta_PS3_CPS: + snprintf(temp,TEMPSIZE,"CPS Header"); + break; + case meta_SQEX_SCD: + snprintf(temp,TEMPSIZE,"Square-Enix SCD"); + break; + case meta_NGC_NST_DSP: + snprintf(temp,TEMPSIZE,"Animaniacs NST header"); + break; + case meta_BAF: + snprintf(temp,TEMPSIZE,".baf WAVE header"); + break; + case meta_PS3_MSF: + snprintf(temp,TEMPSIZE,"PS3 MSF header"); + break; + case meta_FSB_MPEG: + snprintf(temp,TEMPSIZE,"FSB MPEG header"); + break; + case meta_NUB_VAG: + snprintf(temp,TEMPSIZE,"VAG (NUB) header"); + break; + case meta_PS3_PAST: + snprintf(temp,TEMPSIZE,"SNDP header"); + break; + case meta_PS3_SGH_SGB: + snprintf(temp,TEMPSIZE,"SGH+SGB SGXD header"); + break; + case meta_NGCA: + snprintf(temp,TEMPSIZE,"NGCA header"); + break; + case meta_WII_RAS: + snprintf(temp,TEMPSIZE,"RAS header"); + break; + case meta_PS2_SPM: + snprintf(temp,TEMPSIZE,"SPM header"); + break; + case meta_X360_TRA: + snprintf(temp,TEMPSIZE,"assumed DefJam Rapstar Audio File by .tra extension"); + break; + case meta_PS2_VGS: + snprintf(temp,TEMPSIZE,"Princess Soft VGS header"); + break; + case meta_PS2_IAB: + snprintf(temp,TEMPSIZE,"IAB header"); + break; + case meta_PS2_STRLR: + snprintf(temp,TEMPSIZE,"STR L/R header"); + break; + case meta_LSF_N1NJ4N: + snprintf(temp,TEMPSIZE,".lsf !n1nj4n header"); + break; + case meta_PS3_VAWX: + snprintf(temp,TEMPSIZE,"VAWX header"); + break; + case meta_PC_SNDS: + snprintf(temp,TEMPSIZE,"assumed Heavy Iron IMA by .snds extension"); + break; + case meta_PS2_WMUS: + snprintf(temp,TEMPSIZE,"assumed The Warriors Sony ADPCM by .wmus extension"); + break; + case meta_HYPERSCAN_KVAG: + snprintf(temp,TEMPSIZE,"Mattel Hyperscan KVAG"); + break; + case meta_IOS_PSND: + snprintf(temp,TEMPSIZE,"PSND Header"); + break; + case meta_BOS_ADP: + snprintf(temp,TEMPSIZE,"ADP! header"); + break; + case meta_EB_SFX: + snprintf(temp,TEMPSIZE,"Excitebots .sfx header"); + break; + case meta_EB_SF0: + snprintf(temp,TEMPSIZE,"assumed Excitebots .sf0 by extension"); + break; + case meta_PS3_KLBS: + snprintf(temp,TEMPSIZE,"klBS Header"); + break; + case meta_PS3_SGX: + snprintf(temp,TEMPSIZE,"PS3 SGXD/WAVE header"); + break; + case meta_PS2_MTAF: + snprintf(temp,TEMPSIZE,"Konami MTAF header"); + break; + case meta_PS2_VAG1: + snprintf(temp,TEMPSIZE,"Konami VAG Mono header (VAG1)"); + break; + case meta_PS2_VAG2: + snprintf(temp,TEMPSIZE,"Konami VAG Stereo header (VAG2)"); + break; + case meta_TUN: + snprintf(temp,TEMPSIZE,"TUN 'ALP' header"); + break; + case meta_WPD: + snprintf(temp,TEMPSIZE,"WPD 'DPW' header"); + break; + case meta_MN_STR: + snprintf(temp,TEMPSIZE,"Mini Ninjas 'STR' header"); + break; + case meta_PS2_MSS: + snprintf(temp,TEMPSIZE,"ShellShock Nam '67 'MSCC' header"); + break; + case meta_PS2_HSF: + snprintf(temp,TEMPSIZE,"Lowrider 'HSF' header"); + break; + case meta_PS3_IVAG: + snprintf(temp,TEMPSIZE,"PS3 'IVAG' Header"); + break; + case meta_PS2_2PFS: + snprintf(temp,TEMPSIZE,"PS2 '2PFS' Header"); + break; + case meta_RSD6OOGV: + snprintf(temp,TEMPSIZE,"RSD6/OOGV Header"); + break; + case meta_UBI_CKD: + snprintf(temp,TEMPSIZE,"CKD 'RIFF' Header"); + break; + case meta_PS2_VBK: + snprintf(temp,TEMPSIZE,"PS2 VBK Header"); + break; + case meta_OTM: + snprintf(temp,TEMPSIZE,"Otomedius OTM Header"); + break; + case meta_CSTM: + snprintf(temp,TEMPSIZE,"Nintendo 3DS CSTM Header"); + break; + default: + snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); + } + concatn(length,desc,temp); +} + +/* */ +const char * const dfs_pairs[][2] = { + {"L","R"}, + {"l","r"}, + {"_0","_1"}, + {"left","right"}, + {"Left","Right"}, +}; +#define DFS_PAIR_COUNT (sizeof(dfs_pairs)/sizeof(dfs_pairs[0])) + +void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile) { + char filename[PATH_LIMIT]; + char filename2[260]; + char * ext; + int dfs_name= -1; /*-1=no stereo, 0=opened_stream is left, 1=opened_stream is right */ + VGMSTREAM * new_stream = NULL; + STREAMFILE *dual_stream = NULL; + int i,j; + + if (opened_stream->channels != 1) return; + + streamFile->get_name(streamFile,filename,sizeof(filename)); + + /* vgmstream's layout stuff currently assumes a single file */ + // fastelbja : no need ... this one works ok with dual file + //if (opened_stream->layout != layout_none) return; + + /* we need at least a base and a name ending to replace */ + if (strlen(filename)<2) return; + + strcpy(filename2,filename); + + /* look relative to the extension; */ + ext = (char *)filename_extension(filename2); + + /* we treat the . as part of the extension */ + if (ext-filename2 >= 1 && ext[-1]=='.') ext--; + + for (i=0; dfs_name==-1 && iopen(streamFile,filename2,STREAMFILE_DEFAULT_BUFFER_SIZE); + if (!dual_stream) goto fail; + + new_stream = init_vgmstream_internal(dual_stream, + 0 /* don't do dual file on this, to prevent recursion */ + ); + close_streamfile(dual_stream); + + /* see if we were able to open the file, and if everything matched nicely */ + if (new_stream && + new_stream->channels == 1 && + /* we have seen legitimate pairs where these are off by one... */ + /* but leaving it commented out until I can find those and recheck */ + /* abs(new_stream->num_samples-opened_stream->num_samples <= 1) && */ + new_stream->num_samples == opened_stream->num_samples && + new_stream->sample_rate == opened_stream->sample_rate && + new_stream->meta_type == opened_stream->meta_type && + new_stream->coding_type == opened_stream->coding_type && + new_stream->layout_type == opened_stream->layout_type && + new_stream->loop_flag == opened_stream->loop_flag && + /* check these even if there is no loop, because they should then + * be zero in both */ + new_stream->loop_start_sample == opened_stream->loop_start_sample && + new_stream->loop_end_sample == opened_stream->loop_end_sample && + /* check even if the layout doesn't use them, because it is + * difficult to determine when it does, and they should be zero + * otherwise, anyway */ + new_stream->interleave_block_size == opened_stream->interleave_block_size && + new_stream->interleave_smallblock_size == opened_stream->interleave_smallblock_size) { + /* We seem to have a usable, matching file. Merge in the second channel. */ + VGMSTREAMCHANNEL * new_chans; + VGMSTREAMCHANNEL * new_loop_chans = NULL; + VGMSTREAMCHANNEL * new_start_chans = NULL; + + /* build the channels */ + new_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); + if (!new_chans) goto fail; + + memcpy(&new_chans[dfs_name],&opened_stream->ch[0],sizeof(VGMSTREAMCHANNEL)); + memcpy(&new_chans[dfs_name^1],&new_stream->ch[0],sizeof(VGMSTREAMCHANNEL)); + + /* loop and start will be initialized later, we just need to + * allocate them here */ + new_start_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); + if (!new_start_chans) { + free(new_chans); + goto fail; + } + + if (opened_stream->loop_ch) { + new_loop_chans = calloc(2,sizeof(VGMSTREAMCHANNEL)); + if (!new_loop_chans) { + free(new_chans); + free(new_start_chans); + goto fail; + } + } + + /* remove the existing structures */ + /* not using close_vgmstream as that would close the file */ + free(opened_stream->ch); + free(new_stream->ch); + + free(opened_stream->start_ch); + free(new_stream->start_ch); + + if (opened_stream->loop_ch) { + free(opened_stream->loop_ch); + free(new_stream->loop_ch); + } + + /* fill in the new structures */ + opened_stream->ch = new_chans; + opened_stream->start_ch = new_start_chans; + opened_stream->loop_ch = new_loop_chans; + + /* stereo! */ + opened_stream->channels = 2; + + /* discard the second VGMSTREAM */ + free(new_stream); + } +fail: + return; +} diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.h b/Frameworks/vgmstream/vgmstream/src/vgmstream.h new file mode 100644 index 000000000..1f80f2ff1 --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/src/vgmstream.h @@ -0,0 +1,881 @@ +/* + * vgmstream.h - definitions for VGMSTREAM, encapsulating a multi-channel, looped audio stream + */ + +#ifndef _VGMSTREAM_H +#define _VGMSTREAM_H + +enum { PATH_LIMIT = 32768 }; + +/* Due mostly to licensing issues, Vorbis, MPEG, and G.722.1 decoding are + * done by external libraries. + * If someone wants to do a standalone build, they can do it by simply + * removing these defines (and the references to the libraries in the + * Makefile) */ +//#define VGM_USE_VORBIS +//#define VGM_USE_MPEG +/* disabled by default, defined for builds that support it */ +//#define VGM_USE_G7221 +//#define VGM_USE_MP4V2 +//#define VGM_USE_FDKAAC + +#include "streamfile.h" +#ifdef BUILD_VGMSTREAM +#include "coding/g72x_state.h" +#else +#include "g72x_state.h" +#endif +#ifdef VGM_USE_VORBIS +#include +#endif +#ifdef VGM_USE_MPEG +#include +#endif +#ifdef VGM_USE_G7221 +#include "g7221.h" +#endif + +#ifdef VGM_USE_MP4V2 +#define MP4V2_NO_STDINT_DEFS +#include +#endif + +#ifdef VGM_USE_FDKAAC +#include +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS +#include +#endif + +#ifdef BUILD_VGMSTREAM +#include "coding/acm_decoder.h" +#include "coding/nwa_decoder.h" +#else +#include "acm_decoder.h" +#include "nwa_decoder.h" +#endif + +/* The encoding type specifies the format the sound data itself takes */ +typedef enum { + /* 16-bit PCM */ + coding_PCM16BE, /* big endian 16-bit PCM */ + coding_PCM16LE, /* little endian 16-bit PCM */ + coding_PCM16LE_int, /* little endian 16-bit PCM with sample-level + interleave handled by the decoder */ + + /* 8-bit PCM */ + coding_PCM8, /* 8-bit PCM */ + coding_PCM8_U, /* 8-bit PCM, unsigned (0x80 = 0) */ + coding_PCM8_int, /* 8-Bit PCM with sample-level interleave handled + by the decoder */ + coding_PCM8_SB_int, /* 8-bit PCM, sign bit (others are 2's complement), + sample-level interleave */ + coding_PCM8_U_int, /* 8-bit PCM, unsigned (0x80 = 0), sample-level + interleave */ + + /* 4-bit ADPCM */ + coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */ + coding_CRI_ADX, /* CRI ADX */ + coding_CRI_ADX_enc_8, /* encrypted CRI ADX, type 8 (God Hand) */ + coding_CRI_ADX_enc_9, /* encrypted CRI ADX, type 9 (PSO2) */ + coding_NGC_DSP, /* NGC ADPCM, called DSP */ + coding_NGC_DTK, /* NGC hardware disc ADPCM, called DTK, TRK or ADP */ + coding_G721, /* CCITT G.721 ADPCM */ + coding_NGC_AFC, /* NGC ADPCM, called AFC */ + coding_PSX, /* PSX & PS2 ADPCM */ + coding_invert_PSX, /* PSX ADPCM with some weirdness */ + coding_PSX_badflags, /* with garbage in the flags byte */ + coding_FFXI, /* FF XI PSX-ish ADPCM */ + coding_BAF_ADPCM, /* Bizarre Creations PSX-ish ADPCM */ + coding_XA, /* PSX CD-XA */ + coding_XBOX, /* XBOX IMA */ + coding_INT_XBOX, /* XBOX 'real interleaved' IMA */ + coding_EAXA, /* EA/XA ADPCM */ + coding_EA_ADPCM, /* EA ADPCM */ + coding_MAXIS_ADPCM, /* MAXIS ADPCM */ + coding_NDS_PROCYON, /* NDS Procyon Studio ADPCM */ + +#ifdef VGM_USE_VORBIS + coding_ogg_vorbis, /* vorbis */ +#endif + coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */ + coding_SDX2_int, /* SDX2 2:1 Squareroot-Delta-Exact compression, + with smaple-level interleave handled by the + decoder */ + coding_CBD2, /* CBD2 2:1 Cuberoot-Delta-Exact compression */ + coding_CBD2_int, /* CBD2 2:1 Cuberoot-Delta-Exact compression, + with sample-level interleave handled by the + decoder */ + coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */ + coding_INT_DVI_IMA, /* Interleaved DVI */ + coding_EACS_IMA, + coding_IMA, /* bare IMA, low nibble first */ + coding_INT_IMA, /* */ + coding_MS_IMA, /* Microsoft IMA */ + coding_RAD_IMA, /* "Radical ADPCM" IMA */ + coding_RAD_IMA_mono, /* "Radical ADPCM" IMA, mono (for interleave) */ + coding_APPLE_IMA4, /* Apple Quicktime IMA4 */ + coding_DAT4_IMA, /* Eurocom 'DAT4' IMA ADPCM */ + coding_SNDS_IMA, /* Heavy Iron Studios .snds IMA ADPCM */ + coding_WS, /* Westwood Studios' custom VBR ADPCM */ +#ifdef VGM_USE_MPEG + coding_fake_MPEG2_L2, /* MPEG-2 Layer 2 (AHX), with lying headers */ + /* I don't even know offhand if all these combinations exist... */ + coding_MPEG1_L1, + coding_MPEG1_L2, + coding_MPEG1_L3, /* good ol' MPEG-1 Layer 3 (MP3) */ + coding_MPEG2_L1, + coding_MPEG2_L2, + coding_MPEG2_L3, + coding_MPEG25_L1, + coding_MPEG25_L2, + coding_MPEG25_L3, +#endif +#ifdef VGM_USE_G7221 + coding_G7221, /* G.722.1 (Polycom Siren 7) */ + coding_G7221C, /* G.722.1 with Annex C extension (Polycom Siren 14) */ +#endif + + coding_ACM, /* InterPlay ACM */ + /* compressed NWA at various levels */ + coding_NWA0, + coding_NWA1, + coding_NWA2, + coding_NWA3, + coding_NWA4, + coding_NWA5, + + coding_MSADPCM, /* Microsoft ADPCM */ + coding_AICA, /* Yamaha AICA ADPCM */ + coding_L5_555, /* Level-5 0x555 */ + coding_SASSC, /* Activision EXAKT SASSC DPCM */ + coding_PCM16LE_XOR_int, /* sample-level xor */ + coding_LSF, /* lsf ADPCM */ + coding_MTAF, /* Konami IMA-derived MTAF ADPCM */ + +#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC) + coding_MP4_AAC, +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS + coding_AT3plus, +#endif +} coding_t; + +/* The layout type specifies how the sound data is laid out in the file */ +typedef enum { + /* generic */ + layout_none, /* straight data */ + /* interleave */ + layout_interleave, /* equal interleave throughout the stream */ + layout_interleave_shortblock, /* interleave with a short last block */ + + layout_interleave_byte, /* full byte interleave */ + + /* headered blocks */ + layout_ast_blocked, /* .ast STRM with BLCK blocks*/ + layout_halpst_blocked, /* blocks with HALPST-format header */ + layout_xa_blocked, + layout_ea_blocked, + layout_eacs_blocked, + layout_caf_blocked, + layout_wsi_blocked, + layout_str_snds_blocked, + layout_ws_aud_blocked, + layout_matx_blocked, + layout_de2_blocked, + layout_xvas_blocked, + layout_vs_blocked, + layout_emff_ps2_blocked, + layout_emff_ngc_blocked, + layout_gsb_blocked, + layout_thp_blocked, + layout_filp_blocked, + layout_psx_mgav_blocked, + layout_ps2_adm_blocked, + layout_dsp_bdsp_blocked, + layout_mxch_blocked, + +#if 0 + layout_strm_blocked, /* */ +#endif + /* otherwise odd */ + layout_dtk_interleave, /* dtk interleaves channels by nibble */ +#ifdef VGM_USE_VORBIS + layout_ogg_vorbis, /* ogg vorbis file */ +#endif +#ifdef VGM_USE_MPEG + layout_fake_mpeg, /* MPEG audio stream with bad frame headers (AHX) */ + layout_mpeg, /* proper MPEG audio stream */ +#endif + layout_acm, /* dummy, let libacm handle layout */ + layout_mus_acm, /* mus has multi-files to deal with */ + layout_aix, /* CRI AIX's wheels within wheels */ + layout_aax, /* CRI AAX's wheels within databases */ + layout_ivaud_blocked, /* GTA IV .ivaud blocks */ + layout_tra_blocked, /* DefJam Rapstar .tra blocks */ + layout_ps2_iab_blocked, + layout_ps2_strlr_blocked, + layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */ +} layout_t; + +/* The meta type specifies how we know what we know about the file. We may know because of a header we read, some of it may have been guessed from filenames, etc. */ +typedef enum { + /* DSP-specific */ + meta_DSP_STD, /* standard GC ADPCM (DSP) header */ + meta_DSP_CSTR, /* Star Fox Assault "Cstr" */ + meta_DSP_RS03, /* Metroid Prime 2 "RS03" */ + meta_DSP_STM, /* Paper Mario 2 STM */ + meta_DSP_HALP, /* SSB:M "HALPST" */ + meta_DSP_AGSC, /* Metroid Prime 2 title */ + meta_DSP_MPDSP, /* Monopoly Party single header stereo */ + meta_DSP_JETTERS, /* Bomberman Jetters .dsp */ + meta_DSP_MSS, + meta_DSP_GCM, + meta_DSP_STR, /* Conan .str files */ + meta_DSP_SADB, /* .sad */ + meta_DSP_WSI, /* .wsi */ + meta_DSP_AMTS, /* .amts */ + meta_DSP_WII_IDSP, /* .gcm with IDSP header */ + meta_DSP_WII_MUS, /* .mus */ + meta_DSP_WII_WSD, /* Phantom Brave (WII) */ + meta_WII_NDP, /* Vertigo (Wii) */ + meta_DSP_YGO, /* Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ + + /* Nintendo */ + meta_STRM, /* STRM */ + meta_RSTM, /* RSTM (similar to STRM) */ + meta_AFC, /* AFC */ + meta_AST, /* AST */ + meta_RWSD, /* single-stream RWSD */ + meta_RWAR, /* single-stream RWAR */ + meta_RWAV, /* contents of RWAR */ + meta_CWAV, /* */ + meta_RSTM_SPM, /* RSTM with 44->22khz hack */ + meta_THP, + meta_RSTM_shrunken, /* Atlus' mutant shortened RSTM */ + meta_NDS_SWAV, /* Asphalt Urban GT 1 & 2 */ + meta_NDS_RRDS, /* Ridge Racer DS */ + meta_WII_BNS, /* Wii BNS Banner Sound (similar to RSTM) */ + meta_STX, /* Pikmin .stx */ + + /* CRI ADX */ + meta_ADX_03, /* ADX "type 03" */ + meta_ADX_04, /* ADX "type 04" */ + meta_ADX_05, /* ADX "type 05" */ + meta_AIX, /* CRI AIX */ + meta_AAX, /* CRI AAX */ + meta_UTF_DSP, /* CRI ADPCM_WII, like AAX with DSP */ + + /* etc */ + meta_NGC_ADPDTK, /* NGC DTK/ADP, no header (.adp) */ + meta_kRAW, /* almost headerless PCM */ + meta_RSF, /* Retro Studios RSF, no header (.rsf) */ + meta_HALPST, /* HAL Labs HALPST */ + meta_GCSW, /* GCSW (PCM) */ + meta_CFN, /* Namco CAF Audio File */ + meta_MYSPD, /* U-Sing .myspd */ + meta_HIS, /* Her Ineractive .his */ + meta_BNSF, /* Bandai Namco Sound Format */ + + meta_PS2_SShd, /* .ADS with SShd header */ + meta_PS2_NPSF, /* Namco Production Sound File */ + meta_PS2_RXW, /* Sony Arc The Lad Sound File */ + meta_PS2_RAW, /* RAW Interleaved Format */ + meta_PS2_EXST, /* Shadow of Colossus EXST */ + meta_PS2_SVAG, /* Konami SVAG */ + meta_PS2_MIB, /* MIB File */ + meta_PS2_MIB_MIH, /* MIB File + MIH Header*/ + meta_PS2_MIC, /* KOEI MIC File */ + meta_PS2_VAGi, /* VAGi Interleaved File */ + meta_PS2_VAGp, /* VAGp Mono File */ + meta_PS2_VAGm, /* VAGp Mono File */ + meta_PS2_pGAV, /* VAGp with Little Endian Header */ + meta_PSX_GMS, /* GMS File (used in PS1 & PS2) */ + meta_PS2_STR, /* Pacman STR+STH files */ + meta_PS2_ILD, /* ILD File */ + meta_PS2_PNB, /* PsychoNauts Bgm File */ + meta_PSX_XA, /* CD-XA with RIFF header */ + meta_PS2_VAGs, /* VAG Stereo from Kingdom Hearts */ + meta_PS2_VPK, /* VPK Audio File */ + meta_PS2_BMDX, /* Beatmania thing */ + meta_PS2_IVB, /* Langrisser 3 IVB */ + meta_PS2_SND, /* some Might & Magics SSND header */ + meta_PS2_SVS, /* Square SVS */ + meta_XSS, /* Dino Crisis 3 */ + meta_SL3, /* Test Drive Unlimited */ + meta_HGC1, /* Knights of the Temple 2 */ + meta_AUS, /* Variuos Capcom Games */ + meta_RWS, /* Variuos Konami Games */ + meta_FSB1, /* FMOD Sample Bank, version 1 */ + meta_FSB3_0, /* FMOD Sample Bank, version 3.0 */ + meta_FSB3_1, /* FMOD Sample Bank, version 3.1 */ + meta_FSB4, /* FMOD Sample Bank, version 4 */ + meta_FSB_MPEG, /* Just Test */ + meta_FSB4_WAV, /* FMOD Sample Bank, version 4 with "WAV" Header */ + meta_RWX, /* Air Force Delta Storm (XBOX) */ + meta_XWB, /* King of Fighters (XBOX) */ + meta_XA30, /* Driver - Parallel Lines (PS2) */ + meta_MUSC, /* Spyro Games, possibly more */ + meta_MUSX_V004, /* Spyro Games, possibly more */ + meta_MUSX_V005, /* Spyro Games, possibly more */ + meta_MUSX_V006, /* Spyro Games, possibly more */ + meta_MUSX_V010, /* Spyro Games, possibly more */ + meta_MUSX_V201, /* Sphinx and the cursed Mummy */ + meta_LEG, /* Legaia 2 */ + meta_FILP, /* Resident Evil - Dead Aim */ + meta_IKM, /* Zwei! */ + meta_SFS, /* Baroque */ + meta_BG00, /* Ibara, Mushihimesama */ + meta_PS2_RSTM, /* Midnight Club 3 */ + meta_PS2_KCES, /* Dance Dance Revolution */ + meta_PS2_DXH, /* Tokobot Plus - Myteries of the Karakuri */ + meta_PS2_PSH, /* Dawn of Mana - Seiken Densetsu 4 */ + meta_PCM_SCD, /* Ephemeral Fantasia */ + meta_PCM_PS2, /* Lunar - Eternal Blue */ + meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 */ + meta_PS2_PSW, /* Rayman Raving Rabbids */ + meta_PS2_VAS, /* Pro Baseball Spirits 5 */ + meta_PS2_TEC, /* TECMO badflagged stream */ + meta_PS2_ENTH, /* Enthusia */ + meta_SDT, /* Baldur's Gate - Dark Alliance */ + meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ + meta_NGC_SWD, /* Conflict - Desert Storm 1 & 2 */ + meta_CAPDSP, /* Capcom DSP Header */ + meta_DC_STR, /* SEGA Stream Asset Builder */ + meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */ + meta_NGC_BH2PCM, /* Bio Hazard 2 */ + meta_SAT_SAP, /* Bubble Symphony */ + meta_DC_IDVI, /* Eldorado Gate */ + meta_KRAW, /* Geometry Wars - Galaxies */ + meta_PS2_OMU, /* PS2 Int file with Header */ + meta_PS2_XA2, /* XG3 Extreme-G Racing */ + meta_IDSP, /* Chronicles of Narnia, Soul Calibur Legends, Mario Strikers Charged */ + meta_SPT_SPD, /* Variouis */ + meta_ISH_ISD, /* Various */ + meta_GSP_GSB, /* Various */ + meta_YDSP, /* WWE Day of Reckoning */ + meta_FFCC_STR, /* Final Fantasy: Crystal Chronicles */ + + + meta_WAA_WAC_WAD_WAM, /* Beyond Good & Evil */ + meta_GCA, /* Metal Slug Anthology */ + meta_MSVP, /* Popcap Hits */ + meta_NGC_SSM, /* Golden Gashbell Full Power */ + meta_PS2_JOE, /* Wall-E / Pixar games */ + + meta_NGC_YMF, /* WWE WrestleMania X8 */ + meta_SADL, /* .sad */ + meta_PS2_CCC, /* Tokyo Xtreme Racer DRIFT 2 */ + meta_PSX_FAG, /* Jackie Chan - Stuntmaster */ + meta_PS2_MIHB, /* Merged MIH+MIB */ + meta_NGC_PDT, /* Mario Party 6 */ + meta_DC_ASD, /* Miss Moonligh */ + meta_NAOMI_SPSD, /* Guilty Gear X */ + + meta_RSD2VAG, /* RSD2VAG */ + meta_RSD2PCMB, /* RSD2PCMB */ + meta_RSD2XADP, /* RSD2XADP */ + meta_RSD3VAG, /* RSD3VAG */ + meta_RSD3GADP, /* RSD3GADP */ + meta_RSD3PCM, /* RSD3PCM */ + meta_RSD3PCMB, /* RSD3PCMB */ + meta_RSD4PCMB, /* RSD4PCMB */ + meta_RSD4PCM, /* RSD4PCM */ + meta_RSD4RADP, /* RSD4RADP */ + meta_RSD4VAG, /* RSD4VAG */ + meta_RSD6VAG, /* RSD6VAG */ + meta_RSD6WADP, /* RSD6WADP */ + meta_RSD6XADP, /* RSD6XADP */ + meta_RSD6RADP, /* RSD6RADP */ + meta_RSD6OOGV, /* RSD6OOGV */ + + meta_PS2_ASS, /* ASS */ + meta_PS2_SEG, /* Eragon */ + meta_XBOX_SEG, + meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */ + meta_STR_ASR, /* Donkey Kong Jet Race */ + meta_ZWDSP, /* Zack and Wiki */ + meta_VGS, /* Guitar Hero Encore - Rocks the 80s */ + meta_DC_DCSW_DCS, /* Evil Twin - Cypriens Chronicles (DC) */ + meta_WII_SMP, /* Mushroom Men - The Spore Wars */ + meta_WII_SNG, /* Excite Trucks */ + meta_EMFF_PS2, /* Eidos Music File Format for PS2*/ + meta_EMFF_NGC, /* Eidos Music File Format for NGC/WII */ + meta_SAT_BAKA, /* Crypt Killer */ + meta_PS2_VSF, /* Musashi: Samurai Legend */ + meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ + meta_ADS, /* Gauntlet Dark Legends (GC) */ + meta_PS2_SPS, /* Ape Escape 2 */ + meta_PS2_XA2_RRP, /* RC Revenge Pro */ + meta_PS2_STM, /* Red Dead Revolver .stm, renamed .ps2stm */ + meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ + meta_UBI_CKD, /* Ubisoft CKD RIFF header from Rayman Origins */ + + meta_XBOX_WAVM, /* XBOX WAVM File */ + meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */ + meta_XBOX_WVS, /* XBOX WVS */ + meta_NGC_WVS, /* NGC WVS */ + meta_XBOX_STMA, /* XBOX STMA */ + meta_XBOX_MATX, /* XBOX MATX */ + meta_XBOX_XMU, /* XBOX XMU */ + meta_XBOX_XVAS, /* XBOX VAS */ + + meta_EAXA_R2, /* EA XA Release 2 */ + meta_EAXA_R3, /* EA XA Release 3 */ + meta_EAXA_PSX, /* EA with PSX ADPCM */ + meta_EACS_PC, /* EACS PC */ + meta_EACS_PSX, /* EACS PSX */ + meta_EACS_SAT, /* EACS SATURN */ + meta_EA_ADPCM, /* EA XA ADPCM */ + meta_EA_IMA, /* EA IMA */ + meta_EA_PCM, /* EA PCM */ + + meta_RAW, /* RAW PCM file */ + + meta_GENH, /* generic header */ + +#ifdef VGM_USE_VORBIS + meta_ogg_vorbis, /* ogg vorbis */ + meta_OGG_SLI, /* Ogg Vorbis file w/ companion .sli for looping */ + meta_OGG_SLI2, /* Ogg Vorbis file w/ different styled .sli for looping */ + meta_OGG_SFL, /* Ogg Vorbis file w/ .sfl (RIFF SFPL) for looping */ + meta_um3_ogg, /* Ogg Vorbis with first 0x800 bytes XOR 0xFF */ + meta_KOVS_ogg, /* Ogg Vorbis with exta header and 0x100 bytes XOR */ + meta_psych_ogg, /* Ogg Vorbis with all bytes -0x23*/ +#endif + + meta_AIFC, /* Audio Interchange File Format AIFF-C */ + meta_AIFF, /* Audio Interchange File Format */ + meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */ + meta_WS_AUD, /* Westwood Studios .aud */ + meta_WS_AUD_old, /* Westwood Studios .aud, old style */ +#ifdef VGM_USE_MPEG + meta_AHX, /* CRI AHX header (same structure as ADX) */ +#endif + meta_RIFF_WAVE, /* RIFF, for WAVs */ + meta_RIFF_WAVE_POS, /* .wav + .pos for looping */ + meta_RIFF_WAVE_labl_Marker, /* RIFF w/ loop Markers in LIST-adtl-labl */ + meta_RIFF_WAVE_smpl, /* RIFF w/ loop data in smpl chunk */ + meta_RIFF_WAVE_MWV, /* .mwv RIFF w/ loop data in ctrl chunk pflt */ + meta_RIFF_WAVE_SNS, /* .sns RIFF */ + meta_RIFX_WAVE, /* RIFX, for big-endian WAVs */ + meta_RIFX_WAVE_smpl, /* RIFX w/ loop data in smpl chunk */ + meta_XNBm, /* XNBm, which has a RIFF fmt chunk */ + meta_PC_MXST, /* Lego Island MxSt */ + meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */ + meta_NWA, /* Visual Art's NWA */ + meta_NWA_NWAINFOINI, /* NWA w/ NWAINFO.INI for looping */ + meta_NWA_GAMEEXEINI, /* NWA w/ Gameexe.ini for looping */ + meta_DVI, /* DVI Interleaved */ + meta_KCEY, /* KCEYCOMP */ + meta_ACM, /* InterPlay ACM header */ + meta_MUS_ACM, /* MUS playlist of InterPlay ACM files */ + meta_DE2, /* Falcom (Gurumin) .de2 */ + meta_VS, /* Men in Black .vs */ + meta_FFXI_BGW, /* FFXI BGW */ + meta_FFXI_SPW, /* FFXI SPW */ + meta_STS_WII, /* Shikigami No Shiro 3 STS Audio File */ + meta_PS2_P2BT, /* Pop'n'Music 7 Audio File */ + meta_PS2_GBTS, /* Pop'n'Music 9 Audio File */ + meta_NGC_DSP_IADP, /* Gamecube Interleave DSP */ + meta_PS2_TK5, /* Tekken 5 Stream Files */ + meta_WII_STR, /* House of The Dead Overkill STR+STH */ + meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ + meta_ZSD, /* Dragon Booster ZSD */ + meta_RedSpark, /* "RedSpark" RSD (MadWorld) */ + meta_PC_IVAUD, /* .ivaud GTA IV */ + meta_NDS_HWAS, /* Spider-Man 3, Tony Hawk's Downhill Jam, possibly more... */ + meta_NGC_LPS, /* Rave Master (Groove Adventure Rave)(GC) */ + meta_NAOMI_ADPCM, /* NAOMI/NAOMI2 ARcade games */ + meta_SD9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ + meta_2DX9, /* beatmaniaIIDX16 - EMPRESS (Arcade) */ + meta_PS2_VGV, /* Rune: Viking Warlord */ + meta_NGC_GCUB, /* Sega Soccer Slam */ + meta_MAXIS_XA, /* Sim City 3000 (PC) */ + meta_NGC_SCK_DSP, /* Scorpion King (NGC) */ + meta_CAFF, /* iPhone .caf */ + meta_EXAKT_SC, /* Activision EXAKT .SC (PS2) */ + meta_WII_WAS, /* DiRT 2 (WII) */ + meta_PONA_3DO, /* Policenauts (3DO) */ + meta_PONA_PSX, /* Policenauts (PSX) */ + meta_XBOX_HLWAV, /* Half Life 2 (XBOX) */ + meta_PS2_AST, /* Some KOEI game (PS2) */ + meta_DMSG, /* Nightcaster II - Equinox (XBOX) */ + meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */ + meta_PS2_STER, /* Juuni Kokuki: Kakukaku Taru Ou Michi Beni Midori no Uka */ + meta_PS2_WB, /* Shooting Love. ~TRIZEAL~ */ + meta_S14, /* raw Siren 14, 24kbit mono */ + meta_SSS, /* raw Siren 14, 48kbit stereo */ + meta_PS2_GCM, /* NamCollection */ + meta_PS2_SMPL, /* Homura */ + meta_PS2_MSA, /* Psyvariar -Complete Edition- */ + meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */ + meta_PS2_KHV, /* Kingdom Hearts 2 VAG streams */ + meta_PC_SMP, /* Ghostbusters PC .smp */ + meta_P3D, /* Prototype P3D */ + meta_PS2_TK1, /* Tekken (NamCollection) */ + meta_PS2_ADSC, /* Kenka Bancho 2: Full Throttle */ + meta_NGC_BO2, /* Blood Omen 2 (NGC) */ + meta_DSP_DDSP, /* Various (2 dsp files stuck together */ + meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */ + meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */ + meta_PSX_MGAV, /* Future Cop L.A.P.D. */ + meta_NGC_DSP_STH_STR, /* SpongeBob Squarepants (NGC), Taz Wanted (NGC), Cubix (NGC), Tak (WII)*/ + meta_PS2_B1S, /* 7 Wonders of the ancient world */ + meta_PS2_WAD, /* The golden Compass */ + meta_DSP_XIII, /* XIII, possibly more (Ubisoft header???) */ + meta_DSP_CABELAS, /* Cabelas games */ + meta_PS2_ADM, /* Dragon Quest 5 */ + meta_PS2_LPCM, /* Ah! My Goddess */ + meta_DSP_BDSP, /* Ah! My Goddess */ + meta_PS2_VMS, /* Autobahn Raser - Police Madness */ + meta_PS2_XAU, // Spectral Force Chronicle + meta_GH3_BAR, /* Guitar Hero III Mobile .bar */ + meta_FFW, /* Freedom Fighters [NGC] */ + meta_DSP_DSPW, /* Sengoku Basara 3 [WII] */ + meta_PS2_JSTM, /* Tantei Jinguji Saburo - Kind of Blue (PS2) */ + meta_SQEX_SCD, /* Square-Enix SCD */ + meta_NGC_NST_DSP, /* Animaniacs [NGC] */ + meta_BAF, /* .baf (Blur) */ + meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */ + meta_PS3_CPS, /* Eternal Sonata (PS3) */ + meta_PS3_MSF, /* MSF header */ + meta_NUB_VAG, /* VAG from Nub archives */ + meta_PS3_PAST, /* Bakugan Battle Brawlers (PS3) */ + meta_PS3_SGH_SGB, /* Folklore (PS3) */ + meta_NGCA, /* GoldenEye 007 (Wii) */ + meta_WII_RAS, /* Donkey Kong Country Returns (Wii) */ + meta_PS2_SPM, /* Lethal Skies Elite Pilot: Team SW */ + meta_X360_TRA, /* Def Jam Rapstar */ + meta_PS2_VGS, // Princess Soft PS2 games + meta_PS2_IAB, // Ueki no Housoku - Taosu ze Robert Juudan!! (PS2) + meta_PS2_STRLR, + meta_LSF_N1NJ4N, /* .lsf n1nj4n Fastlane Street Racing (iPhone) */ + meta_PS3_VAWX, // No More Heroes: Heroes Paradise (PS3) + meta_PC_SNDS, // Incredibles PC .snds + meta_PS2_WMUS, // The Warriors (PS2) + meta_HYPERSCAN_KVAG, // Hyperscan KVAG/BVG + meta_IOS_PSND, // Crash Bandicoot Nitro Kart 2 (iOS) + meta_BOS_ADP, // ADP! (Balls of Steel, PC) + meta_EB_SFX, // Excitebots .sfx + meta_EB_SF0, // Excitebots .sf0 + meta_PS3_KLBS, // L@VE ONCE (PS3) + meta_PS3_SGX, // Boku no Natsuyasumi 3 (PS3) + meta_PS2_MTAF, // Metal Gear Solid 3 MTAF + meta_PS2_VAG1, // Metal Gear Solid 3 VAG1 + meta_PS2_VAG2, // Metal Gear Solid 3 VAG2 + meta_TUN, // LEGO Racers (PC) + meta_WPD, // Shuffle! (PC) + meta_MN_STR, // Mini Ninjas (PC/PS3/WII) + meta_PS2_MSS, // ShellShock Nam '67 (PS2) + meta_PS2_HSF, // Lowrider (PS2) + meta_PS3_IVAG, // Interleaved VAG files (PS3) + meta_PS2_2PFS, // Mahoromatic: Moetto - KiraKira Maid-San (PS2) + meta_PS2_VBK, + meta_OTM, // Otomedius (Arcade) + meta_CSTM, // Nintendo 3DS CSTM +#ifdef VGM_USE_MP4V2 + meta_MP4, +#endif +} meta_t; + +typedef struct { + STREAMFILE * streamfile; /* file used by this channel */ + off_t channel_start_offset; /* where data for this channel begins */ + off_t offset; /* current location in the file */ + + off_t frame_header_offset; /* offset of the current frame header (for WS) */ + int samples_left_in_frame; /* for WS */ + + /* format specific */ + + /* adpcm */ + int16_t adpcm_coef[16]; /* for formats with decode coefficients built in */ + int32_t adpcm_coef_3by32[0x60]; /* for Level-5 0x555 */ + union { + int16_t adpcm_history1_16; /* previous sample */ + int32_t adpcm_history1_32; + }; + union { + int16_t adpcm_history2_16; /* previous previous sample */ + int32_t adpcm_history2_32; + }; + union { + int16_t adpcm_history3_16; + int32_t adpcm_history3_32; + }; + + double adpcm_history1_double; + double adpcm_history2_double; + + int adpcm_step_index; /* for IMA */ + int adpcm_scale; /* for MS ADPCM */ + + struct g72x_state g72x_state; /* state for G.721 decoder, sort of big but we + might as well keep it around */ + +#ifdef DEBUG + int samples_done; + int16_t loop_history1,loop_history2; +#endif + + /* ADX encryption */ + int adx_channels; + uint16_t adx_xor; + uint16_t adx_mult; + uint16_t adx_add; + + /* BMDX encryption */ + uint8_t bmdx_xor; + uint8_t bmdx_add; + + /* generic encryption */ + uint16_t key_xor; +} VGMSTREAMCHANNEL; + +typedef struct { + /* basics */ + int32_t num_samples; /* the actual number of samples in this stream */ + int32_t sample_rate; /* sample rate in Hz */ + int channels; /* number of channels */ + coding_t coding_type; /* type of encoding */ + layout_t layout_type; /* type of layout for data */ + meta_t meta_type; /* how we know the metadata */ + + /* looping */ + int loop_flag; /* is this stream looped? */ + int32_t loop_start_sample; /* first sample of the loop (included in the loop) */ + int32_t loop_end_sample; /* last sample of the loop (not included in the loop) */ + + /* channels */ + VGMSTREAMCHANNEL * ch; /* pointer to array of channels */ + + /* channel copies */ + VGMSTREAMCHANNEL * start_ch; /* copies of channel status as they were at the beginning of the stream */ + VGMSTREAMCHANNEL * loop_ch; /* copies of channel status as they were at the loop point */ + + /* layout-specific */ + int32_t current_sample; /* number of samples we've passed */ + int32_t samples_into_block; /* number of samples into the current block */ + /* interleave */ + size_t interleave_block_size; /* interleave for this file */ + size_t interleave_smallblock_size; /* smaller interleave for last block */ + /* headered blocks */ + off_t current_block_offset; /* start of this block (offset of block header) */ + size_t current_block_size; /* size of the block we're in now */ + off_t next_block_offset; /* offset of header of the next block */ + int block_count; /* count of "semi" block in total block */ + + int hit_loop; /* have we seen the loop yet? */ + + /* loop layout (saved values) */ + int32_t loop_sample; /* saved from current_sample, should be loop_start_sample... */ + int32_t loop_samples_into_block; /* saved from samples_into_block */ + off_t loop_block_offset; /* saved from current_block_offset */ + size_t loop_block_size; /* saved from current_block_size */ + off_t loop_next_block_offset; /* saved from next_block_offset */ + + uint8_t xa_channel; /* Selected XA Channel */ + int32_t xa_sector_length; /* XA block */ + uint8_t xa_headerless; /* headerless XA block */ + int8_t get_high_nibble; + + uint8_t ea_big_endian; /* Big Endian ? */ + uint8_t ea_compression_type; + uint8_t ea_compression_version; + uint8_t ea_platform; + + int32_t ws_output_size; /* output bytes for this block */ + + void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */ + + int32_t thpNextFrameSize; + + int skip_last_channel; + + /* Data the codec needs for the whole stream. This is for codecs too + * different from vgmstream's structure to be reasonably shoehorned into + * using the ch structures. + * Note also that support must be added for resetting, looping and + * closing for every codec that uses this, as it will not be handled. */ + void * codec_data; +} VGMSTREAM; + +#ifdef VGM_USE_VORBIS +typedef struct { + STREAMFILE *streamfile; + ogg_int64_t offset; + ogg_int64_t size; + ogg_int64_t other_header_bytes; + + // XOR setup with a single byte (SCD) + unsigned char scd_xor; + ogg_int64_t scd_xor_len; +} ogg_vorbis_streamfile; + +typedef struct { + OggVorbis_File ogg_vorbis_file; + int bitstream; + + ogg_vorbis_streamfile ov_streamfile; +} ogg_vorbis_codec_data; +#endif + +#ifdef VGM_USE_MPEG +#define AHX_EXPECTED_FRAME_SIZE 0x414 +/* MPEG_BUFFER_SIZE should be >= AHX_EXPECTED_FRAME_SIZE */ +#define MPEG_BUFFER_SIZE 0x1000 +typedef struct { + uint8_t buffer[MPEG_BUFFER_SIZE]; + int buffer_used; + int buffer_full; + size_t bytes_in_buffer; + mpg123_handle *m; +} mpeg_codec_data; +#endif + +#ifdef VGM_USE_G7221 +typedef struct { + sample buffer[640]; + g7221_handle *handle; +} g7221_codec_data; +#endif + +#ifdef VGM_USE_MAIATRAC3PLUS +typedef struct { + sample *buffer; + int channels; + int samples_discard; + void *handle; +} maiatrac3plus_codec_data; +#endif + +/* with one file this is also used for just + ACM */ +typedef struct { + int file_count; + int current_file; + /* the index we return to upon loop completion */ + int loop_start_file; + /* one after the index of the last file, typically + * will be equal to file_count */ + int loop_end_file; + /* Upon exit from a loop, which file to play. */ + /* -1 if there is no such file */ + /*int end_file;*/ + ACMStream **files; +} mus_acm_codec_data; + +#define AIX_BUFFER_SIZE 0x1000 +/* AIXery */ +typedef struct { + sample buffer[AIX_BUFFER_SIZE]; + int segment_count; + int stream_count; + int current_segment; + /* one per segment */ + int32_t *sample_counts; + /* organized like: + * segment1_stream1, segment1_stream2, segment2_stream1, segment2_stream2*/ + VGMSTREAM **adxs; +} aix_codec_data; + +typedef struct { + int segment_count; + int current_segment; + int loop_segment; + /* one per segment */ + int32_t *sample_counts; + VGMSTREAM **adxs; +} aax_codec_data; + +/* for compressed NWA */ +typedef struct { + NWAData *nwa; +} nwa_codec_data; + +typedef struct { + int substream_count; + VGMSTREAM **substreams; + STREAMFILE **intfiles; +} scd_int_codec_data; + +#ifdef VGM_USE_MP4V2 +typedef struct { + STREAMFILE *streamfile; + uint64_t start; + uint64_t offset; + uint64_t size; +} mp4_streamfile; + +#ifdef VGM_USE_FDKAAC +typedef struct { + mp4_streamfile if_file; + MP4FileHandle h_mp4file; + MP4TrackId track_id; + unsigned long sampleId, numSamples; + UINT codec_init_data_size; + HANDLE_AACDECODER h_aacdecoder; + unsigned int sample_ptr, samples_per_frame, samples_discard; + INT_PCM sample_buffer[( (6) * (2048)*4 )]; +} mp4_aac_codec_data; +#endif +#endif + +/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */ +VGMSTREAM * init_vgmstream(const char * const filename); + +VGMSTREAM * init_vgmstream_from_STREAMFILE(STREAMFILE *streamFile); + +/* reset a VGMSTREAM to start of stream */ +void reset_vgmstream(VGMSTREAM * vgmstream); + +/* allocate a VGMSTREAM and channel stuff */ +VGMSTREAM * allocate_vgmstream(int channel_count, int looped); + +/* deallocate, close, etc. */ +void close_vgmstream(VGMSTREAM * vgmstream); + +/* calculate the number of samples to be played based on looping parameters */ +int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM * vgmstream); + +/* render! */ +void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream); + +/* smallest self-contained group of samples is a frame */ +int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream); +/* number of bytes per frame */ +int get_vgmstream_frame_size(VGMSTREAM * vgmstream); +/* in NDS IMA the frame size is the block size, so the last one is short */ +int get_vgmstream_samples_per_shortframe(VGMSTREAM * vgmstream); +int get_vgmstream_shortframe_size(VGMSTREAM * vgmstream); + +/* Assume that we have written samples_written into the buffer already, and we have samples_to_do consecutive + * samples ahead of us. Decode those samples into the buffer. */ +void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer); + +/* Assume additionally that we have samples_to_do consecutive samples in "data", + * and this this is for channel number "channel" */ +void decode_vgmstream_mem(VGMSTREAM * vgmstream, int samples_written, int samples_to_do, sample * buffer, uint8_t * data, int channel); + +/* calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ +int vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM * vgmstream); + +/* Detect start and save values, also detect end and restore values. Only works on exact sample values. + * Returns 1 if loop was done. */ +int vgmstream_do_loop(VGMSTREAM * vgmstream); + +/* Write a description of the stream into array pointed by desc, + * which must be length bytes long. Will always be null-terminated if length > 0 + */ +void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length); + +/* See if there is a second file which may be the second channel, given + * already opened mono opened_stream which was opened from filename. + * If a suitable file is found, open it and change opened_stream to a + * stereo stream. */ +void try_dual_file_stereo(VGMSTREAM * opened_stream, STREAMFILE *streamFile); + +#endif diff --git a/Frameworks/vgmstream/vgmstream/vgmstream-Info.plist b/Frameworks/vgmstream/vgmstream/vgmstream-Info.plist new file mode 100644 index 000000000..30d0c6cfa --- /dev/null +++ b/Frameworks/vgmstream/vgmstream/vgmstream-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + NoWork-Inc.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2014 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj b/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj new file mode 100644 index 000000000..a05aa28e1 --- /dev/null +++ b/Plugins/vgmstream/vgmstream.xcodeproj/project.pbxproj @@ -0,0 +1,354 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 836F6B1418BDB80D0095E648 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 836F6B1318BDB80D0095E648 /* Cocoa.framework */; }; + 836F6B1E18BDB80D0095E648 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 836F6B1C18BDB80D0095E648 /* InfoPlist.strings */; }; + 836F705C18BDC40E0095E648 /* VGMDecoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 836F705B18BDC40E0095E648 /* VGMDecoder.m */; }; + 836F705D18BDC4580095E648 /* vgmstream.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 836F6B6D18BDB8890095E648 /* vgmstream.framework */; }; + 836F705F18BDC47F0095E648 /* vgmstream.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836F6B6D18BDB8890095E648 /* vgmstream.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 836F6B6C18BDB8890095E648 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 836F6B6718BDB8880095E648 /* vgmstream.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 836F6B3918BDB8880095E648; + remoteInfo = vgmstream; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 836F705E18BDC4710095E648 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 836F705F18BDC47F0095E648 /* vgmstream.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 836F6B1018BDB80D0095E648 /* vgmstream.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = vgmstream.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; + 836F6B1318BDB80D0095E648 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + 836F6B1618BDB80D0095E648 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 836F6B1718BDB80D0095E648 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + 836F6B1818BDB80D0095E648 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + 836F6B1B18BDB80D0095E648 /* vgmstream-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "vgmstream-Info.plist"; sourceTree = ""; }; + 836F6B1D18BDB80D0095E648 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + 836F6B1F18BDB80D0095E648 /* vgmstream-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "vgmstream-Prefix.pch"; sourceTree = ""; }; + 836F6B6718BDB8880095E648 /* vgmstream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vgmstream.xcodeproj; path = ../../Frameworks/vgmstream/vgmstream.xcodeproj; sourceTree = ""; }; + 836F705A18BDC40E0095E648 /* VGMDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VGMDecoder.h; sourceTree = ""; }; + 836F705B18BDC40E0095E648 /* VGMDecoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VGMDecoder.m; sourceTree = ""; }; + 836F706018BDC84D0095E648 /* Plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Plugin.h; path = ../../../Audio/Plugin.h; sourceTree = ""; }; + 836F706118BDC8650095E648 /* PlaylistController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PlaylistController.h; path = ../../../Playlist/PlaylistController.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 836F6B0D18BDB80D0095E648 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F705D18BDC4580095E648 /* vgmstream.framework in Frameworks */, + 836F6B1418BDB80D0095E648 /* Cocoa.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 836F6B0718BDB80D0095E648 = { + isa = PBXGroup; + children = ( + 836F6B1918BDB80D0095E648 /* vgmstream */, + 836F6B1218BDB80D0095E648 /* Frameworks */, + 836F6B1118BDB80D0095E648 /* Products */, + ); + sourceTree = ""; + }; + 836F6B1118BDB80D0095E648 /* Products */ = { + isa = PBXGroup; + children = ( + 836F6B1018BDB80D0095E648 /* vgmstream.bundle */, + ); + name = Products; + sourceTree = ""; + }; + 836F6B1218BDB80D0095E648 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 836F6B1318BDB80D0095E648 /* Cocoa.framework */, + 836F6B1518BDB80D0095E648 /* Other Frameworks */, + 836F6B6718BDB8880095E648 /* vgmstream.xcodeproj */, + ); + name = Frameworks; + sourceTree = ""; + }; + 836F6B1518BDB80D0095E648 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + 836F6B1618BDB80D0095E648 /* Foundation.framework */, + 836F6B1718BDB80D0095E648 /* CoreData.framework */, + 836F6B1818BDB80D0095E648 /* AppKit.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + 836F6B1918BDB80D0095E648 /* vgmstream */ = { + isa = PBXGroup; + children = ( + 836F706118BDC8650095E648 /* PlaylistController.h */, + 836F706018BDC84D0095E648 /* Plugin.h */, + 836F705A18BDC40E0095E648 /* VGMDecoder.h */, + 836F705B18BDC40E0095E648 /* VGMDecoder.m */, + 836F6B1A18BDB80D0095E648 /* Supporting Files */, + ); + path = vgmstream; + sourceTree = ""; + }; + 836F6B1A18BDB80D0095E648 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 836F6B1B18BDB80D0095E648 /* vgmstream-Info.plist */, + 836F6B1C18BDB80D0095E648 /* InfoPlist.strings */, + 836F6B1F18BDB80D0095E648 /* vgmstream-Prefix.pch */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 836F6B6818BDB8880095E648 /* Products */ = { + isa = PBXGroup; + children = ( + 836F6B6D18BDB8890095E648 /* vgmstream.framework */, + ); + name = Products; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 836F6B0F18BDB80D0095E648 /* vgmstream */ = { + isa = PBXNativeTarget; + buildConfigurationList = 836F6B2218BDB80D0095E648 /* Build configuration list for PBXNativeTarget "vgmstream" */; + buildPhases = ( + 836F6B0C18BDB80D0095E648 /* Sources */, + 836F6B0D18BDB80D0095E648 /* Frameworks */, + 836F6B0E18BDB80D0095E648 /* Resources */, + 836F705E18BDC4710095E648 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = vgmstream; + productName = vgmstream; + productReference = 836F6B1018BDB80D0095E648 /* vgmstream.bundle */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 836F6B0818BDB80D0095E648 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Christopher Snowhill"; + }; + buildConfigurationList = 836F6B0B18BDB80D0095E648 /* Build configuration list for PBXProject "vgmstream" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 836F6B0718BDB80D0095E648; + productRefGroup = 836F6B1118BDB80D0095E648 /* Products */; + projectDirPath = ""; + projectReferences = ( + { + ProductGroup = 836F6B6818BDB8880095E648 /* Products */; + ProjectRef = 836F6B6718BDB8880095E648 /* vgmstream.xcodeproj */; + }, + ); + projectRoot = ""; + targets = ( + 836F6B0F18BDB80D0095E648 /* vgmstream */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXReferenceProxy section */ + 836F6B6D18BDB8890095E648 /* vgmstream.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = vgmstream.framework; + remoteRef = 836F6B6C18BDB8890095E648 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; +/* End PBXReferenceProxy section */ + +/* Begin PBXResourcesBuildPhase section */ + 836F6B0E18BDB80D0095E648 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F6B1E18BDB80D0095E648 /* InfoPlist.strings in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 836F6B0C18BDB80D0095E648 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 836F705C18BDC40E0095E648 /* VGMDecoder.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 836F6B1C18BDB80D0095E648 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + 836F6B1D18BDB80D0095E648 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 836F6B2018BDB80D0095E648 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 836F6B2118BDB80D0095E648 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + SDKROOT = macosx; + }; + name = Release; + }; + 836F6B2318BDB80D0095E648 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "vgmstream/vgmstream-Prefix.pch"; + INFOPLIST_FILE = "vgmstream/vgmstream-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Debug; + }; + 836F6B2418BDB80D0095E648 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_OBJC_ARC = NO; + COMBINE_HIDPI_IMAGES = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "vgmstream/vgmstream-Prefix.pch"; + INFOPLIST_FILE = "vgmstream/vgmstream-Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = bundle; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 836F6B0B18BDB80D0095E648 /* Build configuration list for PBXProject "vgmstream" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836F6B2018BDB80D0095E648 /* Debug */, + 836F6B2118BDB80D0095E648 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 836F6B2218BDB80D0095E648 /* Build configuration list for PBXNativeTarget "vgmstream" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 836F6B2318BDB80D0095E648 /* Debug */, + 836F6B2418BDB80D0095E648 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 836F6B0818BDB80D0095E648 /* Project object */; +} diff --git a/Plugins/vgmstream/vgmstream/VGMDecoder.h b/Plugins/vgmstream/vgmstream/VGMDecoder.h new file mode 100644 index 000000000..206ce24cc --- /dev/null +++ b/Plugins/vgmstream/vgmstream/VGMDecoder.h @@ -0,0 +1,26 @@ +// +// VGMDecoder.h +// vgmstream +// +// Created by Christopher Snowhill on 02/25/14. +// Copyright 2014 __NoWork, Inc__. All rights reserved. +// + +#import + +#import +#import + +#import "Plugin.h" + +@interface VGMDecoder : NSObject { + VGMSTREAM *stream; + + int sampleRate; + int channels; + long totalFrames; + long framesLength; + long framesFade; + long framesRead; +} +@end diff --git a/Plugins/vgmstream/vgmstream/VGMDecoder.m b/Plugins/vgmstream/vgmstream/VGMDecoder.m new file mode 100644 index 000000000..1c86ce6bc --- /dev/null +++ b/Plugins/vgmstream/vgmstream/VGMDecoder.m @@ -0,0 +1,227 @@ +// +// VGMDecoder.m +// vgmstream +// +// Created by Christopher Snowhill on 02/25/14. +// Copyright 2014 __NoWork, Inc__. All rights reserved. +// + +#import "VGMDecoder.h" + +#import "PlaylistController.h" + +typedef struct _COGSTREAMFILE { + STREAMFILE sf; + id file; + off_t offset; + char name[PATH_LIMIT]; +} COGSTREAMFILE; + +static void cogsf_seek(COGSTREAMFILE *this, off_t offset) { + if ([this->file seek:offset whence:SEEK_SET] != 0) + this->offset = offset; + else + this->offset = [this->file tell]; +} + +static off_t cogsf_get_size(COGSTREAMFILE *this) { + off_t offset = [this->file tell]; + [this->file seek:0 whence:SEEK_END]; + off_t size = [this->file tell]; + [this->file seek:offset whence:SEEK_SET]; + return size; +} + +static off_t cogsf_get_offset(COGSTREAMFILE *this) { + return this->offset; +} + +static void cogsf_get_name(COGSTREAMFILE *this, char *buffer, size_t length) { + strncpy(buffer, this->name, length); + buffer[length-1]='\0'; +} + +static size_t cogsf_read(COGSTREAMFILE *this, uint8_t *dest, off_t offset, size_t length) { + size_t read; + if (this->offset != offset) + cogsf_seek(this, offset); + read = [this->file read:dest amount:length]; + if (read > 0) + this->offset += read; + return read; +} + +static void cogsf_close(COGSTREAMFILE *this) { + [this->file release]; + free(this); +} + +static STREAMFILE *cogsf_create_from_path(const char *path); +static STREAMFILE *cogsf_open(COGSTREAMFILE *this, const char *const filename,size_t buffersize) { + if (!filename) return NULL; + return cogsf_create_from_path(filename); +} + +static STREAMFILE *cogsf_create(id file, const char *path) { + COGSTREAMFILE *streamfile = malloc(sizeof(COGSTREAMFILE)); + + if (!streamfile) return NULL; + + memset(streamfile,0,sizeof(COGSTREAMFILE)); + streamfile->sf.read = (void*)cogsf_read; + streamfile->sf.get_size = (void*)cogsf_get_size; + streamfile->sf.get_offset = (void*)cogsf_get_offset; + streamfile->sf.get_name = (void*)cogsf_get_name; + streamfile->sf.get_realname = (void*)cogsf_get_name; + streamfile->sf.open = (void*)cogsf_open; + streamfile->sf.close = (void*)cogsf_close; + streamfile->file = [file retain]; + streamfile->offset = 0; + strncpy(streamfile->name, path, sizeof(streamfile->name)); + + return &streamfile->sf; +} + +STREAMFILE *cogsf_create_from_path(const char *path) { + id source; + NSString * urlString = [NSString stringWithUTF8String:path]; + NSURL * url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + + id audioSourceClass = NSClassFromString(@"AudioSource"); + source = [audioSourceClass audioSourceForURL:url]; + + if (![source open:url]) + return 0; + + if (![source seekable]) + return 0; + + return cogsf_create(source, path); +} + +VGMSTREAM *init_vgmstream_from_cogfile(const char *path) { + STREAMFILE *sf; + VGMSTREAM *vgm; + + sf = cogsf_create_from_path(path); + if (!sf) return NULL; + + vgm = init_vgmstream_from_STREAMFILE(sf); + if (!vgm) goto err1; + + return vgm; +err1: + cogsf_close((COGSTREAMFILE *)sf); + return NULL; +} + +@implementation VGMDecoder + +- (BOOL)open:(id)s +{ + stream = init_vgmstream_from_cogfile([[[[s url] absoluteString] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] UTF8String]); + if ( !stream ) + return NO; + + sampleRate = stream->sample_rate; + channels = stream->channels; + totalFrames = get_vgmstream_play_samples( 2.0, 10.0, 10.0, stream ); + framesFade = sampleRate * 10; + framesLength = totalFrames - framesFade; + + framesRead = 0; + + [self willChangeValueForKey:@"properties"]; + [self didChangeValueForKey:@"properties"]; + + return YES; +} + +- (NSDictionary *)properties +{ + return [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithInt:0], @"bitrate", + [NSNumber numberWithInt:sampleRate], @"sampleRate", + [NSNumber numberWithDouble:totalFrames], @"totalFrames", + [NSNumber numberWithInt:16], @"bitsPerSample", + [NSNumber numberWithBool:NO], @"floatingPoint", + [NSNumber numberWithInt:channels], @"channels", + [NSNumber numberWithBool:YES], @"seekable", + @"host", @"endian", + nil]; +} + +- (int)readAudio:(void *)buf frames:(UInt32)frames +{ + BOOL repeatone = IsRepeatOneSet(); + + if (!repeatone && framesRead >= totalFrames) + return 0; + + sample * sbuf = (sample *) buf; + + render_vgmstream( sbuf, frames, stream ); + + if ( !repeatone && framesRead + frames > framesLength ) { + long fadeStart = (framesLength > framesRead) ? framesLength : framesRead; + long fadeEnd = (framesRead + frames) > totalFrames ? totalFrames : (framesRead + frames); + long fadePos; + + int fadeScale = (int)((float)(totalFrames - fadeStart) / (float)framesFade * 65536.0f); + float fadeStep = (int)(1.0f / (float)framesFade * 65536.0f); + for (fadePos = fadeStart; fadePos < fadeEnd; ++fadePos) { + sbuf[ 0 ] = sbuf[ 0 ] * fadeScale / 65536; + sbuf[ 1 ] = sbuf[ 1 ] * fadeScale / 65536; + sbuf += 2; + fadeScale -= fadeStep; + if (fadeScale <= 0) break; + } + frames = (UInt32)(fadePos - fadeStart); + } + + framesRead += frames; + + return frames; +} + +- (long)seek:(long)frame +{ + if (frame < framesRead) { + reset_vgmstream( stream ); + framesRead = 0; + } + + while (framesRead < frame) { + sample buffer[1024]; + long max_sample_count = 1024 / channels; + long samples_to_skip = frame - framesRead; + if ( samples_to_skip > max_sample_count ) + samples_to_skip = max_sample_count; + render_vgmstream( buffer, (int)samples_to_skip, stream ); + framesRead += samples_to_skip; + } + + return framesRead; +} + +- (void)close +{ + close_vgmstream( stream ); +} + ++ (NSArray *)fileTypes +{ + return [NSArray arrayWithObjects:@"2dx9", @"aaap", @"aax", @"acm", @"adp", @"adpcm", @"ads", @"adx", @"afc", @"agsc", @"ahx",@"aifc", @"aiff", @"aix", @"amts", @"as4", @"asd", @"asf", @"asr", @"ass", @"ast", @"aud", @"aus", @"baf", @"baka", @"bar", @"bcstm", @"bcwav", @"bg00", @"bgw", @"bh2pcm", @"bmdx", @"bns", @"bnsf", @"bo2", @"brstm", @"caf", @"capdsp", @"ccc", @"cfn", @"cnk", @"dcs", @"dcsw", @"ddsp", @"de2", @"dmsg", @"dsp", @"dvi", @"dxh", @"eam", @"emff", @"enth", @"fag", @"filp", @"fsb", @"gca", @"gcm", @"gcsw", @"gcw", @"genh", @"gms", @"gsp", @"hgc1", @"his", @"hps", @"hwas", @"idsp", @"idvi", @"ikm", @"ild", @"int", @"isd", @"ish", @"ivaud", @"ivb", @"joe", @"kces", @"kcey", @"khv", @"kraw", @"leg", @"logg", @"lps", @"lsf", @"lwav", @"matx", @"mcg", @"mi4", @"mib", @"mic", @"mihb", @"mpdsp", @"msa", @"mss", @"msvp", @"mus", @"musc", @"musx", @"mwv", @"myspd", @"ndp", @"npsf", @"nwa", @"omu", @"otm", @"p3d", @"pcm", @"pdt", @"pnb", @"pos", @"psh", @"psw", @"raw", @"rkv", @"rnd", @"rrds", @"rsd", @"rsf", @"rstm", @"rwar", @"rwav", @"rws", @"rwsd", @"rwx", @"rxw", @"s14", @"sab", @"sad", @"sap", @"sc", @"scd", @"sd9", @"sdt", @"seg", @"sfl", @"sfs", @"sl3", @"sli", @"smp", @"smpl", @"snd", @"sng", @"sns", @"spd", @"sps", @"spsd", @"spt", @"spw", @"ss2", @"ss7", @"ssm", @"sss", @"ster", @"sth", @"stm", @"stma", @"str", @"strm", @"sts", @"stx", @"svag", @"svs", @"swav", @"swd", @"tec", @"thp", @"tk5", @"tydsp", @"um3", @"vag", @"vas", @"vgs", @"vig", @"vjdsp", @"voi", @"vpk", @"vs", @"vsf", @"waa", @"wac", @"wad", @"wam", @"was", @"wavm", @"wb", @"wii", @"wp2", @"wsd", @"wsi", @"wvs", @"xa", @"xa2", @"xa30", @"xmu", @"xss", @"xvas", @"xwav", @"xwb", @"ydsp", @"ymf", @"zsd", @"zwdsp", nil]; +} + ++ (NSArray *)mimeTypes +{ + return nil; +} + ++ (float)priority +{ + return 0.0; +} + +@end diff --git a/Plugins/vgmstream/vgmstream/en.lproj/InfoPlist.strings b/Plugins/vgmstream/vgmstream/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/Plugins/vgmstream/vgmstream/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/Plugins/vgmstream/vgmstream/vgmstream-Info.plist b/Plugins/vgmstream/vgmstream/vgmstream-Info.plist new file mode 100644 index 000000000..00a2af9aa --- /dev/null +++ b/Plugins/vgmstream/vgmstream/vgmstream-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + NoWork-Inc.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2014 Christopher Snowhill. All rights reserved. + NSPrincipalClass + + + diff --git a/Plugins/vgmstream/vgmstream/vgmstream-Prefix.pch b/Plugins/vgmstream/vgmstream/vgmstream-Prefix.pch new file mode 100644 index 000000000..35d76409f --- /dev/null +++ b/Plugins/vgmstream/vgmstream/vgmstream-Prefix.pch @@ -0,0 +1,9 @@ +// +// Prefix header +// +// The contents of this file are implicitly included at the beginning of every source file. +// + +#ifdef __OBJC__ + #import +#endif