aboutsummaryrefslogtreecommitdiff
path: root/lib/vgmstream
diff options
context:
space:
mode:
authortheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
committertheuni <theuni-nospam-@xbmc.org>2011-01-24 16:05:21 -0500
commitc51b1189e3d5353e842991f5859ddcea0f73e426 (patch)
treeef2cb8a6184699aa614f3655dca4ce661cdc108e /lib/vgmstream
parentbe61ebdc9e897fe40c6f371111724de79ddee8d5 (diff)
Merged cptspiff's code-reshuffle branch.
Squashed commit due to build breakage during code-reshuffle history. Conflicts: xbmc/Util.cpp xbmc/cdrip/CDDARipper.cpp xbmc/filesystem/Directory.cpp xbmc/filesystem/File.cpp
Diffstat (limited to 'lib/vgmstream')
-rw-r--r--lib/vgmstream/COPYING19
-rw-r--r--lib/vgmstream/Makefile.in207
-rw-r--r--lib/vgmstream/XBMCVGM.cpp91
-rw-r--r--lib/vgmstream/ext_includes/pstdint.h728
-rw-r--r--lib/vgmstream/readme.txt148
-rw-r--r--lib/vgmstream/src/coding/acm_decoder.c839
-rw-r--r--lib/vgmstream/src/coding/acm_decoder.h87
-rw-r--r--lib/vgmstream/src/coding/adx_decoder.c81
-rw-r--r--lib/vgmstream/src/coding/aica_decoder.c50
-rw-r--r--lib/vgmstream/src/coding/coding.h83
-rw-r--r--lib/vgmstream/src/coding/eaxa_decoder.c117
-rw-r--r--lib/vgmstream/src/coding/g721_decoder.c471
-rw-r--r--lib/vgmstream/src/coding/g72x_state.h35
-rw-r--r--lib/vgmstream/src/coding/ima_decoder.c273
-rw-r--r--lib/vgmstream/src/coding/l5_555_decoder.c58
-rw-r--r--lib/vgmstream/src/coding/mpeg_decoder.c129
-rw-r--r--lib/vgmstream/src/coding/msadpcm_decoder.c96
-rw-r--r--lib/vgmstream/src/coding/nds_procyon_decoder.c60
-rw-r--r--lib/vgmstream/src/coding/ngc_afc_decoder.c58
-rw-r--r--lib/vgmstream/src/coding/ngc_dsp_decoder.c106
-rw-r--r--lib/vgmstream/src/coding/ngc_dtk_decoder.c53
-rw-r--r--lib/vgmstream/src/coding/nwa_decoder.c352
-rw-r--r--lib/vgmstream/src/coding/nwa_decoder.h67
-rw-r--r--lib/vgmstream/src/coding/ogg_vorbis_decoder.c22
-rw-r--r--lib/vgmstream/src/coding/pcm_decoder.c68
-rw-r--r--lib/vgmstream/src/coding/psx_decoder.c181
-rw-r--r--lib/vgmstream/src/coding/sdx2_decoder.c71
-rw-r--r--lib/vgmstream/src/coding/ws_decoder.c146
-rw-r--r--lib/vgmstream/src/coding/xa_decoder.c72
-rw-r--r--lib/vgmstream/src/layout/aax_layout.c67
-rw-r--r--lib/vgmstream/src/layout/aix_layout.c92
-rw-r--r--lib/vgmstream/src/layout/ast_blocked.c18
-rw-r--r--lib/vgmstream/src/layout/blocked.c126
-rw-r--r--lib/vgmstream/src/layout/caf_blocked.c26
-rw-r--r--lib/vgmstream/src/layout/de2_blocked.c18
-rw-r--r--lib/vgmstream/src/layout/ea_block.c142
-rw-r--r--lib/vgmstream/src/layout/emff_blocked.c34
-rw-r--r--lib/vgmstream/src/layout/filp_blocked.c19
-rw-r--r--lib/vgmstream/src/layout/gsb_blocked.c18
-rw-r--r--lib/vgmstream/src/layout/halpst_blocked.c19
-rw-r--r--lib/vgmstream/src/layout/ims_block.c18
-rw-r--r--lib/vgmstream/src/layout/interleave.c65
-rw-r--r--lib/vgmstream/src/layout/interleave_byte.c62
-rw-r--r--lib/vgmstream/src/layout/layout.h57
-rw-r--r--lib/vgmstream/src/layout/mus_acm_layout.c50
-rw-r--r--lib/vgmstream/src/layout/nolayout.c28
-rw-r--r--lib/vgmstream/src/layout/str_snds_blocked.c54
-rw-r--r--lib/vgmstream/src/layout/thp_blocked.c31
-rw-r--r--lib/vgmstream/src/layout/vs_blocked.c17
-rw-r--r--lib/vgmstream/src/layout/ws_aud_blocked.c24
-rw-r--r--lib/vgmstream/src/layout/wsi_blocked.c23
-rw-r--r--lib/vgmstream/src/layout/xa_blocked.c49
-rw-r--r--lib/vgmstream/src/layout/xvas_block.c24
-rw-r--r--lib/vgmstream/src/libvgmstream.vcproj1027
-rw-r--r--lib/vgmstream/src/meta/Cstr.c303
-rw-r--r--lib/vgmstream/src/meta/aax.c733
-rw-r--r--lib/vgmstream/src/meta/acm.c66
-rw-r--r--lib/vgmstream/src/meta/adx_header.c347
-rw-r--r--lib/vgmstream/src/meta/afc_header.c67
-rw-r--r--lib/vgmstream/src/meta/agsc.c73
-rw-r--r--lib/vgmstream/src/meta/ahx.c121
-rw-r--r--lib/vgmstream/src/meta/aifc.c305
-rw-r--r--lib/vgmstream/src/meta/aix.c410
-rw-r--r--lib/vgmstream/src/meta/ast.c91
-rw-r--r--lib/vgmstream/src/meta/bgw.c140
-rw-r--r--lib/vgmstream/src/meta/brstm.c163
-rw-r--r--lib/vgmstream/src/meta/capdsp.c71
-rw-r--r--lib/vgmstream/src/meta/dc_asd.c75
-rw-r--r--lib/vgmstream/src/meta/dc_idvi.c71
-rw-r--r--lib/vgmstream/src/meta/dc_kcey.c66
-rw-r--r--lib/vgmstream/src/meta/dc_str.c165
-rw-r--r--lib/vgmstream/src/meta/dc_wav_dcs.c116
-rw-r--r--lib/vgmstream/src/meta/de2.c101
-rw-r--r--lib/vgmstream/src/meta/ea_header.c293
-rw-r--r--lib/vgmstream/src/meta/ea_old.c162
-rw-r--r--lib/vgmstream/src/meta/emff.c179
-rw-r--r--lib/vgmstream/src/meta/fsb.c322
-rw-r--r--lib/vgmstream/src/meta/gca.c69
-rw-r--r--lib/vgmstream/src/meta/gcsw.c62
-rw-r--r--lib/vgmstream/src/meta/genh.c398
-rw-r--r--lib/vgmstream/src/meta/gsp_gsb.c111
-rw-r--r--lib/vgmstream/src/meta/halpst.c124
-rw-r--r--lib/vgmstream/src/meta/idsp.c162
-rw-r--r--lib/vgmstream/src/meta/ish_isd.c89
-rw-r--r--lib/vgmstream/src/meta/ivb.c60
-rw-r--r--lib/vgmstream/src/meta/kraw.c63
-rw-r--r--lib/vgmstream/src/meta/meta.h335
-rw-r--r--lib/vgmstream/src/meta/msvp.c70
-rw-r--r--lib/vgmstream/src/meta/mus_acm.c360
-rw-r--r--lib/vgmstream/src/meta/musc.c72
-rw-r--r--lib/vgmstream/src/meta/musx.c342
-rw-r--r--lib/vgmstream/src/meta/naomi_spsd.c72
-rw-r--r--lib/vgmstream/src/meta/nds_sad.c110
-rw-r--r--lib/vgmstream/src/meta/nds_strm.c171
-rw-r--r--lib/vgmstream/src/meta/ngc_adpdtk.c52
-rw-r--r--lib/vgmstream/src/meta/ngc_bh2pcm.c87
-rw-r--r--lib/vgmstream/src/meta/ngc_caf.c75
-rw-r--r--lib/vgmstream/src/meta/ngc_dsp_std.c1232
-rw-r--r--lib/vgmstream/src/meta/ngc_ffcc_str.c85
-rw-r--r--lib/vgmstream/src/meta/ngc_iadp.c0
-rw-r--r--lib/vgmstream/src/meta/ngc_pdt.c79
-rw-r--r--lib/vgmstream/src/meta/ngc_ssm.c96
-rw-r--r--lib/vgmstream/src/meta/ngc_tydsp.c72
-rw-r--r--lib/vgmstream/src/meta/ngc_waa_wac_wad_wam.c100
-rw-r--r--lib/vgmstream/src/meta/ngc_ymf.c77
-rw-r--r--lib/vgmstream/src/meta/nwa.c358
-rw-r--r--lib/vgmstream/src/meta/ogg_vorbis_file.c292
-rw-r--r--lib/vgmstream/src/meta/pcm.c115
-rw-r--r--lib/vgmstream/src/meta/pos.c66
-rw-r--r--lib/vgmstream/src/meta/ps2_ads.c141
-rw-r--r--lib/vgmstream/src/meta/ps2_ass.c92
-rw-r--r--lib/vgmstream/src/meta/ps2_aus.c71
-rw-r--r--lib/vgmstream/src/meta/ps2_bg00.c65
-rw-r--r--lib/vgmstream/src/meta/ps2_bmdx.c92
-rw-r--r--lib/vgmstream/src/meta/ps2_ccc.c68
-rw-r--r--lib/vgmstream/src/meta/ps2_dxh.c76
-rw-r--r--lib/vgmstream/src/meta/ps2_enth.c94
-rw-r--r--lib/vgmstream/src/meta/ps2_exst.c79
-rw-r--r--lib/vgmstream/src/meta/ps2_filp.c67
-rw-r--r--lib/vgmstream/src/meta/ps2_gbts.c92
-rw-r--r--lib/vgmstream/src/meta/ps2_hgc1.c64
-rw-r--r--lib/vgmstream/src/meta/ps2_ikm.c65
-rw-r--r--lib/vgmstream/src/meta/ps2_ild.c69
-rw-r--r--lib/vgmstream/src/meta/ps2_int.c115
-rw-r--r--lib/vgmstream/src/meta/ps2_joe.c94
-rw-r--r--lib/vgmstream/src/meta/ps2_kces.c71
-rw-r--r--lib/vgmstream/src/meta/ps2_leg.c66
-rw-r--r--lib/vgmstream/src/meta/ps2_mib.c170
-rw-r--r--lib/vgmstream/src/meta/ps2_mic.c75
-rw-r--r--lib/vgmstream/src/meta/ps2_mihb.c66
-rw-r--r--lib/vgmstream/src/meta/ps2_npsf.c70
-rw-r--r--lib/vgmstream/src/meta/ps2_p2bt.c70
-rw-r--r--lib/vgmstream/src/meta/ps2_pnb.c66
-rw-r--r--lib/vgmstream/src/meta/ps2_psh.c89
-rw-r--r--lib/vgmstream/src/meta/ps2_psw.c88
-rw-r--r--lib/vgmstream/src/meta/ps2_rkv.c64
-rw-r--r--lib/vgmstream/src/meta/ps2_rnd.c56
-rw-r--r--lib/vgmstream/src/meta/ps2_rstm.c64
-rw-r--r--lib/vgmstream/src/meta/ps2_rws.c89
-rw-r--r--lib/vgmstream/src/meta/ps2_rxw.c70
-rw-r--r--lib/vgmstream/src/meta/ps2_seg.c71
-rw-r--r--lib/vgmstream/src/meta/ps2_sfs.c64
-rw-r--r--lib/vgmstream/src/meta/ps2_sl3.c65
-rw-r--r--lib/vgmstream/src/meta/ps2_str.c92
-rw-r--r--lib/vgmstream/src/meta/ps2_svag.c85
-rw-r--r--lib/vgmstream/src/meta/ps2_tec.c61
-rw-r--r--lib/vgmstream/src/meta/ps2_vag.c200
-rw-r--r--lib/vgmstream/src/meta/ps2_vas.c66
-rw-r--r--lib/vgmstream/src/meta/ps2_vpk.c70
-rw-r--r--lib/vgmstream/src/meta/ps2_xa2.c60
-rw-r--r--lib/vgmstream/src/meta/ps2_xa30.c63
-rw-r--r--lib/vgmstream/src/meta/psx_cdxa.c117
-rw-r--r--lib/vgmstream/src/meta/psx_fag.c66
-rw-r--r--lib/vgmstream/src/meta/psx_gms.c76
-rw-r--r--lib/vgmstream/src/meta/raw.c59
-rw-r--r--lib/vgmstream/src/meta/riff.c342
-rw-r--r--lib/vgmstream/src/meta/rs03.c81
-rw-r--r--lib/vgmstream/src/meta/rsd.c705
-rw-r--r--lib/vgmstream/src/meta/rsf.c73
-rw-r--r--lib/vgmstream/src/meta/rwsd.c245
-rw-r--r--lib/vgmstream/src/meta/rwx.c66
-rw-r--r--lib/vgmstream/src/meta/sat_dvi.c68
-rw-r--r--lib/vgmstream/src/meta/sat_sap.c67
-rw-r--r--lib/vgmstream/src/meta/sdt.c80
-rw-r--r--lib/vgmstream/src/meta/sfl.c182
-rw-r--r--lib/vgmstream/src/meta/sli.c121
-rw-r--r--lib/vgmstream/src/meta/spt_spd.c96
-rw-r--r--lib/vgmstream/src/meta/ss_stream.c61
-rw-r--r--lib/vgmstream/src/meta/str_asr.c97
-rw-r--r--lib/vgmstream/src/meta/str_snds.c134
-rw-r--r--lib/vgmstream/src/meta/svs.c69
-rw-r--r--lib/vgmstream/src/meta/thp.c97
-rw-r--r--lib/vgmstream/src/meta/vgs.c100
-rw-r--r--lib/vgmstream/src/meta/vs.c75
-rw-r--r--lib/vgmstream/src/meta/wii_mus.c124
-rw-r--r--lib/vgmstream/src/meta/wii_smp.c75
-rw-r--r--lib/vgmstream/src/meta/wii_sng.c125
-rw-r--r--lib/vgmstream/src/meta/wii_sts.c87
-rw-r--r--lib/vgmstream/src/meta/ws_aud.c132
-rw-r--r--lib/vgmstream/src/meta/xbox_ims.c61
-rw-r--r--lib/vgmstream/src/meta/xbox_stma.c64
-rw-r--r--lib/vgmstream/src/meta/xbox_wavm.c61
-rw-r--r--lib/vgmstream/src/meta/xbox_wvs.c67
-rw-r--r--lib/vgmstream/src/meta/xbox_xmu.c65
-rw-r--r--lib/vgmstream/src/meta/xbox_xvas.c72
-rw-r--r--lib/vgmstream/src/meta/xbox_xwav.c107
-rw-r--r--lib/vgmstream/src/meta/xss.c72
-rw-r--r--lib/vgmstream/src/meta/xwb.c103
-rw-r--r--lib/vgmstream/src/meta/ydsp.c83
-rw-r--r--lib/vgmstream/src/meta/zwdsp.c88
-rw-r--r--lib/vgmstream/src/streamfile.c276
-rw-r--r--lib/vgmstream/src/streamfile.h142
-rw-r--r--lib/vgmstream/src/streamtypes.h20
-rw-r--r--lib/vgmstream/src/util.c144
-rw-r--r--lib/vgmstream/src/util.h66
-rw-r--r--lib/vgmstream/src/vgmstream.c2209
-rw-r--r--lib/vgmstream/src/vgmstream.h608
-rw-r--r--lib/vgmstream/win32/win32.sln19
-rw-r--r--lib/vgmstream/win32/win32.vcproj1000
-rw-r--r--lib/vgmstream/win32/win32.vcxproj345
-rw-r--r--lib/vgmstream/win32/win32.vcxproj.filters612
201 files changed, 30091 insertions, 0 deletions
diff --git a/lib/vgmstream/COPYING b/lib/vgmstream/COPYING
new file mode 100644
index 0000000000..8dac8cf7cc
--- /dev/null
+++ b/lib/vgmstream/COPYING
@@ -0,0 +1,19 @@
+Copyright (c) 2008 Adam Gashlin, Fastelbja, Ronny Elfert
+
+Portions Copyright (c) 2004-2008, Marko Kreen
+Portions Copyright (c) 1998, Justin Frankel/Nullsoft Inc.
+Portions Copyright (C) 2006 Nullsoft, Inc.
+Portions Copyright (c) 2005-2007 Paul Hsieh
+Portions Public Domain originating with Sun Microsystems
+
+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.
diff --git a/lib/vgmstream/Makefile.in b/lib/vgmstream/Makefile.in
new file mode 100644
index 0000000000..9db00ba6cb
--- /dev/null
+++ b/lib/vgmstream/Makefile.in
@@ -0,0 +1,207 @@
+ARCH=@ARCH@
+
+ifeq ($(findstring osx,$(ARCH)), osx)
+ CFLAGS +=-D_LINUX -fPIC -DPIC -O3 -DXBMC
+ CXXFLAGS +=-D_LINUX -fPIC -DPIC -O3 -DXBMC
+else
+ CFLAGS +=-D_LINUX -fPIC -DXBMC
+ CXXFLAGS +=-D_LINUX -fPIC -DXBMC
+endif
+
+CODING_OBJS=src/coding/acm_decoder.o \
+ src/coding/adx_decoder.o \
+ src/coding/aica_decoder.o \
+ src/coding/eaxa_decoder.o \
+ src/coding/g721_decoder.o \
+ src/coding/ima_decoder.o \
+ src/coding/l5_555_decoder.o \
+ src/coding/mpeg_decoder.o \
+ src/coding/msadpcm_decoder.o \
+ src/coding/nds_procyon_decoder.o \
+ src/coding/ngc_afc_decoder.o \
+ src/coding/ngc_dsp_decoder.o \
+ src/coding/ngc_dtk_decoder.o \
+ src/coding/nwa_decoder.o \
+ src/coding/ogg_vorbis_decoder.o \
+ src/coding/pcm_decoder.o \
+ src/coding/psx_decoder.o \
+ src/coding/sdx2_decoder.o \
+ src/coding/ws_decoder.o \
+ src/coding/xa_decoder.o
+
+LAYOUT_OBJS=src/layout/aax_layout.o \
+ src/layout/aix_layout.o \
+ src/layout/ast_blocked.o \
+ src/layout/blocked.o \
+ src/layout/caf_blocked.o \
+ src/layout/de2_blocked.o \
+ src/layout/ea_block.o \
+ src/layout/emff_blocked.o \
+ src/layout/filp_blocked.o \
+ src/layout/gsb_blocked.o \
+ src/layout/halpst_blocked.o \
+ src/layout/ims_block.o \
+ src/layout/interleave.o \
+ src/layout/interleave_byte.o \
+ src/layout/mus_acm_layout.o \
+ src/layout/nolayout.o \
+ src/layout/str_snds_blocked.o \
+ src/layout/thp_blocked.o \
+ src/layout/vs_blocked.o \
+ src/layout/ws_aud_blocked.o \
+ src/layout/wsi_blocked.o \
+ src/layout/xa_blocked.o \
+ src/layout/xvas_block.o
+
+META_OBJS=src/meta/aax.o \
+ src/meta/acm.o \
+ src/meta/adx_header.o \
+ src/meta/afc_header.o \
+ src/meta/agsc.o \
+ src/meta/ahx.o \
+ src/meta/aifc.o \
+ src/meta/aix.o \
+ src/meta/ast.o \
+ src/meta/bgw.o \
+ src/meta/brstm.o \
+ src/meta/capdsp.o \
+ src/meta/Cstr.o \
+ src/meta/dc_asd.o \
+ src/meta/dc_idvi.o \
+ src/meta/dc_kcey.o \
+ src/meta/dc_str.o \
+ src/meta/dc_wav_dcs.o \
+ src/meta/de2.o \
+ src/meta/ea_header.o \
+ src/meta/ea_old.o \
+ src/meta/emff.o \
+ src/meta/fsb.o \
+ src/meta/gca.o \
+ src/meta/gcsw.o \
+ src/meta/genh.o \
+ src/meta/gsp_gsb.o \
+ src/meta/halpst.o \
+ src/meta/idsp.o \
+ src/meta/ish_isd.o \
+ src/meta/ivb.o \
+ src/meta/kraw.o \
+ src/meta/msvp.o \
+ src/meta/mus_acm.o \
+ src/meta/musc.o \
+ src/meta/musx.o \
+ src/meta/naomi_spsd.o \
+ src/meta/nds_sad.o \
+ src/meta/nds_strm.o \
+ src/meta/ngc_adpdtk.o \
+ src/meta/ngc_bh2pcm.o \
+ src/meta/ngc_caf.o \
+ src/meta/ngc_dsp_std.o \
+ src/meta/ngc_ffcc_str.o \
+ src/meta/ngc_iadp.o \
+ src/meta/ngc_pdt.o \
+ src/meta/ngc_ssm.o \
+ src/meta/ngc_tydsp.o \
+ src/meta/ngc_waa_wac_wad_wam.o \
+ src/meta/ngc_ymf.o \
+ src/meta/nwa.o \
+ src/meta/ogg_vorbis_file.o \
+ src/meta/pcm.o \
+ src/meta/pos.o \
+ src/meta/ps2_ads.o \
+ src/meta/ps2_ass.o \
+ src/meta/ps2_aus.o \
+ src/meta/ps2_bg00.o \
+ src/meta/ps2_bmdx.o \
+ src/meta/ps2_ccc.o \
+ src/meta/ps2_dxh.o \
+ src/meta/ps2_enth.o \
+ src/meta/ps2_exst.o \
+ src/meta/ps2_filp.o \
+ src/meta/ps2_gbts.o \
+ src/meta/ps2_hgc1.o \
+ src/meta/ps2_ikm.o \
+ src/meta/ps2_ild.o \
+ src/meta/ps2_int.o \
+ src/meta/ps2_joe.o \
+ src/meta/ps2_kces.o \
+ src/meta/ps2_leg.o \
+ src/meta/ps2_mib.o \
+ src/meta/ps2_mic.o \
+ src/meta/ps2_mihb.o \
+ src/meta/ps2_npsf.o \
+ src/meta/ps2_p2bt.o \
+ src/meta/ps2_pnb.o \
+ src/meta/ps2_psh.o \
+ src/meta/ps2_psw.o \
+ src/meta/ps2_rkv.o \
+ src/meta/ps2_rnd.o \
+ src/meta/ps2_rstm.o \
+ src/meta/ps2_rws.o \
+ src/meta/ps2_rxw.o \
+ src/meta/ps2_seg.o \
+ src/meta/ps2_sfs.o \
+ src/meta/ps2_sl3.o \
+ src/meta/ps2_str.o \
+ src/meta/ps2_svag.o \
+ src/meta/ps2_tec.o \
+ src/meta/ps2_vag.o \
+ src/meta/ps2_vas.o \
+ src/meta/ps2_vpk.o \
+ src/meta/ps2_xa2.o \
+ src/meta/ps2_xa30.o \
+ src/meta/psx_cdxa.o \
+ src/meta/psx_fag.o \
+ src/meta/psx_gms.o \
+ src/meta/raw.o \
+ src/meta/riff.o \
+ src/meta/rs03.o \
+ src/meta/rsd.o \
+ src/meta/rsf.o \
+ src/meta/rwsd.o \
+ src/meta/rwx.o \
+ src/meta/sat_dvi.o \
+ src/meta/sat_sap.o \
+ src/meta/sdt.o \
+ src/meta/sfl.o \
+ src/meta/sli.o \
+ src/meta/spt_spd.o \
+ src/meta/ss_stream.o \
+ src/meta/str_asr.o \
+ src/meta/str_snds.o \
+ src/meta/svs.o \
+ src/meta/thp.o \
+ src/meta/vgs.o \
+ src/meta/vs.o \
+ src/meta/wii_mus.o \
+ src/meta/wii_smp.o \
+ src/meta/wii_sng.o \
+ src/meta/wii_sts.o \
+ src/meta/ws_aud.o \
+ src/meta/xbox_ims.o \
+ src/meta/xbox_stma.o \
+ src/meta/xbox_wavm.o \
+ src/meta/xbox_wvs.o \
+ src/meta/xbox_xmu.o \
+ src/meta/xbox_xvas.o \
+ src/meta/xbox_xwav.o \
+ src/meta/xss.o \
+ src/meta/xwb.o \
+ src/meta/ydsp.o \
+ src/meta/zwdsp.o
+
+OBJS = $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) XBMCVGM.o src/vgmstream.o src/util.o src/streamfile.o
+
+SLIB=@abs_top_srcdir@/system/players/paplayer/vgmstream-@ARCH@.so
+
+$(SLIB): $(OBJS)
+ifeq ($(findstring osx,$(ARCH)), osx)
+ ld -bundle -flat_namespace -undefined suppress -o $@ $(OBJS) $(BUNDLE1_O)
+ @abs_top_srcdir@/tools/Mach5/wrapper.rb $@;mv output.so $@
+ chmod +x $@
+else
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -o $@ $(OBJS) `cat @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.def` @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o
+
+endif
+
+include @abs_top_srcdir@/Makefile.include
+
diff --git a/lib/vgmstream/XBMCVGM.cpp b/lib/vgmstream/XBMCVGM.cpp
new file mode 100644
index 0000000000..9228322f44
--- /dev/null
+++ b/lib/vgmstream/XBMCVGM.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-2010 Team XBMC
+ * http://www.xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#ifndef _LINUX
+#include <windows.h>
+#else
+#define __cdecl
+#define __declspec(x)
+#endif
+
+extern "C"
+{
+ #include "src/vgmstream.h"
+
+ long __declspec(dllexport) DLL_Init()
+ {
+ return 1;
+ }
+
+ long __declspec(dllexport) DLL_LoadVGM(const char* szFileName, int* sampleRate, int* sampleSize, int* channels)
+ {
+ VGMSTREAM* result;
+
+ if ((result = init_vgmstream(szFileName)) == NULL)
+ return 0;
+
+ *sampleRate = result->sample_rate;
+ *sampleSize = 16;
+ *channels = result->channels;
+ return (long)result;
+ }
+
+ void __declspec(dllexport) DLL_FreeVGM(long vgm)
+ {
+ close_vgmstream((VGMSTREAM*)vgm);
+ }
+
+ int __declspec(dllexport) DLL_FillBuffer(long vgm, char* szBuffer, int iSize)
+ {
+ VGMSTREAM* song = (VGMSTREAM*)vgm;
+ render_vgmstream((sample*)szBuffer,iSize/(2*song->channels),(VGMSTREAM*)vgm);
+
+ return iSize;
+ }
+
+ unsigned long __declspec(dllexport) DLL_Seek(long vgm, unsigned long timepos)
+ {
+ VGMSTREAM* song = (VGMSTREAM*)vgm;
+ int16_t* buffer = new int16_t[576*song->channels];
+ long samples_to_do = (long)timepos * song->sample_rate / 1000L;
+ if (samples_to_do < song->current_sample )
+ reset_vgmstream(song);
+ else
+ samples_to_do -= song->current_sample;
+
+ while (samples_to_do > 0)
+ {
+ long l = samples_to_do>576?576:samples_to_do;
+ render_vgmstream(buffer,l,song);
+ samples_to_do -= l;
+ }
+ delete[] buffer;
+
+ return timepos;
+ }
+
+ unsigned long __declspec(dllexport) DLL_GetLength(long vgm)
+ {
+ VGMSTREAM* song = (VGMSTREAM*)vgm;
+
+ return song->num_samples/song->sample_rate*1000;
+ }
+}
diff --git a/lib/vgmstream/ext_includes/pstdint.h b/lib/vgmstream/ext_includes/pstdint.h
new file mode 100644
index 0000000000..b36f63db3a
--- /dev/null
+++ b/lib/vgmstream/ext_includes/pstdint.h
@@ -0,0 +1,728 @@
+/* A portable stdint.h
+ ****************************************************************************
+ * BSD License:
+ ****************************************************************************
+ *
+ * Copyright (c) 2005-2007 Paul Hsieh
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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.
+ *
+ ****************************************************************************
+ *
+ * Version 0.1.10
+ *
+ * The ANSI C standard committee, for the C99 standard, specified the
+ * inclusion of a new standard include file called stdint.h. This is
+ * a very useful and long desired include file which contains several
+ * very precise definitions for integer scalar types that is
+ * critically important for making portable several classes of
+ * applications including cryptography, hashing, variable length
+ * integer libraries and so on. But for most developers its likely
+ * useful just for programming sanity.
+ *
+ * The problem is that most compiler vendors have decided not to
+ * implement the C99 standard, and the next C++ language standard
+ * (which has a lot more mindshare these days) will be a long time in
+ * coming and its unknown whether or not it will include stdint.h or
+ * how much adoption it will have. Either way, it will be a long time
+ * before all compilers come with a stdint.h and it also does nothing
+ * for the extremely large number of compilers available today which
+ * do not include this file, or anything comparable to it.
+ *
+ * So that's what this file is all about. Its an attempt to build a
+ * single universal include file that works on as many platforms as
+ * possible to deliver what stdint.h is supposed to. A few things
+ * that should be noted about this file:
+ *
+ * 1) It is not guaranteed to be portable and/or present an identical
+ * interface on all platforms. The extreme variability of the
+ * ANSI C standard makes this an impossibility right from the
+ * very get go. Its really only meant to be useful for the vast
+ * majority of platforms that possess the capability of
+ * implementing usefully and precisely defined, standard sized
+ * integer scalars. Systems which are not intrinsically 2s
+ * complement may produce invalid constants.
+ *
+ * 2) There is an unavoidable use of non-reserved symbols.
+ *
+ * 3) Other standard include files are invoked.
+ *
+ * 4) This file may come in conflict with future platforms that do
+ * include stdint.h. The hope is that one or the other can be
+ * used with no real difference.
+ *
+ * 5) In the current verison, if your platform can't represent
+ * int32_t, int16_t and int8_t, it just dumps out with a compiler
+ * error.
+ *
+ * 6) 64 bit integers may or may not be defined. Test for their
+ * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX.
+ * Note that this is different from the C99 specification which
+ * requires the existence of 64 bit support in the compiler. If
+ * this is not defined for your platform, yet it is capable of
+ * dealing with 64 bits then it is because this file has not yet
+ * been extended to cover all of your system's capabilities.
+ *
+ * 7) (u)intptr_t may or may not be defined. Test for its presence
+ * with the test: #ifdef PTRDIFF_MAX. If this is not defined
+ * for your platform, then it is because this file has not yet
+ * been extended to cover all of your system's capabilities, not
+ * because its optional.
+ *
+ * 8) The following might not been defined even if your platform is
+ * capable of defining it:
+ *
+ * WCHAR_MIN
+ * WCHAR_MAX
+ * (u)int64_t
+ * PTRDIFF_MIN
+ * PTRDIFF_MAX
+ * (u)intptr_t
+ *
+ * 9) The following have not been defined:
+ *
+ * WINT_MIN
+ * WINT_MAX
+ *
+ * 10) The criteria for defining (u)int_least(*)_t isn't clear,
+ * except for systems which don't have a type that precisely
+ * defined 8, 16, or 32 bit types (which this include file does
+ * not support anyways). Default definitions have been given.
+ *
+ * 11) The criteria for defining (u)int_fast(*)_t isn't something I
+ * would trust to any particular compiler vendor or the ANSI C
+ * committee. It is well known that "compatible systems" are
+ * commonly created that have very different performance
+ * characteristics from the systems they are compatible with,
+ * especially those whose vendors make both the compiler and the
+ * system. Default definitions have been given, but its strongly
+ * recommended that users never use these definitions for any
+ * reason (they do *NOT* deliver any serious guarantee of
+ * improved performance -- not in this file, nor any vendor's
+ * stdint.h).
+ *
+ * 12) The following macros:
+ *
+ * PRINTF_INTMAX_MODIFIER
+ * PRINTF_INT64_MODIFIER
+ * PRINTF_INT32_MODIFIER
+ * PRINTF_INT16_MODIFIER
+ * PRINTF_LEAST64_MODIFIER
+ * PRINTF_LEAST32_MODIFIER
+ * PRINTF_LEAST16_MODIFIER
+ * PRINTF_INTPTR_MODIFIER
+ *
+ * are strings which have been defined as the modifiers required
+ * for the "d", "u" and "x" printf formats to correctly output
+ * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t,
+ * (u)least32_t, (u)least16_t and (u)intptr_t types respectively.
+ * PRINTF_INTPTR_MODIFIER is not defined for some systems which
+ * provide their own stdint.h. PRINTF_INT64_MODIFIER is not
+ * defined if INT64_MAX is not defined. These are an extension
+ * beyond what C99 specifies must be in stdint.h.
+ *
+ * In addition, the following macros are defined:
+ *
+ * PRINTF_INTMAX_HEX_WIDTH
+ * PRINTF_INT64_HEX_WIDTH
+ * PRINTF_INT32_HEX_WIDTH
+ * PRINTF_INT16_HEX_WIDTH
+ * PRINTF_INT8_HEX_WIDTH
+ * PRINTF_INTMAX_DEC_WIDTH
+ * PRINTF_INT64_DEC_WIDTH
+ * PRINTF_INT32_DEC_WIDTH
+ * PRINTF_INT16_DEC_WIDTH
+ * PRINTF_INT8_DEC_WIDTH
+ *
+ * Which specifies the maximum number of characters required to
+ * print the number of that type in either hexadecimal or decimal.
+ * These are an extension beyond what C99 specifies must be in
+ * stdint.h.
+ *
+ * Compilers tested (all with 0 warnings at their highest respective
+ * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32
+ * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio
+ * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3
+ *
+ * This file should be considered a work in progress. Suggestions for
+ * improvements, especially those which increase coverage are strongly
+ * encouraged.
+ *
+ * Acknowledgements
+ *
+ * The following people have made significant contributions to the
+ * development and testing of this file:
+ *
+ * Chris Howie
+ * John Steele Scott
+ * Dave Thorup
+ *
+ */
+
+#include <stddef.h>
+#include <limits.h>
+#include <signal.h>
+
+/*
+ * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and
+ * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_.
+ */
+
+#if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED)
+#include <stdint.h>
+#define _PSTDINT_H_INCLUDED
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
+# endif
+# ifndef PRINTF_INT64_HEX_WIDTH
+# define PRINTF_INT64_HEX_WIDTH "16"
+# endif
+# ifndef PRINTF_INT32_HEX_WIDTH
+# define PRINTF_INT32_HEX_WIDTH "8"
+# endif
+# ifndef PRINTF_INT16_HEX_WIDTH
+# define PRINTF_INT16_HEX_WIDTH "4"
+# endif
+# ifndef PRINTF_INT8_HEX_WIDTH
+# define PRINTF_INT8_HEX_WIDTH "2"
+# endif
+# ifndef PRINTF_INT64_DEC_WIDTH
+# define PRINTF_INT64_DEC_WIDTH "20"
+# endif
+# ifndef PRINTF_INT32_DEC_WIDTH
+# define PRINTF_INT32_DEC_WIDTH "10"
+# endif
+# ifndef PRINTF_INT16_DEC_WIDTH
+# define PRINTF_INT16_DEC_WIDTH "5"
+# endif
+# ifndef PRINTF_INT8_DEC_WIDTH
+# define PRINTF_INT8_DEC_WIDTH "3"
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
+# endif
+
+/*
+ * Something really weird is going on with Open Watcom. Just pull some of
+ * these duplicated definitions from Open Watcom's stdint.h file for now.
+ */
+
+# if defined (__WATCOMC__) && __WATCOMC__ >= 1250
+# if !defined (INT64_C)
+# define INT64_C(x) (x + (INT64_MAX - INT64_MAX))
+# endif
+# if !defined (UINT64_C)
+# define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX))
+# endif
+# if !defined (INT32_C)
+# define INT32_C(x) (x + (INT32_MAX - INT32_MAX))
+# endif
+# if !defined (UINT32_C)
+# define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX))
+# endif
+# if !defined (INT16_C)
+# define INT16_C(x) (x)
+# endif
+# if !defined (UINT16_C)
+# define UINT16_C(x) (x)
+# endif
+# if !defined (INT8_C)
+# define INT8_C(x) (x)
+# endif
+# if !defined (UINT8_C)
+# define UINT8_C(x) (x)
+# endif
+# if !defined (UINT64_MAX)
+# define UINT64_MAX 18446744073709551615ULL
+# endif
+# if !defined (INT64_MAX)
+# define INT64_MAX 9223372036854775807LL
+# endif
+# if !defined (UINT32_MAX)
+# define UINT32_MAX 4294967295UL
+# endif
+# if !defined (INT32_MAX)
+# define INT32_MAX 2147483647L
+# endif
+# if !defined (INTMAX_MAX)
+# define INTMAX_MAX INT64_MAX
+# endif
+# if !defined (INTMAX_MIN)
+# define INTMAX_MIN INT64_MIN
+# endif
+# endif
+#endif
+
+#ifndef _PSTDINT_H_INCLUDED
+#define _PSTDINT_H_INCLUDED
+
+#ifndef SIZE_MAX
+# define SIZE_MAX (~(size_t)0)
+#endif
+
+/*
+ * Deduce the type assignments from limits.h under the assumption that
+ * integer sizes in bits are powers of 2, and follow the ANSI
+ * definitions.
+ */
+
+#ifndef UINT8_MAX
+# define UINT8_MAX 0xff
+#endif
+#ifndef uint8_t
+# if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S)
+ typedef unsigned char uint8_t;
+# define UINT8_C(v) ((uint8_t) v)
+# else
+# error "Platform not supported"
+# endif
+#endif
+
+#ifndef INT8_MAX
+# define INT8_MAX 0x7f
+#endif
+#ifndef INT8_MIN
+# define INT8_MIN INT8_C(0x80)
+#endif
+#ifndef int8_t
+# if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S)
+ typedef signed char int8_t;
+# define INT8_C(v) ((int8_t) v)
+# else
+# error "Platform not supported"
+# endif
+#endif
+
+#ifndef UINT16_MAX
+# define UINT16_MAX 0xffff
+#endif
+#ifndef uint16_t
+#if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S)
+ typedef unsigned int uint16_t;
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER ""
+# endif
+# define UINT16_C(v) ((uint16_t) (v))
+#elif (USHRT_MAX == UINT16_MAX)
+ typedef unsigned short uint16_t;
+# define UINT16_C(v) ((uint16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef INT16_MAX
+# define INT16_MAX 0x7fff
+#endif
+#ifndef INT16_MIN
+# define INT16_MIN INT16_C(0x8000)
+#endif
+#ifndef int16_t
+#if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S)
+ typedef signed int int16_t;
+# define INT16_C(v) ((int16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER ""
+# endif
+#elif (SHRT_MAX == INT16_MAX)
+ typedef signed short int16_t;
+# define INT16_C(v) ((int16_t) (v))
+# ifndef PRINTF_INT16_MODIFIER
+# define PRINTF_INT16_MODIFIER "h"
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef UINT32_MAX
+# define UINT32_MAX (0xffffffffUL)
+#endif
+#ifndef uint32_t
+#if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S)
+ typedef unsigned long uint32_t;
+# define UINT32_C(v) v ## UL
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+#elif (UINT_MAX == UINT32_MAX)
+ typedef unsigned int uint32_t;
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+# define UINT32_C(v) v ## U
+#elif (USHRT_MAX == UINT32_MAX)
+ typedef unsigned short uint32_t;
+# define UINT32_C(v) ((unsigned short) (v))
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+#ifndef INT32_MAX
+# define INT32_MAX (0x7fffffffL)
+#endif
+#ifndef INT32_MIN
+# define INT32_MIN INT32_C(0x80000000)
+#endif
+#ifndef int32_t
+#if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S)
+ typedef signed long int32_t;
+# define INT32_C(v) v ## L
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER "l"
+# endif
+#elif (INT_MAX == INT32_MAX)
+ typedef signed int int32_t;
+# define INT32_C(v) v
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#elif (SHRT_MAX == INT32_MAX)
+ typedef signed short int32_t;
+# define INT32_C(v) ((short) (v))
+# ifndef PRINTF_INT32_MODIFIER
+# define PRINTF_INT32_MODIFIER ""
+# endif
+#else
+#error "Platform not supported"
+#endif
+#endif
+
+/*
+ * The macro stdint_int64_defined is temporarily used to record
+ * whether or not 64 integer support is available. It must be
+ * defined for any 64 integer extensions for new platforms that are
+ * added.
+ */
+
+#undef stdint_int64_defined
+#if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S)
+# if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S)
+# define stdint_int64_defined
+ typedef long long int64_t;
+ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# endif
+#endif
+
+#if !defined (stdint_int64_defined)
+# if defined(__GNUC__)
+# define stdint_int64_defined
+ __extension__ typedef long long int64_t;
+ __extension__ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S)
+# define stdint_int64_defined
+ typedef long long int64_t;
+ typedef unsigned long long uint64_t;
+# define UINT64_C(v) v ## ULL
+# define INT64_C(v) v ## LL
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "ll"
+# endif
+# elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC)
+# define stdint_int64_defined
+ typedef __int64 int64_t;
+ typedef unsigned __int64 uint64_t;
+# define UINT64_C(v) v ## UI64
+# define INT64_C(v) v ## I64
+# ifndef PRINTF_INT64_MODIFIER
+# define PRINTF_INT64_MODIFIER "I64"
+# endif
+# endif
+#endif
+
+#if !defined (LONG_LONG_MAX) && defined (INT64_C)
+# define LONG_LONG_MAX INT64_C (9223372036854775807)
+#endif
+#ifndef ULONG_LONG_MAX
+# define ULONG_LONG_MAX UINT64_C (18446744073709551615)
+#endif
+
+#if !defined (INT64_MAX) && defined (INT64_C)
+# define INT64_MAX INT64_C (9223372036854775807)
+#endif
+#if !defined (INT64_MIN) && defined (INT64_C)
+# define INT64_MIN INT64_C (-9223372036854775808)
+#endif
+#if !defined (UINT64_MAX) && defined (INT64_C)
+# define UINT64_MAX UINT64_C (18446744073709551615)
+#endif
+
+/*
+ * Width of hexadecimal for number field.
+ */
+
+#ifndef PRINTF_INT64_HEX_WIDTH
+# define PRINTF_INT64_HEX_WIDTH "16"
+#endif
+#ifndef PRINTF_INT32_HEX_WIDTH
+# define PRINTF_INT32_HEX_WIDTH "8"
+#endif
+#ifndef PRINTF_INT16_HEX_WIDTH
+# define PRINTF_INT16_HEX_WIDTH "4"
+#endif
+#ifndef PRINTF_INT8_HEX_WIDTH
+# define PRINTF_INT8_HEX_WIDTH "2"
+#endif
+
+#ifndef PRINTF_INT64_DEC_WIDTH
+# define PRINTF_INT64_DEC_WIDTH "20"
+#endif
+#ifndef PRINTF_INT32_DEC_WIDTH
+# define PRINTF_INT32_DEC_WIDTH "10"
+#endif
+#ifndef PRINTF_INT16_DEC_WIDTH
+# define PRINTF_INT16_DEC_WIDTH "5"
+#endif
+#ifndef PRINTF_INT8_DEC_WIDTH
+# define PRINTF_INT8_DEC_WIDTH "3"
+#endif
+
+/*
+ * Ok, lets not worry about 128 bit integers for now. Moore's law says
+ * we don't need to worry about that until about 2040 at which point
+ * we'll have bigger things to worry about.
+ */
+
+#ifdef stdint_int64_defined
+ typedef int64_t intmax_t;
+ typedef uint64_t uintmax_t;
+# define INTMAX_MAX INT64_MAX
+# define INTMAX_MIN INT64_MIN
+# define UINTMAX_MAX UINT64_MAX
+# define UINTMAX_C(v) UINT64_C(v)
+# define INTMAX_C(v) INT64_C(v)
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH
+# endif
+#else
+ typedef int32_t intmax_t;
+ typedef uint32_t uintmax_t;
+# define INTMAX_MAX INT32_MAX
+# define UINTMAX_MAX UINT32_MAX
+# define UINTMAX_C(v) UINT32_C(v)
+# define INTMAX_C(v) INT32_C(v)
+# ifndef PRINTF_INTMAX_MODIFIER
+# define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER
+# endif
+# ifndef PRINTF_INTMAX_HEX_WIDTH
+# define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH
+# endif
+# ifndef PRINTF_INTMAX_DEC_WIDTH
+# define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH
+# endif
+#endif
+
+/*
+ * Because this file currently only supports platforms which have
+ * precise powers of 2 as bit sizes for the default integers, the
+ * least definitions are all trivial. Its possible that a future
+ * version of this file could have different definitions.
+ */
+
+#ifndef stdint_least_defined
+ typedef int8_t int_least8_t;
+ typedef uint8_t uint_least8_t;
+ typedef int16_t int_least16_t;
+ typedef uint16_t uint_least16_t;
+ typedef int32_t int_least32_t;
+ typedef uint32_t uint_least32_t;
+# define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER
+# define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER
+# define UINT_LEAST8_MAX UINT8_MAX
+# define INT_LEAST8_MAX INT8_MAX
+# define UINT_LEAST16_MAX UINT16_MAX
+# define INT_LEAST16_MAX INT16_MAX
+# define UINT_LEAST32_MAX UINT32_MAX
+# define INT_LEAST32_MAX INT32_MAX
+# define INT_LEAST8_MIN INT8_MIN
+# define INT_LEAST16_MIN INT16_MIN
+# define INT_LEAST32_MIN INT32_MIN
+# ifdef stdint_int64_defined
+ typedef int64_t int_least64_t;
+ typedef uint64_t uint_least64_t;
+# define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER
+# define UINT_LEAST64_MAX UINT64_MAX
+# define INT_LEAST64_MAX INT64_MAX
+# define INT_LEAST64_MIN INT64_MIN
+# endif
+#endif
+#undef stdint_least_defined
+
+/*
+ * The ANSI C committee pretending to know or specify anything about
+ * performance is the epitome of misguided arrogance. The mandate of
+ * this file is to *ONLY* ever support that absolute minimum
+ * definition of the fast integer types, for compatibility purposes.
+ * No extensions, and no attempt to suggest what may or may not be a
+ * faster integer type will ever be made in this file. Developers are
+ * warned to stay away from these types when using this or any other
+ * stdint.h.
+ */
+
+typedef int_least8_t int_fast8_t;
+typedef uint_least8_t uint_fast8_t;
+typedef int_least16_t int_fast16_t;
+typedef uint_least16_t uint_fast16_t;
+typedef int_least32_t int_fast32_t;
+typedef uint_least32_t uint_fast32_t;
+#define UINT_FAST8_MAX UINT_LEAST8_MAX
+#define INT_FAST8_MAX INT_LEAST8_MAX
+#define UINT_FAST16_MAX UINT_LEAST16_MAX
+#define INT_FAST16_MAX INT_LEAST16_MAX
+#define UINT_FAST32_MAX UINT_LEAST32_MAX
+#define INT_FAST32_MAX INT_LEAST32_MAX
+#define INT_FAST8_MIN INT_LEAST8_MIN
+#define INT_FAST16_MIN INT_LEAST16_MIN
+#define INT_FAST32_MIN INT_LEAST32_MIN
+#ifdef stdint_int64_defined
+ typedef int_least64_t int_fast64_t;
+ typedef uint_least64_t uint_fast64_t;
+# define UINT_FAST64_MAX UINT_LEAST64_MAX
+# define INT_FAST64_MAX INT_LEAST64_MAX
+# define INT_FAST64_MIN INT_LEAST64_MIN
+#endif
+
+#undef stdint_int64_defined
+
+/*
+ * Whatever piecemeal, per compiler thing we can do about the wchar_t
+ * type limits.
+ */
+
+#if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__)
+# include <wchar.h>
+# ifndef WCHAR_MIN
+# define WCHAR_MIN 0
+# endif
+# ifndef WCHAR_MAX
+# define WCHAR_MAX ((wchar_t)-1)
+# endif
+#endif
+
+/*
+ * Whatever piecemeal, per compiler/platform thing we can do about the
+ * (u)intptr_t types and limits.
+ */
+
+#if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED)
+# define STDINT_H_UINTPTR_T_DEFINED
+#endif
+
+#ifndef STDINT_H_UINTPTR_T_DEFINED
+# if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64)
+# define stdint_intptr_bits 64
+# elif defined (__WATCOMC__) || defined (__TURBOC__)
+# if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__)
+# define stdint_intptr_bits 16
+# else
+# define stdint_intptr_bits 32
+# endif
+# elif defined (__i386__) || defined (_WIN32) || defined (WIN32)
+# define stdint_intptr_bits 32
+# elif defined (__INTEL_COMPILER)
+/* TODO -- what will Intel do about x86-64? */
+# endif
+
+# ifdef stdint_intptr_bits
+# define stdint_intptr_glue3_i(a,b,c) a##b##c
+# define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c)
+# ifndef PRINTF_INTPTR_MODIFIER
+# define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER)
+# endif
+# ifndef PTRDIFF_MAX
+# define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef PTRDIFF_MIN
+# define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
+# endif
+# ifndef UINTPTR_MAX
+# define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef INTPTR_MAX
+# define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX)
+# endif
+# ifndef INTPTR_MIN
+# define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN)
+# endif
+# ifndef INTPTR_C
+# define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x)
+# endif
+# ifndef UINTPTR_C
+# define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x)
+# endif
+ typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t;
+ typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t;
+# else
+/* TODO -- This following is likely wrong for some platforms, and does
+ nothing for the definition of uintptr_t. */
+ typedef ptrdiff_t intptr_t;
+# endif
+# define STDINT_H_UINTPTR_T_DEFINED
+#endif
+
+/*
+ * Assumes sig_atomic_t is signed and we have a 2s complement machine.
+ */
+
+#ifndef SIG_ATOMIC_MAX
+# define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1)
+#endif
+
+#endif
diff --git a/lib/vgmstream/readme.txt b/lib/vgmstream/readme.txt
new file mode 100644
index 0000000000..9e6f24cabd
--- /dev/null
+++ b/lib/vgmstream/readme.txt
@@ -0,0 +1,148 @@
+vgmstream
+
+This is vgmstream, a library for playing streamed audio from video games.
+It is very much under development. There are two end-user bits: a command
+line decoder called "test", and a simple Winamp plugin called "in_vgmstream".
+
+--- needed files (for Windows) ---
+Since Ogg Vorbis and MPEG audio are now supported, you will need to have
+libvorbis.dll and libmpg123-0.dll.
+I suggest getting libvorbis.dll here:
+http://www.rarewares.org/files/ogg/libvorbis1.2.0.zip
+and the companion Intel math dll:
+http://www.rarewares.org/files/libmmd9.1.zip
+And libmpg123-0.dll from this archive:
+http://www.mpg123.de/download/win32/mpg123-1.4.3-x86.zip
+
+Put libvorbis.dll, libmmd.dll, and libmpg123-0.dll somewhere Windows can find
+them. For in_vgmstream this means in the directory with winamp.exe, or in a
+system directory. For test.exe this means in the same directory as test.exe,
+or in a system directory.
+
+--- test.exe ---
+Usage: test.exe [-o outfile.wav] [-l loop count]
+ [-f fade time] [-d fade delay] [-ipPcmxeE] infile
+Options:
+ -o outfile.wav: name of output .wav file, default is dump.wav
+ -l loop count: loop count, default 2.0
+ -f fade time: fade time (seconds), default 10.0
+ -d fade delay: fade delay (seconds, default 0.0
+ -i: ignore looping information and play the whole stream once
+ -p: output to stdout (for piping into another program)
+ -P: output to stdout even if stdout is a terminal
+ -c: loop forever (continuously)
+ -m: print metadata only, don't decode
+ -x: decode and print adxencd command line to encode as ADX
+ -e: force end-to-end looping
+ -E: force end-to-end looping even if file has real loop points
+ -r outfile2.wav: output a second time after resetting
+
+Typical usage would be:
+test -o happy.wav happy.adx
+to decode happy.adx to happy.wav.
+
+--- in_vgmstream ---
+Drop the in_vgmstream.dll in your Winamp plugins directory.
+
+---
+File types supported by this version of vgmstream:
+- .adx (CRI ADX ADPCM)
+- .brstm (RSTM: GC/Wii DSP ADPCM, 8/16 bit PCM)
+- .strm (STRM: NDS IMA ADPCM, 8/16 bit PCM)
+- .adp (GC DTK ADPCM)
+- .agsc (GC DSP ADPCM)
+- .rsf (CCITT G.721 ADPCM)
+- .afc (GC AFC ADPCM)
+- .ast (GC/Wii AFC ADPCM, 16 bit PCM)
+- .hps (GC DSP ADPCM)
+- .dsp (GC DSP ADPCM)
+ - standard, with dual file stereo
+ - RS03
+ - Cstr
+ - .stm
+ - _lr.dsp
+- .gcsw (16 bit PCM)
+- .ads/.ss2 (PSX ADPCM)
+- .npsf (PSX ADPCM)
+- .rwsd (Wii DSP ADPCM, 8/16 bit PCM)
+- .xa (CD-ROM XA audio)
+- .rxw (PSX ADPCM)
+- .int (16 bit PCM)
+- .stm/.dsp (GC DSP ADPCM)
+- .sts (PSX ADPCM)
+- .svag (PSX ADPCM)
+- .mib, .mi4 (w/ or w/o .mih) (PSX ADPCM)
+- .mpdsp (GC DSP ADPCM)
+- .mic (PSX ADPCM)
+- .mss (GC DSP ADPCM)
+- .gcm (GC DSP ADPCM)
+- .raw (16 bit PCM)
+- .vag (PSX ADPCM)
+- .gms (PSX ADPCM)
+- .str+.sth (PSX ADPCM)
+- .ild (PSX APDCM)
+- .pnb (PSX ADPCM)
+- .wavm (XBOX IMA ADPCM)
+- .xwav (XBOX IMA ADPCM)
+- .wp2 (PSX ADPCM)
+- .str (GC DSP ADPCM)
+- .sng, .asf, .str, .eam (EA/XA ADPCM or PSX ADPCM)
+- .cfn (GC DSP ADPCM)
+- .vpk (PSX ADPCM)
+- .genh (PSX ADPCM, XBOX IMA ADPCM, GC DTK ADPCM, 8/16 bit PCM, SDX2, DVI, MPEG)
+- .ogg, .logg (Ogg Vorbis)
+- .sad (GC DSP ADPCM)
+- .bmdx (PSX ADPCM)
+- .wsi (Wii DSP ADPCM)
+- .aifc (SDX2 DPCM, DVI IMA ADPCM)
+- .aiff (8/16 bit PCM)
+- .str (SDX2 DPCM)
+- .aud (IMA ADPCM, WS DPCM)
+- .ahx (MPEG-2 Layer II)
+- .ivb (PS2 ADPCM)
+- .amts (GC DSP ADPCM)
+- .svs (PS2 ADPCM)
+- .wav (8/16 bit PCM)
+- .lwav (8/16 bit PCM)
+- .pos (loop info for .wav)
+- .nwa (16 bit PCM, NWA DPCM)
+- .xss (16 bit PCM)
+- .sl3 (PS2 ADPCM)
+- .hgc1 (PS2 ADPCM)
+- .aus (PS2 ADPCM)
+- .rws (PS2 ADPCM)
+- .fsb (PS2 ADPCM, Wii DSP ADPCM, Xbox IMA ADPCM)
+- .rsd (PS2 ADPCM, 16 bit PCM)
+- .rwx (16 bit PCM)
+- .xwb (16 bit PCM)
+- .asf, .as4 (8/16 bit PCM, EACS IMA ADPCM)
+- .cnk (PS2 ADPCM)
+- .xa30 (PS2 ADPCM)
+- .musc (PS2 ADPCM)
+- .leg (PS2 ADPCM)
+- .filp (PS2 ADPCM)
+- .ikm (PS2 ADPCM)
+- .musx (PS2 ADPCM)
+- .sfs (PS2 ADPCM)
+- .bg00 (PS2 ADPCM)
+- .dvi (DVI IMA ADPCM)
+- .kcey (EACS IMA ADPCM)
+- .rstm (PS2 ADPCM)
+- .acm (InterPlay ACM)
+- .sli (loop info for .ogg)
+- .psh (PS2 ADPCM)
+- .vig (PS2 ADPCM)
+- .sfl (loop info for .ogg);
+- .um3 (Ogg Vorbis)
+- .rkv (PS2 ADPCM)
+- .psw (PS2 ADPCM)
+- .vas (PS2 ADPCM)
+- .tec (PS2 ADPCM)
+- .enth (PS2 ADPCM)
+- .sdt (GC DSP ADPCM)
+- .aix (CRI ADX ADPCM)
+- .tydsp (GC DSP ADPCM)
+- .matx (xbox audio)
+
+Enjoy!
+-hcs
diff --git a/lib/vgmstream/src/coding/acm_decoder.c b/lib/vgmstream/src/coding/acm_decoder.c
new file mode 100644
index 0000000000..edc53d742a
--- /dev/null
+++ b/lib/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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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/lib/vgmstream/src/coding/acm_decoder.h b/lib/vgmstream/src/coding/acm_decoder.h
new file mode 100644
index 0000000000..2ddff5f84d
--- /dev/null
+++ b/lib/vgmstream/src/coding/acm_decoder.h
@@ -0,0 +1,87 @@
+/*
+ * 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
+
+#include "../streamfile.h"
+
+#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/lib/vgmstream/src/coding/adx_decoder.c b/lib/vgmstream/src/coding/adx_decoder.c
new file mode 100644
index 0000000000..338d82c44b
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(stream->offset+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) + 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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(stream->offset+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;i<stream->adx_channels;i++)
+ {
+ adx_next_key(stream);
+ }
+ }
+
+}
diff --git a/lib/vgmstream/src/coding/aica_decoder.c b/lib/vgmstream/src/coding/aica_decoder.c
new file mode 100644
index 0000000000..9bd6b7468b
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_nibble =
+ (
+ (unsigned)read_8bit(stream->offset+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/lib/vgmstream/src/coding/coding.h b/lib/vgmstream/src/coding/coding.h
new file mode 100644
index 0000000000..de7c26d113
--- /dev/null
+++ b/lib/vgmstream/src/coding/coding.h
@@ -0,0 +1,83 @@
+#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_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_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
+
+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_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_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_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);
+
+#ifdef VGM_USE_VORBIS
+void decode_ogg_vorbis(ogg_vorbis_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_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);
+void decode_mpeg(VGMSTREAMCHANNEL * stream,
+ mpeg_codec_data * data,
+ sample * outbuf, int32_t samples_to_do, int channels);
+#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);
+
+void decode_msadpcm_stereo(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);
+
+#endif
diff --git a/lib/vgmstream/src/coding/eaxa_decoder.c b/lib/vgmstream/src/coding/eaxa_decoder.c
new file mode 100644
index 0000000000..16a4d23e8b
--- /dev/null
+++ b/lib/vgmstream/src/coding/eaxa_decoder.c
@@ -0,0 +1,117 @@
+#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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_16bitBE(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ uint8_t sample_byte = (uint8_t)read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ uint8_t sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i,stream->streamfile);
+ int32_t 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;
+}
+
diff --git a/lib/vgmstream/src/coding/g721_decoder.c b/lib/vgmstream/src/coding/g721_decoder.c
new file mode 100644
index 0000000000..41e147ac44
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=
+ g721_decoder(
+ read_8bit(stream->offset+i/2,stream->streamfile)>>(i&1?4:0),
+ &(stream->g72x_state)
+ );
+ }
+}
diff --git a/lib/vgmstream/src/coding/g72x_state.h b/lib/vgmstream/src/coding/g72x_state.h
new file mode 100644
index 0000000000..bf1a6ade59
--- /dev/null
+++ b/lib/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/lib/vgmstream/src/coding/ima_decoder.c b/lib/vgmstream/src/coding/ima_decoder.c
new file mode 100644
index 0000000000..e190647e57
--- /dev/null
+++ b/lib/vgmstream/src/coding/ima_decoder.c
@@ -0,0 +1,273 @@
+#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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_nibble =
+ (read_8bit(stream->offset+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_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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int step = ADPCMTable[step_index];
+
+ if(vgmstream->layout_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_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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int step = ADPCMTable[step_index];
+ uint8_t sample_byte;
+ int sample_nibble;
+ int sample_decoded;
+ int delta;
+
+ sample_byte = read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int step = ADPCMTable[step_index];
+ uint8_t sample_byte;
+ int sample_nibble;
+ int sample_decoded;
+ int delta;
+
+ sample_byte = read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int step = ADPCMTable[step_index];
+ uint8_t sample_byte;
+ int sample_nibble;
+ int sample_decoded;
+ int delta;
+
+ sample_byte = read_8bit(stream->offset+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;
+}
diff --git a/lib/vgmstream/src/coding/l5_555_decoder.c b/lib/vgmstream/src/coding/l5_555_decoder.c
new file mode 100644
index 0000000000..0a12e83720
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(framesin*0x12+stream->offset+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/lib/vgmstream/src/coding/mpeg_decoder.c b/lib/vgmstream/src/coding/mpeg_decoder.c
new file mode 100644
index 0000000000..ae176af9c2
--- /dev/null
+++ b/lib/vgmstream/src/coding/mpeg_decoder.c
@@ -0,0 +1,129 @@
+#include "../vgmstream.h"
+
+#ifdef VGM_USE_MPEG
+#include <string.h>
+#include <mpg123.h>
+#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);
+ }
+}
+
+/* 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);
+
+ 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;
+ }
+}
+
+#endif
diff --git a/lib/vgmstream/src/coding/msadpcm_decoder.c b/lib/vgmstream/src/coding/msadpcm_decoder.c
new file mode 100644
index 0000000000..9c2fbd9f38
--- /dev/null
+++ b/lib/vgmstream/src/coding/msadpcm_decoder.c
@@ -0,0 +1,96 @@
+#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 }
+};
+
+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; i<first_sample+samples_to_do; i++) {
+ int j;
+
+ for (j=0;j<2;j++)
+ {
+ VGMSTREAMCHANNEL *ch = &vgmstream->ch[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++;
+ }
+ }
+}
diff --git a/lib/vgmstream/src/coding/nds_procyon_decoder.c b/lib/vgmstream/src/coding/nds_procyon_decoder.c
new file mode 100644
index 0000000000..75f86125b2
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(framesin*16+stream->offset+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/lib/vgmstream/src/coding/ngc_afc_decoder.c b/lib/vgmstream/src/coding/ngc_afc_decoder.c
new file mode 100644
index 0000000000..8c796f9518
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(framesin*9+stream->offset+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/lib/vgmstream/src/coding/ngc_dsp_decoder.c b/lib/vgmstream/src/coding/ngc_dsp_decoder.c
new file mode 100644
index 0000000000..27825ae968
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(framesin*8+stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = mem[framesin*8+1+i/2];
+
+#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;
+}
+
+/*
+ * 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/lib/vgmstream/src/coding/ngc_dtk_decoder.c b/lib/vgmstream/src/coding/ngc_dtk_decoder.c
new file mode 100644
index 0000000000..21d1890217
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int sample_byte = read_8bit(framesin*32+stream->offset+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/lib/vgmstream/src/coding/nwa_decoder.c b/lib/vgmstream/src/coding/nwa_decoder.c
new file mode 100644
index 0000000000..a568007859
--- /dev/null
+++ b/lib/vgmstream/src/coding/nwa_decoder.c
@@ -0,0 +1,352 @@
+/* originally from nwatowav.cc 2007.7.28 version, which read: */
+/*
+ * Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
+ * 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 <stdlib.h>
+#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);
+ free(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;i<nwa->channels;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/lib/vgmstream/src/coding/nwa_decoder.h b/lib/vgmstream/src/coding/nwa_decoder.h
new file mode 100644
index 0000000000..80b45ba7c2
--- /dev/null
+++ b/lib/vgmstream/src/coding/nwa_decoder.h
@@ -0,0 +1,67 @@
+/* originally from nwatowav.cc 2007.7.28 version, which read: */
+/*
+ * Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
+ * 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
+
+#include "../streamfile.h"
+
+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/lib/vgmstream/src/coding/ogg_vorbis_decoder.c b/lib/vgmstream/src/coding/ogg_vorbis_decoder.c
new file mode 100644
index 0000000000..5f571d1e7f
--- /dev/null
+++ b/lib/vgmstream/src/coding/ogg_vorbis_decoder.c
@@ -0,0 +1,22 @@
+#include "../vgmstream.h"
+
+#ifdef VGM_USE_VORBIS
+#include <vorbis/vorbisfile.h>
+#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/lib/vgmstream/src/coding/pcm_decoder.c b/lib/vgmstream/src/coding/pcm_decoder.c
new file mode 100644
index 0000000000..c1e64ee81d
--- /dev/null
+++ b/lib/vgmstream/src/coding/pcm_decoder.c
@@ -0,0 +1,68 @@
+#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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_16bitLE(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_16bitBE(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int16_t v = (uint8_t)read_8bit(stream->offset+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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int16_t v = (uint8_t)read_8bit(stream->offset+i*channelspacing,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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ outbuf[sample_count]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile);
+ }
+}
diff --git a/lib/vgmstream/src/coding/psx_decoder.c b/lib/vgmstream/src/coding/psx_decoder.c
new file mode 100644
index 0000000000..775fdd643a
--- /dev/null
+++ b/lib/vgmstream/src/coding/psx_decoder.c
@@ -0,0 +1,181 @@
+#include <math.h>
+#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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+
+ sample=0;
+
+ if(flag<0x07) {
+
+ short sample_byte = (short)read_8bit(stream->offset+(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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+
+ sample=0;
+
+ if(flag<0x07) {
+
+ short sample_byte = (short)read_8bit(stream->offset+(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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ short sample_byte = (short)read_8bit(stream->offset+(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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ short sample_byte = (short)read_8bit(stream->offset+(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;
+}
+
diff --git a/lib/vgmstream/src/coding/sdx2_decoder.c b/lib/vgmstream/src/coding/sdx2_decoder.c
new file mode 100644
index 0000000000..958590eb87
--- /dev/null
+++ b/lib/vgmstream/src/coding/sdx2_decoder.c
@@ -0,0 +1,71 @@
+#include <math.h>
+#include "coding.h"
+#include "../util.h"
+
+/* SDX2 - 2:1 Squareroot-delta-exact compression */
+
+/* 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
+};
+
+void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
+
+ int32_t hist = stream->adpcm_history1_32;
+
+ int i;
+ int32_t sample_count;
+
+ for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int8_t sample_byte = read_8bit(stream->offset+i,stream->streamfile);
+ int16_t sample;
+
+ if (!(sample_byte & 1)) hist = 0;
+ sample = hist + squares[sample_byte+128];
+
+ hist = outbuf[sample_count] = clamp16(sample);
+ }
+ stream->adpcm_history1_32=hist;
+}
+
+void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
+
+ int32_t hist = stream->adpcm_history1_32;
+
+ int i;
+ int32_t sample_count;
+
+ for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ int8_t sample_byte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
+ int16_t sample;
+
+ if (!(sample_byte & 1)) hist = 0;
+ sample = hist + squares[sample_byte+128];
+
+ hist = outbuf[sample_count] = clamp16(sample);
+ }
+ stream->adpcm_history1_32=hist;
+}
diff --git a/lib/vgmstream/src/coding/ws_decoder.c b/lib/vgmstream/src/coding/ws_decoder.c
new file mode 100644
index 0000000000..b72193dc7c
--- /dev/null
+++ b/lib/vgmstream/src/coding/ws_decoder.c
@@ -0,0 +1,146 @@
+#include <math.h>
+#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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing,offset++) {
+ outbuf[sample_count]=((uint8_t)read_8bit(offset,stream->streamfile)-0x80)*0x100;
+ }
+ } else {
+ if (first_sample == 0) {
+ hist = 0x80;
+ samples_left_in_frame = 0;
+ }
+ /* actually decompress */
+ for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; ) {
+ uint8_t header;
+ uint8_t count;
+
+ if (samples_left_in_frame == 0) {
+ header_off = offset;
+ offset++;
+ }
+
+ header = read_8bit(header_off,stream->streamfile);
+ 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 */
+ i<first_sample+samples_to_do; /* up to samples_to_do */
+ i++,sample_count+=channelspacing, /* done with writing a sample */
+ samples_left_in_frame--) { /* done with reading a sample */
+ int twobit = ((count + 1)*4-samples_left_in_frame)%4;
+ uint8_t sample;
+ sample = read_8bit(offset,stream->streamfile);
+ 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 */
+ i<first_sample+samples_to_do; /* up to samples_to_do */
+ i++,sample_count+=channelspacing, /* done with writing a sample */
+ samples_left_in_frame--) { /* done with reading a sample */
+ int nibble = ((count + 1)*4-samples_left_in_frame)%2;
+ uint8_t sample;
+ sample = read_8bit(offset,stream->streamfile);
+ 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 */
+ i<first_sample+samples_to_do; /* up to samples_to_do */
+ offset++, /* done with a byte */
+ i++,sample_count+=channelspacing, /* done with writing a sample */
+ samples_left_in_frame--) { /* done with reading a sample */
+ outbuf[sample_count]=((hist=(uint8_t)read_8bit(offset,stream->streamfile))-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 */
+ i<first_sample+samples_to_do; /* up to samples_to_do */
+ i++,sample_count+=channelspacing, /* done with writing a sample */
+ samples_left_in_frame--) { /* done with reading a sample */
+ outbuf[sample_count]=(hist-0x80)*0x100;
+ }
+ }
+ }
+ }
+
+ stream->offset = offset;
+ stream->adpcm_history1_16 = hist;
+ stream->samples_left_in_frame = samples_left_in_frame;
+ stream->frame_header_offset = header_off;
+}
diff --git a/lib/vgmstream/src/coding/xa_decoder.c b/lib/vgmstream/src/coding/xa_decoder.c
new file mode 100644
index 0000000000..c974cea6c5
--- /dev/null
+++ b/lib/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; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
+ short sample_byte = (short)read_8bit(stream->offset+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/lib/vgmstream/src/layout/aax_layout.c b/lib/vgmstream/src/layout/aax_layout.c
new file mode 100644
index 0000000000..2e0834ae99
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ int samples_to_do;
+ int samples_this_block = data->sample_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;i<data->adxs[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;i<data->adxs[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/lib/vgmstream/src/layout/aix_layout.c b/lib/vgmstream/src/layout/aix_layout.c
new file mode 100644
index 0000000000..2e8a7b8319
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ int samples_to_do;
+ int samples_this_block = data->sample_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;i<data->adxs[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;i<data->adxs[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/lib/vgmstream/src/layout/ast_blocked.c b/lib/vgmstream/src/layout/ast_blocked.c
new file mode 100644
index 0000000000..d882a0de1c
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset +
+ 0x20 + vgmstream->current_block_size*i;
+ }
+}
diff --git a/lib/vgmstream/src/layout/blocked.c b/lib/vgmstream/src/layout/blocked.c
new file mode 100644
index 0000000000..036e69a36f
--- /dev/null
+++ b/lib/vgmstream/src/layout/blocked.c
@@ -0,0 +1,126 @@
+#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_written<sample_count) {
+ int samples_to_do;
+
+ if (vgmstream->loop_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_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;
+ 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/lib/vgmstream/src/layout/caf_blocked.c b/lib/vgmstream/src/layout/caf_blocked.c
new file mode 100644
index 0000000000..d944baa01c
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;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/lib/vgmstream/src/layout/de2_blocked.c b/lib/vgmstream/src/layout/de2_blocked.c
new file mode 100644
index 0000000000..a89ddbafac
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
+ }
+}
diff --git a/lib/vgmstream/src/layout/ea_block.c b/lib/vgmstream/src/layout/ea_block.c
new file mode 100644
index 0000000000..a195e7bf73
--- /dev/null
+++ b/lib/vgmstream/src/layout/ea_block.c
@@ -0,0 +1,142 @@
+#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;i<vgmstream->channels;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;i<vgmstream->channels;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;i<vgmstream->channels;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_PCM16LE_int:
+ vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-0x0C;
+ for(i=0;i<vgmstream->channels;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;i<vgmstream->channels;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;i<vgmstream->channels;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)) {
+ for(i=0;i<vgmstream->channels;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;i<vgmstream->channels;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;i<vgmstream->channels;i++)
+ vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2));
+ } else {
+
+ for (i=0;i<vgmstream->channels;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/lib/vgmstream/src/layout/emff_blocked.c b/lib/vgmstream/src/layout/emff_blocked.c
new file mode 100644
index 0000000000..b3ed7f5f24
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset+0x40+(vgmstream->current_block_size*i);
+ }
+}
+
diff --git a/lib/vgmstream/src/layout/filp_blocked.c b/lib/vgmstream/src/layout/filp_blocked.c
new file mode 100644
index 0000000000..550c6e7381
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset+0x800+(vgmstream->current_block_size*i);
+
+ }
+}
diff --git a/lib/vgmstream/src/layout/gsb_blocked.c b/lib/vgmstream/src/layout/gsb_blocked.c
new file mode 100644
index 0000000000..80ce3eef1d
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i);
+ }
+}
diff --git a/lib/vgmstream/src/layout/halpst_blocked.c b/lib/vgmstream/src/layout/halpst_blocked.c
new file mode 100644
index 0000000000..affb135f77
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset +
+ 0x20 + vgmstream->current_block_size*i;
+ }
+}
diff --git a/lib/vgmstream/src/layout/ims_block.c b/lib/vgmstream/src/layout/ims_block.c
new file mode 100644
index 0000000000..c5df59480c
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
+ }
+}
diff --git a/lib/vgmstream/src/layout/interleave.c b/lib/vgmstream/src/layout/interleave.c
new file mode 100644
index 0000000000..f10ee574e7
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ int samples_to_do;
+
+ if (vgmstream->loop_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;chan<vgmstream->channels;chan++)
+ vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_smallblock_size*chan;
+ } else {
+
+ for (chan=0;chan<vgmstream->channels;chan++)
+ vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*vgmstream->channels;
+ }
+ vgmstream->samples_into_block=0;
+ }
+
+ }
+}
diff --git a/lib/vgmstream/src/layout/interleave_byte.c b/lib/vgmstream/src/layout/interleave_byte.c
new file mode 100644
index 0000000000..c9f8eb0886
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ int samples_to_do;
+
+ if (vgmstream->loop_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;j<vgmstream->channels;j++) {
+ for (i=0;i<frame_size;i++) {
+ sample_data[i] = read_8bit(vgmstream->ch[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;chan<vgmstream->channels;chan++)
+ vgmstream->ch[chan].offset+=frame_size*vgmstream->channels;
+ vgmstream->samples_into_block=0;
+ }
+
+ }
+}
diff --git a/lib/vgmstream/src/layout/layout.h b/lib/vgmstream/src/layout/layout.h
new file mode 100644
index 0000000000..3d7ab19f2d
--- /dev/null
+++ b/lib/vgmstream/src/layout/layout.h
@@ -0,0 +1,57 @@
+#ifndef _LAYOUT_H
+#define _LAYOUT_H
+
+#include "../streamtypes.h"
+#include "../vgmstream.h"
+
+void ast_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 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);
+
+#endif
diff --git a/lib/vgmstream/src/layout/mus_acm_layout.c b/lib/vgmstream/src/layout/mus_acm_layout.c
new file mode 100644
index 0000000000..bda82b501c
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ ACMStream *acm = data->files[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/lib/vgmstream/src/layout/nolayout.c b/lib/vgmstream/src/layout/nolayout.c
new file mode 100644
index 0000000000..dd36976fbb
--- /dev/null
+++ b/lib/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_written<sample_count) {
+ int samples_to_do;
+
+ if (vgmstream->loop_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/lib/vgmstream/src/layout/str_snds_blocked.c b/lib/vgmstream/src/layout/str_snds_blocked.c
new file mode 100644
index 0000000000..e18f1510ee
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18;
+ }
+}
diff --git a/lib/vgmstream/src/layout/thp_blocked.c b/lib/vgmstream/src/layout/thp_blocked.c
new file mode 100644
index 0000000000..f4ed39e876
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;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/lib/vgmstream/src/layout/vs_blocked.c b/lib/vgmstream/src/layout/vs_blocked.c
new file mode 100644
index 0000000000..76e4cb277d
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;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/lib/vgmstream/src/layout/ws_aud_blocked.c b/lib/vgmstream/src/layout/ws_aud_blocked.c
new file mode 100644
index 0000000000..dfc824a575
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset +
+ 8 + vgmstream->current_block_size*i;
+ }
+}
diff --git a/lib/vgmstream/src/layout/wsi_blocked.c b/lib/vgmstream/src/layout/wsi_blocked.c
new file mode 100644
index 0000000000..6dcd79a52e
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset +
+ 0x10 + (vgmstream->current_block_size+0x10)*i;
+ }
+}
diff --git a/lib/vgmstream/src/layout/xa_blocked.c b/lib/vgmstream/src/layout/xa_blocked.c
new file mode 100644
index 0000000000..6de0623a7b
--- /dev/null
+++ b/lib/vgmstream/src/layout/xa_blocked.c
@@ -0,0 +1,49 @@
+#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 :(
+ 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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset;
+ }
+}
diff --git a/lib/vgmstream/src/layout/xvas_block.c b/lib/vgmstream/src/layout/xvas_block.c
new file mode 100644
index 0000000000..ee78c3ad10
--- /dev/null
+++ b/lib/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;i<vgmstream->channels;i++) {
+ vgmstream->ch[i].offset = vgmstream->current_block_offset;
+ }
+ vgmstream->current_block_size /=2;
+
+}
diff --git a/lib/vgmstream/src/libvgmstream.vcproj b/lib/vgmstream/src/libvgmstream.vcproj
new file mode 100644
index 0000000000..8d42e13f55
--- /dev/null
+++ b/lib/vgmstream/src/libvgmstream.vcproj
@@ -0,0 +1,1027 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8,00"
+ Name="libvgmstream"
+ ProjectGUID="{54A6AD11-5369-4895-A06F-E255ABB99B11}"
+ RootNamespace="libvgmstream"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../ext_includes"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../ext_includes"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release DLL|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="../ext_includes"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="$(OutDir)\vgmstream.dll"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\streamfile.h"
+ >
+ </File>
+ <File
+ RelativePath=".\streamtypes.h"
+ >
+ </File>
+ <File
+ RelativePath=".\util.h"
+ >
+ </File>
+ <File
+ RelativePath=".\vgmstream.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\streamfile.c"
+ >
+ </File>
+ <File
+ RelativePath=".\util.c"
+ >
+ </File>
+ <File
+ RelativePath=".\vgmstream.c"
+ >
+ </File>
+ <File
+ RelativePath="..\XBMCVGM.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="meta"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath=".\meta\meta.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath=".\meta\aax.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\acm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\adx_header.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\afc_header.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\agsc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ahx.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\aifc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\aix.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ast.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\bgw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\brstm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\capdsp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\Cstr.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\dc_asd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\dc_idvi.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\dc_kcey.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\dc_str.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\dc_wav_dcs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\de2.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ea_header.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ea_old.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\emff.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\fsb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\gca.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\gcsw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\genh.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\gsp_gsb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\halpst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\idsp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ish_isd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ivb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\kraw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\msvp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\mus_acm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\musc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\musx.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\naomi_spsd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\nds_sad.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\nds_strm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_adpdtk.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_bh2pcm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_caf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_dsp_std.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_ffcc_str.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_pdt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_ssm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_tydsp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_waa_wac_wad_wam.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ngc_ymf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\nwa.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ogg_vorbis_file.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\pcm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\pos.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_ads.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_ass.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_aus.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_bg00.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_bmdx.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_ccc.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_dxh.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_enth.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_exst.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_filp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_gbts.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_hgc1.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_ikm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_ild.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_int.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_joe.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_kces.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_leg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_mib.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_mic.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_mihb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_npsf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_p2bt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_pnb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_psh.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_psw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_rkv.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_rnd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_rstm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_rws.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_rxw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_seg.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_sfs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_sl3.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_str.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_svag.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_tec.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_vag.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_vas.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_vpk.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_xa2.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ps2_xa30.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\psx_cdxa.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\psx_fag.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\psx_gms.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\raw.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\riff.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\rs03.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\rsd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\rsf.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\rwsd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\rwx.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\sat_dvi.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\sat_sap.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\sdt.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\sfl.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\sli.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\spt_spd.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ss_stream.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\str_asr.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\str_snds.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\svs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\thp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\vgs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\vs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\wii_mus.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\wii_smp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\wii_sng.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\wii_sts.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ws_aud.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_ims.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_stma.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_wavm.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_wvs.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_xmu.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_xvas.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xbox_xwav.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xss.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\xwb.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\ydsp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\meta\zwdsp.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="coding"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath=".\coding\acm_decoder.h"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\coding.h"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\g72x_state.h"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\nwa_decoder.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath=".\coding\acm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\adx_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\aica_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\eaxa_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\g721_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ima_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\l5_555_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\mpeg_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\msadpcm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\nds_procyon_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ngc_afc_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ngc_dsp_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ngc_dtk_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\nwa_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ogg_vorbis_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\pcm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\psx_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\sdx2_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\ws_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath=".\coding\xa_decoder.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="layout"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath=".\layout\layout.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath=".\layout\aax_layout.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\aix_layout.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\ast_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\caf_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\de2_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\ea_block.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\emff_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\filp_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\gsb_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\halpst_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\ims_block.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\interleave.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\interleave_byte.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\mus_acm_layout.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\nolayout.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\str_snds_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\thp_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\vs_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\ws_aud_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\wsi_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\xa_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath=".\layout\xvas_block.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/vgmstream/src/meta/Cstr.c b/lib/vgmstream/src/meta/Cstr.c
new file mode 100644
index 0000000000..0cd2867a5a
--- /dev/null
+++ b/lib/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[260];
+
+ 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<start_offset+0x800 &&
+ (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile) ||
+ read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile)))
+ first_data+=8;
+#ifdef DEBUG
+ fprintf(stderr,"guessed first_data at %#x\n",first_data);
+#endif
+ }
+
+ /* check initial predictor/scale */
+ if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile))
+ goto fail;
+ if (read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile))
+ goto fail;
+
+#ifdef DEBUG
+ fprintf(stderr,"p/s ok\n");
+#endif
+
+ /* check type==0 and gain==0 */
+ if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile))
+ goto fail;
+ if (read_16bitBE(0x8e,streamFile) || read_16bitBE(0xbc,streamFile))
+ goto fail;
+
+#ifdef DEBUG
+ fprintf(stderr,"type & gain ok\n");
+#endif
+
+ /* check for loop flag agreement */
+ if (read_16bitBE(0x2c,streamFile) != read_16bitBE(0x8c,streamFile))
+ goto fail;
+
+#ifdef DEBUG
+ fprintf(stderr,"loop flags agree\n");
+#endif
+
+ loop_offset = start_offset+read_32bitBE(0x10,streamFile)*2;
+ if (loop_flag) {
+ int loops_ok=0;
+ /* check loop predictor/scale */
+ /* some fuzz allowed */
+ for (loop_adjust=0;loop_adjust>=-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/lib/vgmstream/src/meta/aax.c b/lib/vgmstream/src/meta/aax.c
new file mode 100644
index 0000000000..7853c0ed3e
--- /dev/null
+++ b/lib/vgmstream/src/meta/aax.c
@@ -0,0 +1,733 @@
+#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[260];
+ off_t *segment_offset = NULL;
+ off_t *segment_size = NULL;
+ int32_t sample_count;
+ int table_error;
+
+ 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;i<segment_count;i++) {
+ data->adxs[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;i<data->segment_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 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;
+}
diff --git a/lib/vgmstream/src/meta/acm.c b/lib/vgmstream/src/meta/acm.c
new file mode 100644
index 0000000000..c58e596788
--- /dev/null
+++ b/lib/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[260];
+
+ 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/lib/vgmstream/src/meta/adx_header.c b/lib/vgmstream/src/meta/adx_header.c
new file mode 100644
index 0000000000..57952118ce
--- /dev/null
+++ b/lib/vgmstream/src/meta/adx_header.c
@@ -0,0 +1,347 @@
+#ifdef _MSC_VER
+#define _USE_MATH_DEFINES
+#endif
+#include <math.h>
+#include <string.h>
+#include <limits.h>
+#include "meta.h"
+
+#include "../coding/coding.h"
+#include "../util.h"
+
+static int find_key(STREAMFILE *file, 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[260];
+ 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, &xor_start, &xor_mult, &xor_add))
+ {
+ coding_type = coding_CRI_ADX_enc;
+ 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? */
+ 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);
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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)
+ {
+ 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;j<i;j++)
+ adx_next_key(&vgmstream->ch[i]);
+ }
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
+
+/* guessadx stuff */
+
+static struct {
+ uint16_t start,mult,add;
+} keys[] = {
+ /* 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.dev (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},
+};
+
+static const int key_count = sizeof(keys)/sizeof(keys[0]);
+
+/* return 0 if not found, 1 if found and set parameters */
+static int find_key(STREAMFILE *file, 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<bruteframecount || bruteframecount<0)
+ bruteframecount=framecount;
+ }
+
+ /* find longest run of nonzero frames */
+ {
+ int longest=-1,longest_length=-1;
+ int i;
+ int length=0;
+ for (i=0;i<bruteframecount;i++) {
+ static const unsigned char zeroes[18]={0};
+ unsigned char buf[18];
+ read_streamfile(buf, startoff+i*18, 18, file);
+ if (memcmp(zeroes,buf,18)) length++;
+ else length=0;
+ if (length > 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; i<bruteframe; i++) {
+ prescales[i] = read_16bitBE(startoff+i*18, file);
+ }
+ }
+
+ /* read in the scales */
+ {
+ int i;
+ for (i=0; i < scales_to_do; i++) {
+ scales[i] = read_16bitBE(startoff+(bruteframe+i)*18, file);
+ }
+ }
+
+ /* guess each of the keys */
+ for (key_id=0;key_id<=key_count;key_id++) {
+ /* test pre-scales */
+ uint16_t xor = keys[key_id].start;
+ uint16_t mult = keys[key_id].mult;
+ uint16_t add = keys[key_id].add;
+ int i;
+
+ for (i=0;i<bruteframe &&
+ ((prescales[i]&0x6000)==(xor&0x6000) ||
+ prescales[i]==0);
+ i++) {
+ xor = xor * mult + add;
+ }
+
+ if (i == bruteframe)
+ {
+ /* test */
+ for (i=0;i<scales_to_do &&
+ (scales[i]&0x6000)==(xor&0x6000);i++) {
+ xor = xor * mult + add;
+ }
+ if (i == scales_to_do)
+ {
+ *xor_start = keys[key_id].start;
+ *xor_mult = keys[key_id].mult;
+ *xor_add = keys[key_id].add;
+
+ rc = 1;
+ goto find_key_cleanup;
+ }
+ }
+ }
+ }
+
+find_key_cleanup:
+ if (scales) free(scales);
+ if (prescales) free(prescales);
+ return rc;
+}
diff --git a/lib/vgmstream/src/meta/afc_header.c b/lib/vgmstream/src/meta/afc_header.c
new file mode 100644
index 0000000000..d7bec9c0b1
--- /dev/null
+++ b/lib/vgmstream/src/meta/afc_header.c
@@ -0,0 +1,67 @@
+#include "meta.h"
+#include "../util.h"
+
+VGMSTREAM * init_vgmstream_afc(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ int loop_flag;
+ const int channel_count = 2; /* .afc seems to be stereo only */
+
+ /* check extension, case insensitive */
+ streamFile->get_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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/agsc.c b/lib/vgmstream/src/meta/agsc.c
new file mode 100644
index 0000000000..4388df1cb3
--- /dev/null
+++ b/lib/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[260];
+
+ 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;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=
+ start_offset;
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/ahx.c b/lib/vgmstream/src/meta/ahx.c
new file mode 100644
index 0000000000..cce0040b1d
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/aifc.c b/lib/vgmstream/src/meta/aifc.c
new file mode 100644
index 0000000000..900bacacd7
--- /dev/null
+++ b/lib/vgmstream/src/meta/aifc.c
@@ -0,0 +1,305 @@
+#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;i<marker_count;i++) {
+ int name_length;
+
+ if (read_16bitBE(marker_offset,streamFile) == marker_id)
+ return read_32bitBE(marker_offset+2,streamFile);
+
+ name_length = (uint8_t)read_8bit(marker_offset+6,streamFile) + 1;
+ if (name_length % 2) name_length++;
+ marker_offset += 6 + name_length;
+ }
+
+ return -1;
+}
+
+VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ off_t file_size = -1;
+ int channel_count = 0;
+ int sample_count = 0;
+ int sample_size = 0;
+ int sample_rate = 0;
+ int coding_type = -1;
+ off_t start_offset = -1;
+ int interleave = -1;
+
+ int loop_flag = 0;
+ int32_t loop_start = -1;
+ int32_t loop_end = -1;
+
+ int AIFFext = 0;
+ int AIFCext = 0;
+ int AIFF = 0;
+ int AIFC = 0;
+ int FormatVersionChunkFound = 0;
+ int CommonChunkFound = 0;
+ int SoundDataChunkFound = 0;
+ int MarkerChunkFound = 0;
+ off_t MarkerChunkOffset = -1;
+ int InstrumentChunkFound =0;
+ off_t InstrumentChunkOffset = -1;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (!strcasecmp("aifc",filename_extension(filename)) ||
+ !strcasecmp("afc",filename_extension(filename)) ||
+ !strcasecmp("aifcl",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 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/aix.c b/lib/vgmstream/src/meta/aix.c
new file mode 100644
index 0000000000..cb545287b6
--- /dev/null
+++ b/lib/vgmstream/src/meta/aix.c
@@ -0,0 +1,410 @@
+#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[260];
+ 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;
+
+ 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 = 0x20+0x10*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(0x20+0x10*i+0,streamFile);
+ samples_in_segment[i] = read_32bitBE(0x20+0x10*i+0x08,streamFile);
+ /*printf("samples_in_segment[%d]=%d\n",i,samples_in_segment[i]);*/
+ /* all segments must have equal samplerate */
+ if (read_32bitBE(0x20+0x10*i+0x0c,streamFile) != sample_rate)
+ 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;i<segment_count*stream_count;i++) {
+ data->adxs[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;i<data->segment_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/lib/vgmstream/src/meta/ast.c b/lib/vgmstream/src/meta/ast.c
new file mode 100644
index 0000000000..ffcf80675f
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/bgw.c b/lib/vgmstream/src/meta/bgw.c
new file mode 100644
index 0000000000..4bc0b19823
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/brstm.c b/lib/vgmstream/src/meta/brstm.c
new file mode 100644
index 0000000000..168e7b7ac2
--- /dev/null
+++ b/lib/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[260];
+
+ 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;j<vgmstream->channels;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;i<channel_count;i++) {
+ if (vgmstream->layout_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/lib/vgmstream/src/meta/capdsp.c b/lib/vgmstream/src/meta/capdsp.c
new file mode 100644
index 0000000000..02d97d1d74
--- /dev/null
+++ b/lib/vgmstream/src/meta/capdsp.c
@@ -0,0 +1,71 @@
+#include "meta.h"
+#include "../util.h"
+
+/* CAPDSP (found in Capcom games) */
+VGMSTREAM * init_vgmstream_capdsp(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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 = 0x2000;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/dc_asd.c b/lib/vgmstream/src/meta/dc_asd.c
new file mode 100644
index 0000000000..aae03096e7
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/dc_idvi.c b/lib/vgmstream/src/meta/dc_idvi.c
new file mode 100644
index 0000000000..7473fdb7d9
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/dc_kcey.c b/lib/vgmstream/src/meta/dc_kcey.c
new file mode 100644
index 0000000000..7fbf5584d8
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/dc_str.c b/lib/vgmstream/src/meta/dc_str.c
new file mode 100644
index 0000000000..071dcbb380
--- /dev/null
+++ b/lib/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[260];
+ off_t start_offset;
+ int loop_flag = 0;
+ int interleave;
+ int channel_count;
+ int samples;
+ 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(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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;
+#if 0
+ /* check header */
+ if ((read_32bitBE(0x00,streamFile) != 0x00000002) &&
+ (read_32bitBE(0x10,streamFile) != 0x00000100) &&
+ (read_32bitBE(0x1C,streamFile) != 0x1F000000))
+ goto fail;
+#endif
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/dc_wav_dcs.c b/lib/vgmstream/src/meta/dc_wav_dcs.c
new file mode 100644
index 0000000000..654042716f
--- /dev/null
+++ b/lib/vgmstream/src/meta/dc_wav_dcs.c
@@ -0,0 +1,116 @@
+#include "meta.h"
+#include "../util.h"
+
+/* WAV+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... */
+
+VGMSTREAM * init_vgmstream_dc_wav_dcs(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ STREAMFILE * streamFileWAV = NULL;
+ char filename[260];
+ char filenameWAV[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(filenameWAV,filename);
+ strcpy(filenameWAV+strlen(filenameWAV)-3,"wav");
+
+ /* Look if the Header file is present, else cancel vgmstream */
+ streamFileWAV = streamFile->open(streamFile,filenameWAV,STREAMFILE_DEFAULT_BUFFER_SIZE);
+ if (!streamFileWAV) goto fail;
+
+ /* check header */
+ if (read_32bitBE(0x00,streamFileWAV) != 0x52494646 || /* "RIFF" */
+ read_32bitBE(0x08,streamFileWAV) != 0x57415645 || /* "WAVE" */
+ read_32bitBE(0x0C,streamFileWAV) != 0x34582E76 || /* 0x34582E76 */
+ read_32bitBE(0x3C,streamFileWAV) != 0x406E616D) /* "@nam" */
+ goto fail;
+
+ /* scan file until we find a "data" string */
+ file_size = get_streamfile_size(streamFileWAV);
+ {
+ 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,streamFileWAV));
+ 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,streamFileWAV);
+ frequency = read_32bitLE(current_chunk-0x0C,streamFileWAV);
+ }
+
+ 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_WAV_DCS;
+
+ /* open the file for reading */
+ {
+ for (i=0;i<channel_count;i++) {
+ vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
+ vgmstream->ch[i].offset = 0;
+ vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */
+ if (!vgmstream->ch[i].streamfile) goto fail;
+ }
+ }
+
+ close_streamfile(streamFileWAV); streamFileWAV=NULL;
+
+ 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/lib/vgmstream/src/meta/de2.c b/lib/vgmstream/src/meta/de2.c
new file mode 100644
index 0000000000..f1b051eb06
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ea_header.c b/lib/vgmstream/src/meta/ea_header.c
new file mode 100644
index 0000000000..c9192134b1
--- /dev/null
+++ b/lib/vgmstream/src/meta/ea_header.c
@@ -0,0 +1,293 @@
+#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;
+ 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_offset<length);
+
+ if(ea->platform==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[260];
+
+ 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("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_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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ea_old.c b/lib/vgmstream/src/meta/ea_old.c
new file mode 100644
index 0000000000..701d14b60f
--- /dev/null
+++ b/lib/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[260];
+ int channel_count;
+ int loop_flag;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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_offset<get_streamfile_size(streamFile)-8);
+
+ // Reset values ...
+ // setting up the first header by calling the eacs_block_update sub
+ if(little_endian)
+ vgmstream->next_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/lib/vgmstream/src/meta/emff.c b/lib/vgmstream/src/meta/emff.c
new file mode 100644
index 0000000000..0798ddfee1
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;j<vgmstream->channels;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;j<vgmstream->channels;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;j<vgmstream->channels;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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/fsb.c b/lib/vgmstream/src/meta/fsb.c
new file mode 100644
index 0000000000..fe3a0ca5bf
--- /dev/null
+++ b/lib/vgmstream/src/meta/fsb.c
@@ -0,0 +1,322 @@
+#include "meta.h"
+#include "../util.h"
+
+/* comment from hcs:
+((uint8_t)read_8bit(offset, file))&0xf for the low nibble,
+((uint8_t)read_8bit(offset, file)) >> 4 for the high one
+((uint8_t)read_8bit(0x4B,streamFile) >> (1?0:4))&0xf;
+*/
+/* FSB1 */
+VGMSTREAM * init_vgmstream_fsb1(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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 */
+VGMSTREAM * init_vgmstream_fsb3(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+
+ /* int fsb3_included_files; */
+ int fsb3_headerlen = 0x18;
+ int fsb3_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) != 0x46534233) /* "FSB3" */
+ 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(0x48,streamFile) == 0x02000806) {
+ loop_flag = 1;
+ } else {
+ loop_flag = 0; /* (read_32bitLE(0x08,streamFile)!=0); */
+ }
+
+ /* Channel check
+ if (read_16bitLE(0x56,streamFile) == 2) {
+ channel_count = 2;
+ } else {
+ goto fail;
+ }
+ */
+
+ channel_count = read_16bitLE(0x56,streamFile);
+
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ /* This will be tricky ;o) */
+ fsb3_format = read_32bitBE(0x48,streamFile);
+ switch (fsb3_format) {
+ case 0x40008800: /* PS2 (Agent Hugo, Flat Out 2) */
+ case 0x41008800: /* PS2 (Flat Out) */
+ case 0x42008800: /* PS2 (Jackass - The Game) */
+ case 0x01008804: /* PS2 (Cold Fear) */
+ case 0x02008804: /* PS2 (Shrek - Smash 'n Crash */
+ vgmstream->coding_type = coding_PSX;
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x10;
+ vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*28/16/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x40,streamFile);
+ vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile))*28/16/channel_count;
+ }
+ break;
+ case 0x02000806: /* WII (Metroid Prime 3) */
+ case 0x01000806: /* WII (Metroid Prime 3) */
+ case 0x40000802: /* WII (WWE Smackdown Vs. Raw 2008) */
+ case 0x40000882: /* WII (Bully) */
+ case 0x41000802: /* GC (Dysney's Incredibles, The) */
+ vgmstream->coding_type = coding_NGC_DSP;
+ vgmstream->layout_type = layout_interleave_byte;
+ vgmstream->interleave_block_size = 2;
+ vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*14/8/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x40,streamFile);
+ vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile))*14/8/channel_count;
+ }
+ break;
+ case 0x40004020: /* WII (Guitar Hero III), uses Xbox-ish IMA */
+ case 0x400040A0: /* WII (Guitar Hero III), uses Xbox-ish IMA */
+ case 0x41004800: /* XBOX (FlatOut, Rainbow Six - Lockdown) */
+ case 0x01004804: /* XBOX (Cold Fear) <- maybe IMA??? */
+ vgmstream->coding_type = coding_XBOX;
+ vgmstream->layout_type = layout_none;
+ vgmstream->num_samples = read_32bitLE(0x0C,streamFile)*64/36/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x40,streamFile);
+ vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile)*64/36/channel_count;
+ }
+ break;
+ default:
+ goto fail;
+ }
+ /* fill in the vital statistics */
+ start_offset = (read_32bitLE(0x08,streamFile))+fsb3_headerlen;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitLE(0x4C,streamFile);
+ vgmstream->meta_type = meta_FSB3;
+
+ if (vgmstream->coding_type == coding_NGC_DSP) {
+ int i;
+ for (i=0;i<16;i++) {
+ vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x68+i*2,streamFile);
+ }
+ if (vgmstream->channels) {
+ for (i=0;i<16;i++) {
+ vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x96+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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ off_t start_offset;
+
+ /* int fsb1_included_files; */
+ 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))) 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) {
+ loop_flag = 1;
+ } 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 = 0x80;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitLE(0x64,streamFile);
+ fsb4_format = read_32bitBE(0x60,streamFile);
+ switch (fsb4_format) {
+ /* PS2 (Spider Man - Web of Shadows), Speed Racer */
+ case 0x40008800:
+ 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;
+ default:
+ goto fail;
+
+ }
+
+ vgmstream->meta_type = meta_FSB4;
+
+
+ /* 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+
+ 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/lib/vgmstream/src/meta/gca.c b/lib/vgmstream/src/meta/gca.c
new file mode 100644
index 0000000000..f6ff5bbdf0
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/gcsw.c b/lib/vgmstream/src/meta/gcsw.c
new file mode 100644
index 0000000000..dfcbd4ad37
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ 0x20+0x8000*i;
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/genh.c b/lib/vgmstream/src/meta/genh.c
new file mode 100644
index 0000000000..5b81e6971c
--- /dev/null
+++ b/lib/vgmstream/src/meta/genh.c
@@ -0,0 +1,398 @@
+#include "../vgmstream.h"
+#include "meta.h"
+#include "../layout/layout.h"
+#include "../util.h"
+#ifdef VGM_USE_MPEG
+#include <mpg123.h>
+#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[260];
+ int coding;
+#ifdef VGM_USE_MPEG
+ mpeg_codec_data *data = NULL;
+#endif
+
+ /* 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) */
+ /* ... 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;
+ 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_SDX2:
+ case coding_PSX:
+ case coding_PSX_badflags:
+ case coding_DVI_IMA:
+ case coding_IMA:
+ case coding_AICA:
+ 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_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;i<channel_count;i++) {
+ off_t chstart_offset = start_offset;
+
+ switch (coding) {
+ case coding_PSX:
+ case coding_PSX_badflags:
+ case coding_PCM16BE:
+ case coding_PCM16LE:
+ case coding_SDX2:
+ case coding_SDX2_int:
+ case coding_DVI_IMA:
+ case coding_IMA:
+ case coding_PCM8:
+ case coding_PCM8_U_int:
+ case coding_AICA:
+ case coding_INT_DVI_IMA:
+ case coding_INT_IMA:
+ 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:
+ /* 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) {
+ int rc;
+ off_t read_offset;
+ 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,vgmstream->ch[0].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;
+ if (rate != vgmstream->sample_rate ||
+ channels != vgmstream->channels ||
+ encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail;
+ mpg123_info(data->m,&mi);
+ if (mi.rate != vgmstream->sample_rate) goto mpeg_fail;
+ if (mi.version == MPG123_1_0 && mi.layer == 1)
+ vgmstream->coding_type = coding_MPEG1_L1;
+ else if (mi.version == MPG123_1_0 && mi.layer == 2)
+ vgmstream->coding_type = coding_MPEG1_L2;
+ else if (mi.version == MPG123_1_0 && mi.layer == 3)
+ vgmstream->coding_type = coding_MPEG1_L3;
+ else if (mi.version == MPG123_2_0 && mi.layer == 1)
+ vgmstream->coding_type = coding_MPEG2_L1;
+ else if (mi.version == MPG123_2_0 && mi.layer == 2)
+ vgmstream->coding_type = coding_MPEG2_L2;
+ else if (mi.version == MPG123_2_0 && mi.layer == 3)
+ vgmstream->coding_type = coding_MPEG2_L3;
+ else if (mi.version == MPG123_2_5 && mi.layer == 1)
+ vgmstream->coding_type = coding_MPEG25_L1;
+ else if (mi.version == MPG123_2_5 && mi.layer == 2)
+ vgmstream->coding_type = coding_MPEG25_L2;
+ else if (mi.version == MPG123_2_5 && mi.layer == 3)
+ vgmstream->coding_type = coding_MPEG25_L3;
+ else goto mpeg_fail;
+ }
+
+ /* reinit, to ignore the reading we've done so far */
+ mpg123_open_feed(data->m);
+
+ vgmstream->codec_data = data;
+ }
+#endif
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+#ifdef VGM_USE_MPEG
+mpeg_fail:
+ if (data) {
+ mpg123_delete(data->m);
+ free(data);
+ }
+#endif
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/gsp_gsb.c b/lib/vgmstream/src/meta/gsp_gsb.c
new file mode 100644
index 0000000000..0caa034615
--- /dev/null
+++ b/lib/vgmstream/src/meta/gsp_gsb.c
@@ -0,0 +1,111 @@
+#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[260];
+ char filenameGSP[260];
+ off_t start_offset;
+ int channel_count;
+ int loop_flag;
+ int header_len;
+ off_t coef1_start;
+ off_t coef2_start;
+ int dsp_blocks;
+
+ /* 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;
+ dsp_blocks = read_32bitBE(header_len-0x5C,streamFileGSP);
+
+ /* 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 */
+ 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=0;
+ 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->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_offset<get_streamfile_size(streamFile));
+
+ gsb_block_update(start_offset,vgmstream);
+
+ close_streamfile(streamFileGSP); streamFileGSP=NULL;
+
+ return vgmstream;
+
+
+ /* clean up anything we may have opened */
+fail:
+ if (streamFileGSP) close_streamfile(streamFileGSP);
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/halpst.c b/lib/vgmstream/src/meta/halpst.c
new file mode 100644
index 0000000000..31f3a1f04d
--- /dev/null
+++ b/lib/vgmstream/src/meta/halpst.c
@@ -0,0 +1,124 @@
+#include "meta.h"
+#include "../coding/coding.h"
+#include "../layout/layout.h"
+#include "../util.h"
+
+VGMSTREAM * init_vgmstream_halpst(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ int channel_count;
+ int loop_flag = 0;
+
+ int32_t samples_l,samples_r;
+ int32_t start_sample = 0;
+
+ size_t max_block;
+
+ /* check extension, case insensitive */
+ streamFile->get_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;
+
+ /* have I ever seen a mono .hps? */
+ if (channel_count!=2) goto fail;
+
+ /* yay for redundancy, gives us something to test */
+ samples_l = dsp_nibbles_to_samples(read_32bitBE(0x18,streamFile))+1;
+ 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);
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/idsp.c b/lib/vgmstream/src/meta/idsp.c
new file mode 100644
index 0000000000..3447fa9c60
--- /dev/null
+++ b/lib/vgmstream/src/meta/idsp.c
@@ -0,0 +1,162 @@
+#include "meta.h"
+#include "../util.h"
+
+/* IDSP (Chronicles of Narnia Wii) */
+VGMSTREAM * init_vgmstream_idsp(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+
+ int loop_flag;
+ int channel_count;
+
+ /* 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;
+
+
+ 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 */
+ start_offset = 0xD0;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
+ vgmstream->coding_type = coding_NGC_DSP;
+ vgmstream->num_samples = read_32bitBE(0x20,streamFile);
+ if (loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = read_32bitBE(0x20,streamFile);
+ }
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = read_32bitBE(0x0C,streamFile);
+ 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(0x3C+i*2,streamFile);
+ }
+ if (vgmstream->channels) {
+ for (i=0;i<16;i++) {
+ vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x9C+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;i<channel_count;i++) {
+ vgmstream->ch[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 (Soul Calibur Legends Wii) */
+VGMSTREAM * init_vgmstream_idsp2(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+
+ int loop_flag;
+ int channel_count;
+
+ /* 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);
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ /* fill in the vital statistics */
+ start_offset = 0x1C0;
+ 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));
+ }
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x10;
+ vgmstream->meta_type = meta_IDSP2;
+
+
+ if (vgmstream->coding_type == coding_NGC_DSP) {
+ int i;
+ for (i=0;i<16;i++) {
+ vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x118+i*2,streamFile);
+ }
+ if (vgmstream->channels) {
+ for (i=0;i<16;i++) {
+ vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x178+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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ish_isd.c b/lib/vgmstream/src/meta/ish_isd.c
new file mode 100644
index 0000000000..b612987049
--- /dev/null
+++ b/lib/vgmstream/src/meta/ish_isd.c
@@ -0,0 +1,89 @@
+#include "meta.h"
+#include "../util.h"
+
+/*
+ISH+ISD
+*/
+
+VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE *streamFile) {
+
+ VGMSTREAM * vgmstream = NULL;
+ STREAMFILE * streamFileISH = NULL;
+ char filename[260];
+ 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(0x20,streamFileISH);
+
+ /* 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 */
+ {
+ for (i=0;i<channel_count;i++) {
+ vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
+ 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(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/lib/vgmstream/src/meta/ivb.c b/lib/vgmstream/src/meta/ivb.c
new file mode 100644
index 0000000000..2fa303bc81
--- /dev/null
+++ b/lib/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[260];
+ 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;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=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/lib/vgmstream/src/meta/kraw.c b/lib/vgmstream/src/meta/kraw.c
new file mode 100644
index 0000000000..9a07709731
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/meta.h b/lib/vgmstream/src/meta/meta.h
new file mode 100644
index 0000000000..432ebdc9d4
--- /dev/null
+++ b/lib/vgmstream/src/meta/meta.h
@@ -0,0 +1,335 @@
+#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);
+
+VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile);
+
+VGMSTREAM * init_vgmstream_sfl(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_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_rwx(STREAMFILE * streamFile);
+
+VGMSTREAM * init_vgmstream_xwb(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_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(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_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_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_rsd4vag(STREAMFILE * streamFile);
+
+VGMSTREAM * init_vgmstream_rsd6vag(STREAMFILE * streamFile);
+
+VGMSTREAM * init_vgmstream_rsd6wadp(STREAMFILE * streamFile);
+
+VGMSTREAM * init_vgmstream_rsd6xadp(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_ps2_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_wav_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_ngc_ffcc_str(STREAMFILE *streamFile);
+
+#endif
diff --git a/lib/vgmstream/src/meta/msvp.c b/lib/vgmstream/src/meta/msvp.c
new file mode 100644
index 0000000000..0627dfab69
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/mus_acm.c b/lib/vgmstream/src/meta/mus_acm.c
new file mode 100644
index 0000000000..fddf354df6
--- /dev/null
+++ b/lib/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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#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<file_count;i++)
+ {
+ int fields_matched;
+ 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;
+
+ fields_matched = sscanf(line_buffer,"%259s %259s %259s",name,
+ loop_name_base_temp,loop_name_temp);
+
+
+ if (fields_matched < 1) goto fail;
+ if (fields_matched == 3 && loop_name_base_temp[0] != '@' && loop_name_temp[0] != '@')
+ {
+ int j;
+ memcpy(loop_name,loop_name_temp,sizeof(loop_name));
+ memcpy(loop_name_base,loop_name_base_temp,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 if (fields_matched >= 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;j<strlen(name);j++) name[j]=toupper(name[j]);
+ }
+
+ /* try looking in the common directory */
+ names[i][0] = '\0';
+ concatn(sizeof(names[0]),names[i],dir_name);
+ concatn(sizeof(names[0]),names[i],name);
+ concatn(sizeof(names[0]),names[i],".ACM");
+
+ if (!exists(names[i],streamFile)) {
+
+ /* We can't test for the directory until we have a file name
+ * to look for, so we do it here with the first file that seems to
+ * be in a subdirectory */
+ if (subdir_name[0]=='\0') {
+ if (find_directory_name(name_base, dir_name, sizeof(subdir_name), subdir_name, name, filename, streamFile))
+ goto fail;
+ }
+
+ names[i][0] = '\0';
+ concatn(sizeof(names[0]),names[i],dir_name);
+ concatn(sizeof(names[0]),names[i],subdir_name);
+ concatn(sizeof(names[0]),names[i],name_base);
+ concatn(sizeof(names[0]),names[i],name);
+ concatn(sizeof(names[0]),names[i],".ACM");
+
+ if (!exists(names[i],streamFile)) goto fail;
+ }
+
+ /*printf("%2d %s\n",i,names[i]);*/
+ }
+
+ if (loop_end_index != -1) {
+ /* find the file to loop back to */
+ char target_name[NAME_LENGTH];
+ target_name[0]='\0';
+ concatn(sizeof(target_name),target_name,dir_name);
+ concatn(sizeof(target_name),target_name,subdir_name);
+ concatn(sizeof(target_name),target_name,loop_name_base);
+ concatn(sizeof(target_name),target_name,loop_name);
+ concatn(sizeof(target_name),target_name,".ACM");
+ /*printf("looking for loop %s\n",target_name);*/
+
+ for (i=0;i<file_count;i++) {
+ if (!strcmp(target_name,names[i]))
+ {
+ loop_start_index = i;
+ break;
+ }
+ }
+
+ if (loop_start_index != -1) {
+ /*printf("loop from %d to %d\n",loop_end_index,loop_start_index);*/
+ /*if (loop_start_index < file_count-1) loop_start_index++;*/
+ loop_end_index++;
+ loop_flag = 1;
+ }
+
+ }
+ }
+
+ /* set up the struct to track the files */
+ data = calloc(1,sizeof(mus_acm_codec_data));
+ if (!data) goto fail;
+
+ data->files = calloc(file_count,sizeof(ACMStream *));
+ if (!data->files) {
+ free(data); data = NULL;
+ goto fail;
+ }
+
+ /* open each file... */
+ for (i=0;i<file_count;i++) {
+
+ /* gonna do this a little backwards, open and parse the file
+ before creating the vgmstream */
+
+ if (acm_open_decoder(&acm_stream,streamFile,names[i]) != ACM_OK) {
+ goto fail;
+ }
+
+ data->files[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;i<data->file_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/lib/vgmstream/src/meta/musc.c b/lib/vgmstream/src/meta/musc.c
new file mode 100644
index 0000000000..1abca4fff2
--- /dev/null
+++ b/lib/vgmstream/src/meta/musc.c
@@ -0,0 +1,72 @@
+#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[260];
+ off_t start_offset;
+ int musc_version;
+ int loop_flag = 0;
+ int channel_count = 2;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("musc",filename_extension(filename))) goto fail;
+
+ /* check header */
+ if (read_32bitBE(0x0,streamFile) != 0x4D555343) /* MUSC */
+ goto fail;
+
+ loop_flag = 0;
+ channel_count = 2;
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ musc_version=read_32bitLE(0x10,streamFile);
+ switch (musc_version) {
+ /* This handles the 'new' MUSC Version, which has only a 32 byte header
+ and doesn't provide any loop info!
+ Spyro - The Eternal Night, Spyro - A new Beginning, Ty - The Tsamanian Tiger */
+ case 0x20:
+ start_offset = 0x20;
+ 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;
+ }
+ break;
+ default:
+ goto fail;
+}
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitLE(0x06,streamFile);
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/musx.c b/lib/vgmstream/src/meta/musx.c
new file mode 100644
index 0000000000..01ed5cb244
--- /dev/null
+++ b/lib/vgmstream/src/meta/musx.c
@@ -0,0 +1,342 @@
+#include "meta.h"
+#include "../util.h"
+
+/* MUSX */
+/* Old MUSX formats, found in Spyro, Ty and other games */
+VGMSTREAM * init_vgmstream_musx_v004(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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(0x08,streamFile) != 0x04000000) /* "0x04000000" */
+ goto fail;
+
+ /* This is tricky, the header changes it's layout if the file is unlooped */
+ 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 */
+ musx_type=(read_32bitBE(0x10,streamFile));
+
+ switch (musx_type) {
+ 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_V004;
+ 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;
+ /* seems to not work for Spyro, maybe i find other games for testing
+ case 0x58425F5F: XB__
+ start_offset = read_32bitLE(0x28,streamFile);
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = 32000;
+ vgmstream->coding_type = coding_XBOX;
+ vgmstream->num_samples = (read_32bitLE(0x0C,streamFile))*64/36/channel_count;
+ vgmstream->layout_type = layout_none;
+ vgmstream->meta_type = meta_MUSX_V004;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = (read_32bitLE(0x890,streamFile))*64/36/channel_count;
+ vgmstream->loop_end_sample = (read_32bitLE(0x89C,streamFile))*64/36/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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
+
+
+
+/* MUSX */
+/* Old MUSX formats, found in Spyro, Ty and other games */
+VGMSTREAM * init_vgmstream_musx_v006(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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(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 */
+ musx_type=(read_32bitBE(0x10,streamFile));
+
+ switch (musx_type) {
+ 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;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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 */
+/* New MUSX formats, found in Quantum of Solace, The Mummy 3, possibly more */
+VGMSTREAM * init_vgmstream_musx_v010(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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(0x08,streamFile) != 0x0A000000) /* "0x0A000000" */
+ goto fail;
+
+ loop_flag = (read_32bitLE(0x34,streamFile)!=0x00000000);
+ channel_count = 2;
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ /* fill in the vital statistics */
+ musx_type=(read_32bitBE(0x10,streamFile));
+
+ 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;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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 */
+/* Old MUSX format, this one handles "Sphinx and the cursed Mummy", it's different from the other formats */
+VGMSTREAM * init_vgmstream_musx_v201(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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) /* "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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/naomi_spsd.c b/lib/vgmstream/src/meta/naomi_spsd.c
new file mode 100644
index 0000000000..f38e669c57
--- /dev/null
+++ b/lib/vgmstream/src/meta/naomi_spsd.c
@@ -0,0 +1,72 @@
+#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[260];
+ off_t start_offset;
+ 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 */
+ vgmstream->channels = channel_count;
+ start_offset = 0x40;
+ vgmstream->sample_rate = (uint16_t)read_16bitLE(0x2A,streamFile);
+ vgmstream->coding_type = coding_AICA;
+
+ vgmstream->num_samples = read_32bitLE(0x0C,streamFile);
+
+ if (loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
+ }
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/nds_sad.c b/lib/vgmstream/src/meta/nds_sad.c
new file mode 100644
index 0000000000..e60c0ac80e
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/nds_strm.c b/lib/vgmstream/src/meta/nds_strm.c
new file mode 100644
index 0000000000..39fa88fa43
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ if (vgmstream->layout_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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_adpdtk.c b/lib/vgmstream/src/meta/ngc_adpdtk.c
new file mode 100644
index 0000000000..a8f6fc871f
--- /dev/null
+++ b/lib/vgmstream/src/meta/ngc_adpdtk.c
@@ -0,0 +1,52 @@
+#include <math.h>
+#include "meta.h"
+#include "../util.h"
+
+VGMSTREAM * init_vgmstream_ngc_adpdtk(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ STREAMFILE * chstreamfile;
+ char filename[260];
+
+ size_t file_size;
+ int i;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("adp",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/lib/vgmstream/src/meta/ngc_bh2pcm.c b/lib/vgmstream/src/meta/ngc_bh2pcm.c
new file mode 100644
index 0000000000..0894827be7
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_caf.c b/lib/vgmstream/src/meta/ngc_caf.c
new file mode 100644
index 0000000000..f56b6db56b
--- /dev/null
+++ b/lib/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[260];
+
+ // 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(offset<file_length);
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(2,(loop_start!=-1)); /* always stereo */
+ if (!vgmstream) goto fail;
+
+ vgmstream->channels=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/lib/vgmstream/src/meta/ngc_dsp_std.c b/lib/vgmstream/src/meta/ngc_dsp_std.c
new file mode 100644
index 0000000000..83cca09737
--- /dev/null
+++ b/lib/vgmstream/src/meta/ngc_dsp_std.c
@@ -0,0 +1,1232 @@
+#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[260];
+
+ 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[260];
+
+ 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[260];
+
+ 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[260];
+
+ 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[260];
+
+ 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[260];
+
+ 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("sad",filename_extension(filename))) goto fail;
+
+ if (read_dsp_header(&ch0_header, 0x80, streamFile)) goto fail;
+ if (read_dsp_header(&ch1_header, 0xe0, streamFile)) goto fail;
+
+ /* check header magic */
+ if (read_32bitBE(0x0,streamFile) != 0x73616462) goto fail; /* "sadb" */
+
+ 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 (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_SADB;
+
+ /* 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;
+}
+
+/* AMTS - .amts files */
+VGMSTREAM * init_vgmstream_amts(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ 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;i<channel_count;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;
+}
+
+/* .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[260];
+ 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;i<channel_count;i++) {
+ off_t block_size;
+
+ block_size = read_32bitBE(check_offset,streamFile);
+
+ /* make sure block is actually big enough to hold the dsp header
+ and beginning of first frame */
+ if (block_size < 0x61+0x10) goto fail;
+ if (read_dsp_header(&header[i], check_offset+0x10, streamFile)) goto fail;
+
+ start_offset[i] = check_offset + 0x60+0x10;
+
+ /* check initial predictor/scale */
+ if (header[i].initial_ps != (uint8_t)read_8bit(check_offset+0x60+0x10,streamFile))
+ goto fail;
+
+ /* check type==0 and gain==0 */
+ if (header[i].format || header[i].gain)
+ goto fail;
+
+#if 0
+ /* difficult to use this with blocks, but might be worth doing */
+ if (header[i].loop_flag) {
+ off_t loop_off;
+ /* check loop predictor/scale */
+ loop_off = header[i].loop_start_offset/16*8;
+ if (header[i].loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile))
+ goto fail;
+ }
+#endif
+
+ check_offset += block_size;
+ }
+ } /* done looking at headers */
+
+ /* check for agreement (two channels only) */
+ if (
+ header[0].sample_count != header[1].sample_count ||
+ header[0].nibble_count != header[1].nibble_count ||
+ header[0].sample_rate != header[1].sample_rate ||
+ header[0].loop_flag != header[1].loop_flag ||
+ header[0].loop_start_offset != header[1].loop_start_offset ||
+ header[0].loop_end_offset != header[1].loop_end_offset
+ ) goto fail;
+
+
+ vgmstream = allocate_vgmstream(channel_count,header[0].loop_flag);
+ if (!vgmstream) goto fail;
+
+ /* fill in the vital statistics */
+ vgmstream->num_samples = header[0].sample_count;
+ 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;j<channel_count;j++) {
+ for (i=0;i<16;i++) {
+ vgmstream->ch[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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
+
+#include "meta.h"
+#include "../util.h"
+
+
+/* SWD (found in Conflict - Desert Storm 1 & 2 */
+VGMSTREAM * init_vgmstream_ngc_swd(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ 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;
+
+ /* 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_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 Star Wars Complete Collection for Wii */
+VGMSTREAM * init_vgmstream_wii_idsp(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ 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))) 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;
+}
+
diff --git a/lib/vgmstream/src/meta/ngc_ffcc_str.c b/lib/vgmstream/src/meta/ngc_ffcc_str.c
new file mode 100644
index 0000000000..bcc18af4ed
--- /dev/null
+++ b/lib/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[260];
+ 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;c<channel_count;c++)
+ {
+ int i;
+ for (i=0;i<16;i++) {
+ vgmstream->ch[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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_iadp.c b/lib/vgmstream/src/meta/ngc_iadp.c
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/lib/vgmstream/src/meta/ngc_iadp.c
diff --git a/lib/vgmstream/src/meta/ngc_pdt.c b/lib/vgmstream/src/meta/ngc_pdt.c
new file mode 100644
index 0000000000..56e7029228
--- /dev/null
+++ b/lib/vgmstream/src/meta/ngc_pdt.c
@@ -0,0 +1,79 @@
+#include "meta.h"
+#include "../util.h"
+
+/* PDT - Custom Generated File (Mario Party) */
+VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+ int loop_flag;
+ int channel_count;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("pdt",filename_extension(filename))) goto fail;
+
+#if 0
+ /* check header */
+ if (read_32bitBE(0x00,streamFile) != 0x00000000) /* 0x0 */
+ goto fail;
+#endif
+
+ loop_flag = (read_32bitBE(0x0C,streamFile)!=2); /* not sure, but it seems unlooped = 2 */
+ 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(0x04,streamFile);
+ vgmstream->coding_type = coding_NGC_DSP;
+ vgmstream->num_samples = read_32bitBE(0x08,streamFile)*14/8/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile)*14/8/channel_count;
+ vgmstream->loop_end_sample = read_32bitBE(0x08,streamFile)*14/8/channel_count;
+ }
+
+ /* dealing with no interleave, 'cause the interleave
+ for 2 channels is larger than the sample count/2 */
+ 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(0x20+i*2,streamFile);
+ }
+ if (vgmstream->channels == 2) {
+ for (i=0;i<16;i++) {
+ vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x40+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;i<channel_count;i++) {
+ vgmstream->ch[i].streamfile = file;
+
+ vgmstream->ch[i].channel_start_offset=
+ vgmstream->ch[i].offset=(get_streamfile_size(streamFile)+start_offset)/2*i;
+
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/ngc_ssm.c b/lib/vgmstream/src/meta/ngc_ssm.c
new file mode 100644
index 0000000000..7ea40369cd
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_tydsp.c b/lib/vgmstream/src/meta/ngc_tydsp.c
new file mode 100644
index 0000000000..bfce69493a
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_waa_wac_wad_wam.c b/lib/vgmstream/src/meta/ngc_waa_wac_wad_wam.c
new file mode 100644
index 0000000000..8738f5fb89
--- /dev/null
+++ b/lib/vgmstream/src/meta/ngc_waa_wac_wad_wam.c
@@ -0,0 +1,100 @@
+#include "meta.h"
+#include "../util.h"
+
+/* WAC - WAD - WAM (Beyond Good & Evil GC) */
+VGMSTREAM * init_vgmstream_waa_wac_wad_wam(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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("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" */
+ read_16bitBE(0x14,streamFile) != (int16_t)0xFEFF) /* "FEFF" */
+ goto fail;
+
+ loop_flag = 1;
+ channel_count = (uint16_t)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 = 0x5C;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitLE(0x18,streamFile);
+ 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;
+ }
+ vgmstream->layout_type = layout_none;
+ vgmstream->meta_type = meta_WAA_WAC_WAD_WAM;
+
+ /* Retrieveing the coef tables and the start of the second channel*/
+ coef1_start = 0x2E;
+ coef2_start = (read_32bitLE(0x2A,streamFile)/2)+0x5C;
+ second_channel_start = coef2_start+0x2E;
+
+ {
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ngc_ymf.c b/lib/vgmstream/src/meta/ngc_ymf.c
new file mode 100644
index 0000000000..9ca6a29443
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/nwa.c b/lib/vgmstream/src/meta/nwa.c
new file mode 100644
index 0000000000..868bef43d7
--- /dev/null
+++ b/lib/vgmstream/src/meta/nwa.c
@@ -0,0 +1,358 @@
+#include "meta.h"
+#include "../util.h"
+#include "../coding/nwa_decoder.h"
+#include <string.h>
+#include <ctype.h>
+
+#ifdef WIN32
+#define DIRSEP '\\'
+#else
+#define DIRSEP '/'
+#endif
+
+/* NWA - Visual Art's streams */
+
+VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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<file_size; offset++) {
+ off_t suboffset;
+ /* Go for an n*m search 'cause it's easier than building an
+ * FSA for the search string. Just wanted to make the point that
+ * I'm not ignorant, just lazy. */
+ for (suboffset = offset;
+ suboffset<file_size &&
+ suboffset-offset<length &&
+ read_8bit(suboffset,inistreamfile)==
+ namebase[suboffset-offset];
+ suboffset++) {}
+
+ if (suboffset-offset==length &&
+ read_8bit(suboffset,inistreamfile)==0x09) { /* tab */
+ found=1;
+ found_off = suboffset+1;
+ }
+ }
+
+ if (found) {
+ char loopstring[9]={0};
+
+ if (read_streamfile((uint8_t*)loopstring,found_off,8,
+ inistreamfile)==8)
+ {
+ loop_start_sample = atol(loopstring);
+ if (loop_start_sample > 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 && offset<file_size; offset++) {
+ off_t suboffset;
+ uint8_t buf[10];
+
+ if (read_8bit(offset,inistreamfile)!='#') continue;
+ if (read_streamfile(buf,offset+1,10,inistreamfile)!=10) break;
+ if (memcmp("DSTRACK = ",buf,10)) continue;
+ if (read_8bit(offset+44,inistreamfile)!='\"') continue;
+
+ for (suboffset = offset+45;
+ suboffset<file_size &&
+ suboffset-offset-45<length &&
+ tolower(read_8bit(suboffset,inistreamfile))==
+ tolower(namebase[suboffset-offset-45]);
+ suboffset++) {}
+
+ if (suboffset-offset-45==length &&
+ read_8bit(suboffset,inistreamfile)=='\"') { /* tab */
+ found=1;
+ found_off = offset+22; /* loop end */
+ }
+ }
+
+ if (found) {
+ char loopstring[9]={0};
+ int start_ok = 0, end_ok = 0;
+ int32_t total_samples =
+ read_32bitLE(0x1c,streamFile)/channel_count;
+
+ if (read_streamfile((uint8_t*)loopstring,found_off,8,
+ inistreamfile)==8)
+ {
+ if (!memcmp("99999999",loopstring,8))
+ {
+ loop_end_sample = total_samples;
+ }
+ else
+ {
+ loop_end_sample = atol(loopstring);
+ }
+ end_ok = 1;
+ }
+ if (read_streamfile((uint8_t*)loopstring,found_off+11,8,
+ inistreamfile)==8)
+ {
+ if (!memcmp("99999999",loopstring,8))
+ {
+ /* not ok to start at last sample,
+ * don't set start_ok flag */
+ }
+ else if (!memcmp("00000000",loopstring,8))
+ {
+ /* loops from the start aren't really loops */
+ }
+ else
+ {
+ loop_start_sample = atol(loopstring);
+ start_ok = 1;
+ }
+ }
+
+ if (start_ok && end_ok) loop_flag = 1;
+ } /* if found file name in INI */
+
+ close_streamfile(inistreamfile);
+ } /* if opened INI ok */
+ } /* INI block */
+
+ /* 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->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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ogg_vorbis_file.c b/lib/vgmstream/src/meta/ogg_vorbis_file.c
new file mode 100644
index 0000000000..2aa08217a6
--- /dev/null
+++ b/lib/vgmstream/src/meta/ogg_vorbis_file.c
@@ -0,0 +1,292 @@
+#include "../vgmstream.h"
+
+#ifdef VGM_USE_VORBIS
+
+#include <stdio.h>
+#include <string.h>
+#include "meta.h"
+#include "../util.h"
+#include <vorbis/vorbisfile.h>
+
+
+#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, 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, 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;i<num_crypt;i++)
+ ((uint8_t*)ptr)[i] ^= 0xff;
+ }
+
+ ov_streamfile->offset += 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;
+ break;
+ default:
+ return -1;
+ break;
+ }
+
+ new_offset = base_offset + offset;
+ if (new_offset < 0 || new_offset > ov_streamfile->size) {
+ 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) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ ov_callbacks callbacks;
+ 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 = 0;
+ int32_t loop_start = 0;
+ int loop_length_found = 0;
+ int32_t loop_length = 0;
+ int loop_end_found = 0;
+ int32_t loop_end = 0;
+
+ int um3_ogg = 0;
+
+ /* 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 goto fail;
+ }
+
+ /* not all um3-ogg are crypted */
+ if (um3_ogg && read_32bitBE(0x0,streamFile)==0x4f676753) um3_ogg = 0;
+
+ if (um3_ogg)
+ callbacks.read_func = read_func_um3;
+ else
+ callbacks.read_func = read_func;
+ callbacks.seek_func = seek_func;
+ callbacks.close_func = close_func;
+ callbacks.tell_func = tell_func;
+
+ temp_streamfile.streamfile = streamFile;
+ temp_streamfile.offset = 0;
+ temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile);
+
+ /* 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)) 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);
+
+ /* open the ogg vorbis file for real */
+ if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL,
+ 0, callbacks)) 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;i<comment->comments;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],"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],"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 = layout_ogg_vorbis;
+ if (um3_ogg)
+ vgmstream->meta_type = meta_um3_ogg;
+ else
+ vgmstream->meta_type = meta_ogg_vorbis;
+
+ 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/lib/vgmstream/src/meta/pcm.c b/lib/vgmstream/src/meta/pcm.c
new file mode 100644
index 0000000000..1092aa2a33
--- /dev/null
+++ b/lib/vgmstream/src/meta/pcm.c
@@ -0,0 +1,115 @@
+#include "meta.h"
+#include "../util.h"
+
+/* PCM (from Ephemeral Fantasia) */
+VGMSTREAM * init_vgmstream_pcm(STREAMFILE *streamFile) {
+
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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(0x0C,streamFile) ==0x0AA00AA0) {
+
+ 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 = 44100;
+ 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)*2;
+ vgmstream->loop_end_sample = read_32bitBE(0x06,streamFile)*2;
+ }
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x2;
+ vgmstream->meta_type = meta_PCM;
+
+ } else if (read_32bitBE(0x410,streamFile) ==0x9CDB0740) {
+
+ 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 = 22050;
+ vgmstream->coding_type = coding_PCM16LE;
+ vgmstream->num_samples = read_32bitLE(0x4,streamFile);
+
+ if(loop_flag == 1) {
+ 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;
+ } else if ((read_32bitBE(0x0,streamFile) ==0x786D6402) ||
+ (read_32bitBE(0x0,streamFile) ==0x786D6401)) {
+ loop_flag = 0;
+ channel_count = read_8bit(0x03,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 = (int32_t)(read_16bitLE(0x4,streamFile) & 0x0000ffff);
+ vgmstream->coding_type = coding_PCM8_int;
+ vgmstream->num_samples = read_32bitLE(0x6,streamFile);
+
+ if(loop_flag == 1) {
+ 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 = 0x8;
+ vgmstream->meta_type = meta_PCM;
+ } 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/pos.c b/lib/vgmstream/src/meta/pos.c
new file mode 100644
index 0000000000..aac9291bff
--- /dev/null
+++ b/lib/vgmstream/src/meta/pos.c
@@ -0,0 +1,66 @@
+#include <ctype.h>
+#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[260];
+ 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/lib/vgmstream/src/meta/ps2_ads.c b/lib/vgmstream/src/meta/ps2_ads.c
new file mode 100644
index 0000000000..b840017d5c
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_ads.c
@@ -0,0 +1,141 @@
+#include "meta.h"
+#include "../util.h"
+
+/* Sony .ADS with SShd & SSbd Headers */
+
+VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ int loop_flag=0;
+ int channel_count;
+ off_t start_offset;
+
+ uint8_t testBuffer[0x10];
+ off_t readOffset = 0;
+ off_t loopEnd = 0;
+
+ int i;
+
+ /* check extension, case insensitive */
+ streamFile->get_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 */
+ if (get_streamfile_size(streamFile)<(size_t)(read_32bitLE(0x24,streamFile) + 0x28))
+ goto fail;
+
+ /* check loop */
+ loop_flag = (read_32bitLE(0x1C,streamFile)!=0xFFFFFFFF);
+
+ 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 = ((read_32bitLE(0x24,streamFile)-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 = read_32bitLE(0x24,streamFile)/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;
+
+ // Hack for files with start_offset = 0x800
+ if(get_streamfile_size(streamFile)-read_32bitLE(0x24,streamFile)>=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;
+ }
+ }
+ }
+
+ /* 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_ass.c b/lib/vgmstream/src/meta/ps2_ass.c
new file mode 100644
index 0000000000..eba5375620
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_aus.c b/lib/vgmstream/src/meta/ps2_aus.c
new file mode 100644
index 0000000000..994b31af14
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_bg00.c b/lib/vgmstream/src/meta/ps2_bg00.c
new file mode 100644
index 0000000000..273c08fe39
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_bmdx.c b/lib/vgmstream/src/meta/ps2_bmdx.c
new file mode 100644
index 0000000000..34d08102e6
--- /dev/null
+++ b/lib/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[260];
+ 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;c<channel_count;c++) {
+ vgmstream->ch[c].bmdx_xor = xor;
+ vgmstream->ch[c].bmdx_add = add;
+ }
+ }
+
+ /* open the file for reading by each channel */
+ {
+ for (i=0;i<channel_count;i++) {
+ if (!vgmstream->ch[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/lib/vgmstream/src/meta/ps2_ccc.c b/lib/vgmstream/src/meta/ps2_ccc.c
new file mode 100644
index 0000000000..c665b48a54
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_dxh.c b/lib/vgmstream/src/meta/ps2_dxh.c
new file mode 100644
index 0000000000..2b1d1411aa
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_enth.c b/lib/vgmstream/src/meta/ps2_enth.c
new file mode 100644
index 0000000000..fa495b79e5
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_exst.c b/lib/vgmstream/src/meta/ps2_exst.c
new file mode 100644
index 0000000000..5451262255
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_filp.c b/lib/vgmstream/src/meta/ps2_filp.c
new file mode 100644
index 0000000000..372d0b90b8
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_gbts.c b/lib/vgmstream/src/meta/ps2_gbts.c
new file mode 100644
index 0000000000..858be05fb5
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_hgc1.c b/lib/vgmstream/src/meta/ps2_hgc1.c
new file mode 100644
index 0000000000..081a2f15e9
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_ikm.c b/lib/vgmstream/src/meta/ps2_ikm.c
new file mode 100644
index 0000000000..d644174830
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_ikm.c
@@ -0,0 +1,65 @@
+#include "meta.h"
+#include "../util.h"
+
+/* IKM (found in Zwei!) */
+VGMSTREAM * init_vgmstream_ikm(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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" */
+ goto fail;
+ if (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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_ild.c b/lib/vgmstream/src/meta/ps2_ild.c
new file mode 100644
index 0000000000..5649444b59
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_int.c b/lib/vgmstream/src/meta/ps2_int.c
new file mode 100644
index 0000000000..5debb2a20c
--- /dev/null
+++ b/lib/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[260];
+ 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;i<vgmstream->channels;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[260];
+ 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;i<vgmstream->channels;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/lib/vgmstream/src/meta/ps2_joe.c b/lib/vgmstream/src/meta/ps2_joe.c
new file mode 100644
index 0000000000..1faf055be3
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_joe.c
@@ -0,0 +1,94 @@
+#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[260];
+ 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("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;
+
+ /* fill in the vital statistics */
+ start_offset = 0x4020;
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = read_32bitLE(0x0,streamFile);
+ vgmstream->coding_type = coding_PSX;
+ vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)*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-0x20)*28/16/channel_count;
+ vgmstream->loop_end_sample = (loopEnd-start_offset+0x20)*28/16/channel_count;
+ }
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x10;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_kces.c b/lib/vgmstream/src/meta/ps2_kces.c
new file mode 100644
index 0000000000..0d803939c8
--- /dev/null
+++ b/lib/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[260];
+ 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 = 0; /* (read_32bitLE(0x08,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 = 0;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_leg.c b/lib/vgmstream/src/meta/ps2_leg.c
new file mode 100644
index 0000000000..8fa85b9c94
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_mib.c b/lib/vgmstream/src/meta/ps2_mib.c
new file mode 100644
index 0000000000..375488a9e9
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_mib.c
@@ -0,0 +1,170 @@
+#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[260];
+
+ uint8_t mibBuffer[0x10];
+ uint8_t testBuffer[0x10];
+
+ size_t fileLength;
+
+ off_t loopStart = 0;
+ off_t loopEnd = 0;
+ off_t interleave = 0;
+ off_t readOffset = 0;
+
+ char filenameMIH[260];
+
+ uint8_t gotMIH=0;
+
+ int i, channel_count=1;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("mib",filename_extension(filename)) &&
+ strcasecmp("mi4",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);
+
+ do {
+ readOffset+=(off_t)read_streamfile(testBuffer,readOffset,0x10,streamFile);
+
+ if(!memcmp(testBuffer,mibBuffer,0x10)) {
+ if(interleave==0) interleave=readOffset-0x10;
+
+ // be sure to point to an interleave value
+ if(((readOffset-0x10)==channel_count*interleave)) {
+ channel_count++;
+ }
+ }
+
+ // Loop Start ...
+ if(testBuffer[0x01]==0x06) {
+ if(loopStart==0) loopStart = readOffset-0x10;
+ }
+
+ // Loop End ...
+ if(testBuffer[0x01]==0x03) {
+ if(loopEnd==0) loopEnd = readOffset-0x10;
+ }
+
+ } while (streamFile->get_offset(streamFile)<(int32_t)fileLength);
+
+ if(gotMIH)
+ channel_count=read_32bitLE(0x08,streamFileMIH);
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,((loopStart!=0) && (loopEnd!=0)));
+ if (!vgmstream) goto fail;
+
+ if(interleave==0) interleave=0x10;
+
+ /* fill in the vital statistics */
+ 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;
+
+ vgmstream->num_samples = (int32_t)(fileLength/16/channel_count*28);
+ }
+
+ if(loopStart!=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/(interleave*channel_count))*interleave)/16*14*(2/channel_count);
+ vgmstream->loop_start_sample += (loopStart%(interleave*channel_count))/16*14*(2/channel_count);
+ vgmstream->loop_end_sample = ((loopEnd/(interleave*channel_count))*interleave)/16*28*(2/channel_count);
+ vgmstream->loop_end_sample += (loopEnd%(interleave*channel_count))/16*14*(2/channel_count);
+ }
+ }
+
+ vgmstream->coding_type = coding_PSX;
+ vgmstream->layout_type = layout_interleave;
+
+ 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;i<channel_count;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 (streamFileMIH) close_streamfile(streamFileMIH);
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/ps2_mic.c b/lib/vgmstream/src/meta/ps2_mic.c
new file mode 100644
index 0000000000..89a615d200
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_mihb.c b/lib/vgmstream/src/meta/ps2_mihb.c
new file mode 100644
index 0000000000..687157f2f2
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_mihb.c
@@ -0,0 +1,66 @@
+#include "meta.h"
+#include "../util.h"
+
+/* MIHB (Merged MIH+MIB) */
+VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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*channel_count/32*28;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = (read_32bitLE(0x10,streamFile))*mib_blocks*channel_count/32*28;
+ }
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile);
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_npsf.c b/lib/vgmstream/src/meta/ps2_npsf.c
new file mode 100644
index 0000000000..69cc4e389e
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_npsf.c
@@ -0,0 +1,70 @@
+#include "meta.h"
+#include "../util.h"
+
+/* Sony .ADS with SShd & SSbd Headers */
+
+VGMSTREAM * init_vgmstream_ps2_npsf(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ 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->layout_type = layout_interleave;
+ vgmstream->meta_type = meta_PS2_NPSF;
+
+ start_offset = (off_t)read_32bitLE(0x10,streamFile);
+
+ /* open the file for reading by each channel */
+ {
+ for (i=0;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_p2bt.c b/lib/vgmstream/src/meta/ps2_p2bt.c
new file mode 100644
index 0000000000..ff34cd84e6
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_pnb.c b/lib/vgmstream/src/meta/ps2_pnb.c
new file mode 100644
index 0000000000..d0d1e7dcf7
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_psh.c b/lib/vgmstream/src/meta/ps2_psh.c
new file mode 100644
index 0000000000..bdc353dc24
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_psw.c b/lib/vgmstream/src/meta/ps2_psw.c
new file mode 100644
index 0000000000..5321b26772
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_rkv.c b/lib/vgmstream/src/meta/ps2_rkv.c
new file mode 100644
index 0000000000..71ee6420ee
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_rkv.c
@@ -0,0 +1,64 @@
+#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[260];
+ off_t start_offset;
+ 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;
+
+ /* check header */
+ if (read_32bitBE(0x00,streamFile) != 0x00000000) /* "\0000" */
+ goto fail;
+
+ 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(0x0C,streamFile);
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x10,streamFile)*28/16/channel_count;
+ vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile);
+ }
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_rnd.c b/lib/vgmstream/src/meta/ps2_rnd.c
new file mode 100644
index 0000000000..fe397344ca
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_rstm.c b/lib/vgmstream/src/meta/ps2_rstm.c
new file mode 100644
index 0000000000..d903b38eaa
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_rws.c b/lib/vgmstream/src/meta/ps2_rws.c
new file mode 100644
index 0000000000..4ca588f015
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_rws.c
@@ -0,0 +1,89 @@
+#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[260];
+ 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:
+ 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;
+ }
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_rxw.c b/lib/vgmstream/src/meta/ps2_rxw.c
new file mode 100644
index 0000000000..ac48b5aaf4
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_seg.c b/lib/vgmstream/src/meta/ps2_seg.c
new file mode 100644
index 0000000000..749892e3f1
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_seg.c
@@ -0,0 +1,71 @@
+#include "meta.h"
+#include "../util.h"
+
+/* SEG (found in Eragon) */
+VGMSTREAM * init_vgmstream_ps2_seg(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+ int loop_flag;
+ int channel_count;
+
+ /* 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" */
+ read_32bitBE(0x04,streamFile) != 0x70733200) /* "ps2\0" */
+ 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_PSX;
+ vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)-start_offset)*28/16/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile);
+ }
+
+ if (channel_count == 1) {
+ vgmstream->layout_type = layout_none;
+ } else if (channel_count == 2) {
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x2000;
+ }
+
+ vgmstream->meta_type = meta_PS2_SEG;
+
+ /* 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+
+ 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/lib/vgmstream/src/meta/ps2_sfs.c b/lib/vgmstream/src/meta/ps2_sfs.c
new file mode 100644
index 0000000000..ce966af404
--- /dev/null
+++ b/lib/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[260];
+ 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)*2)*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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_sl3.c b/lib/vgmstream/src/meta/ps2_sl3.c
new file mode 100644
index 0000000000..0f774b9dc5
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_str.c b/lib/vgmstream/src/meta/ps2_str.c
new file mode 100644
index 0000000000..a00228e2e8
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_str.c
@@ -0,0 +1,92 @@
+#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[260];
+
+ 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)==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;i<channel_count;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+=(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/lib/vgmstream/src/meta/ps2_svag.c b/lib/vgmstream/src/meta/ps2_svag.c
new file mode 100644
index 0000000000..c9ddd30f43
--- /dev/null
+++ b/lib/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[260];
+
+ 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<channel_count;i++) {
+ if (channel_count > 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/lib/vgmstream/src/meta/ps2_tec.c b/lib/vgmstream/src/meta/ps2_tec.c
new file mode 100644
index 0000000000..1287d1b0e3
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_tec.c
@@ -0,0 +1,61 @@
+#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[260];
+ off_t start_offset;
+ int loop_flag;
+ int channel_count;
+
+ /* 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;
+ }
+
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x4000;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_vag.c b/lib/vgmstream/src/meta/ps2_vag.c
new file mode 100644
index 0000000000..a6399db1d1
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_vag.c
@@ -0,0 +1,200 @@
+#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[260];
+
+ // 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 '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 '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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_vas.c b/lib/vgmstream/src/meta/ps2_vas.c
new file mode 100644
index 0000000000..aa25d2d12b
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ps2_vpk.c b/lib/vgmstream/src/meta/ps2_vpk.c
new file mode 100644
index 0000000000..7def9785c1
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/ps2_xa2.c b/lib/vgmstream/src/meta/ps2_xa2.c
new file mode 100644
index 0000000000..9b902dc3e7
--- /dev/null
+++ b/lib/vgmstream/src/meta/ps2_xa2.c
@@ -0,0 +1,60 @@
+#include "meta.h"
+#include "../util.h"
+
+/* XA2 (XG3 Extreme-G Racing) */
+VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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 = (read_32bitLE(0x10,streamFile)!=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 = read_32bitLE(0x0C,streamFile);
+ if (loop_flag) {
+ vgmstream->loop_start_sample = vgmstream->num_samples-read_32bitLE(0x08,streamFile);
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
diff --git a/lib/vgmstream/src/meta/ps2_xa30.c b/lib/vgmstream/src/meta/ps2_xa30.c
new file mode 100644
index 0000000000..21339e6191
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/psx_cdxa.c b/lib/vgmstream/src/meta/psx_cdxa.c
new file mode 100644
index 0000000000..24b274f6ae
--- /dev/null
+++ b/lib/vgmstream/src/meta/psx_cdxa.c
@@ -0,0 +1,117 @@
+#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[260];
+
+ int channel_count;
+ 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)))
+ goto fail;
+
+ /* First init to have the correct info of the channel */
+ start_offset=init_xa_channel(0,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 = 0;
+
+ 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->coding_type = coding_XA;
+ vgmstream->num_samples = (int32_t)((((get_streamfile_size(streamFile) - 0x3C)/2352)*0x1F80)/(2*channel_count));
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+
+begin:
+
+ // 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);
+ if (!((currentChannel==channel) && (subAudio==0x64))) {
+ block_offset+=2352;
+ goto begin;
+ }
+ return block_offset;
+}
diff --git a/lib/vgmstream/src/meta/psx_fag.c b/lib/vgmstream/src/meta/psx_fag.c
new file mode 100644
index 0000000000..21be33cbe6
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/psx_gms.c b/lib/vgmstream/src/meta/psx_gms.c
new file mode 100644
index 0000000000..fdbf07cdb4
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;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=
+ (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/lib/vgmstream/src/meta/raw.c b/lib/vgmstream/src/meta/raw.c
new file mode 100644
index 0000000000..4a002d7920
--- /dev/null
+++ b/lib/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[260];
+ 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/lib/vgmstream/src/meta/riff.c b/lib/vgmstream/src/meta/riff.c
new file mode 100644
index 0000000000..32697c5fc9
--- /dev/null
+++ b/lib/vgmstream/src/meta/riff.c
@@ -0,0 +1,342 @@
+#include "meta.h"
+#include "../layout/layout.h"
+#include "../util.h"
+
+/* Resource Interchange File Format */
+/* only the bare minimum needed to read PCM wavs */
+
+/* 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;
+ }
+}
+
+VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ off_t file_size = -1;
+ int channel_count = 0;
+ int sample_count = 0;
+ int sample_rate = 0;
+ int coding_type = -1;
+ off_t start_offset = -1;
+ int interleave = -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;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("wav",filename_extension(filename)) &&
+ strcasecmp("lwav",filename_extension(filename)))
+ {
+ if (strcasecmp("mwv",filename_extension(filename)))
+ goto fail;
+ else
+ mwv = 1;
+ }
+
+ /* 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;
+
+ sample_rate = read_32bitLE(current_chunk+0x0c,streamFile);
+ channel_count = read_16bitLE(current_chunk+0x0a,streamFile);
+
+ switch (read_16bitLE(current_chunk+0x8,streamFile)) {
+ case 1: /* PCM */
+ switch (read_16bitLE(current_chunk+0x16,streamFile)) {
+ case 16:
+ coding_type = coding_PCM16LE;
+ interleave = 2;
+ break;
+ case 8:
+ coding_type = coding_PCM8_U_int;
+ interleave = 1;
+ break;
+ default:
+ goto fail;
+ }
+ break;
+ case 0x555: /* Level-5 0x555 ADPCM */
+ if (!mwv) goto fail;
+ coding_type = coding_L5_555;
+ interleave = 0x12;
+ break;
+ default:
+ 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;
+ default:
+ /* ignorance is bliss */
+ break;
+ }
+
+ current_chunk += 8+chunk_size;
+ }
+ }
+
+ if (!FormatChunkFound || !DataChunkFound) goto fail;
+
+ switch (coding_type) {
+ case coding_PCM16LE:
+ sample_count = data_size/2/channel_count;
+ break;
+ case coding_PCM8_U_int:
+ sample_count = data_size/channel_count;
+ break;
+ case coding_L5_555:
+ sample_count = data_size/0x12/channel_count*32;
+ break;
+ }
+
+ /* 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 && coding_type != coding_PCM8_U_int)
+ vgmstream->layout_type = layout_interleave;
+ else
+ vgmstream->layout_type = layout_none;
+ vgmstream->interleave_block_size = interleave;
+
+ if (loop_flag) {
+ if (loop_start_ms >= 0)
+ {
+ vgmstream->loop_start_sample =
+ (long long)loop_start_ms*sample_rate/1000;
+ vgmstream->loop_end_sample =
+ (long long)loop_end_ms*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 (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 < 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;
+ }
+
+ /* 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/rs03.c b/lib/vgmstream/src/meta/rs03.c
new file mode 100644
index 0000000000..82f57c8131
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/rsd.c b/lib/vgmstream/src/meta/rsd.c
new file mode 100644
index 0000000000..f81a6b557e
--- /dev/null
+++ b/lib/vgmstream/src/meta/rsd.c
@@ -0,0 +1,705 @@
+#include "meta.h"
+#include "../util.h"
+
+/* RSD */
+/* RSD2VAG */
+VGMSTREAM * init_vgmstream_rsd2vag(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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_interleave;
+ vgmstream->interleave_block_size = 0x24;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
+
+
+/* RSD3PCM - Little Endian */
+VGMSTREAM * init_vgmstream_rsd3pcm(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
+
+
+
+/* RSD6VAG */
+VGMSTREAM * init_vgmstream_rsd6vag(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
+
+
+
+/* RSD6XADP */
+VGMSTREAM * init_vgmstream_rsd6xadp(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ 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_interleave;
+ vgmstream->interleave_block_size = 0x24;
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
diff --git a/lib/vgmstream/src/meta/rsf.c b/lib/vgmstream/src/meta/rsf.c
new file mode 100644
index 0000000000..9ae8325e11
--- /dev/null
+++ b/lib/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[260];
+
+ 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/lib/vgmstream/src/meta/rwsd.c b/lib/vgmstream/src/meta/rwsd.c
new file mode 100644
index 0000000000..52994c5551
--- /dev/null
+++ b/lib/vgmstream/src/meta/rwsd.c
@@ -0,0 +1,245 @@
+#include "meta.h"
+#include "../coding/coding.h"
+#include "../util.h"
+
+static off_t read_rwav(off_t offset, int *version, off_t *start_offset, off_t *info_chunkp, STREAMFILE *streamFile)
+{
+ off_t info_chunk;
+ off_t data_chunk;
+ off_t wave_offset;
+
+ if ((uint32_t)read_32bitBE(offset,streamFile)!=0x52574156) /* "RWAV" */
+ goto fail;
+ if ((uint32_t)read_32bitBE(offset+4,streamFile)!=0xFEFF0102) /* version 2 */
+ goto fail;
+
+ info_chunk = offset+read_32bitBE(offset+0x10,streamFile);
+ if ((uint32_t)read_32bitBE(info_chunk,streamFile)!=0x494e464f) /* "INFO" */
+ goto fail;
+ data_chunk = offset+read_32bitBE(offset+0x18,streamFile);
+ if ((uint32_t)read_32bitBE(data_chunk,streamFile)!=0x44415441) /* "DATA" */
+ goto fail;
+
+ *start_offset = data_chunk + 8;
+ *info_chunkp = info_chunk + 8;
+ *version = 2;
+ wave_offset = info_chunk - 8;
+
+ return wave_offset;
+fail:
+ return -1;
+}
+
+static off_t read_rwar(off_t offset, int *version, off_t *start_offset, off_t *info_chunk, STREAMFILE *streamFile)
+{
+ off_t wave_offset;
+ if ((uint32_t)read_32bitBE(offset,streamFile)!=0x52574152) /* "RWAR" */
+ goto fail;
+ if ((uint32_t)read_32bitBE(offset+4,streamFile)!=0xFEFF0100) /* version 0 */
+ goto fail;
+
+ wave_offset = read_rwav(offset+0x60,version,start_offset,info_chunk,streamFile);
+ *version = 0;
+ return wave_offset;
+
+fail:
+ return -1;
+}
+
+/* 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[260];
+
+ coding_t coding_type;
+
+ off_t info_chunk;
+ off_t wave_offset;
+ size_t wave_length;
+ int codec_number;
+ int channel_count;
+ int loop_flag;
+ int rwar = 0;
+ int rwav = 0;
+ int version = -1;
+
+ off_t start_offset = 0;
+ size_t stream_size;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("rwsd",filename_extension(filename)))
+ {
+ if (strcasecmp("rwar",filename_extension(filename)))
+ {
+ if (strcasecmp("rwav",filename_extension(filename)))
+ {
+ goto fail;
+ }
+ else
+ {
+ rwav = 1;
+ }
+ }
+ else
+ {
+ rwar = 1;
+ }
+ }
+
+ /* check header */
+ if (rwar)
+ {
+ wave_offset = read_rwar(0,&version,&start_offset,&info_chunk,streamFile);
+ if (wave_offset < 0) goto fail;
+ }
+ else if (rwav)
+ {
+ wave_offset = read_rwav(0,&version,&start_offset,&info_chunk,streamFile);
+ if (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 */
+ wave_offset = read_32bitBE(0x18,streamFile);
+ if ((uint32_t)read_32bitBE(wave_offset,streamFile)!=0x57415645) /* "WAVE" */
+ goto fail;
+ /* get WAVE size, check */
+ wave_length = read_32bitBE(0x1c,streamFile);
+ if (read_32bitBE(wave_offset+4,streamFile)!=wave_length)
+ goto fail;
+
+ /* check wave count */
+ if (read_32bitBE(wave_offset+8,streamFile) != 1)
+ goto fail; /* only support 1 */
+
+ version = 2;
+
+ break;
+ case 0xFEFF0103:
+ wave_offset = read_rwar(0xe0,&version,&start_offset,&info_chunk,streamFile);
+ if (wave_offset < 0) goto fail;
+
+ rwar = 1;
+ break;
+ default:
+ goto fail;
+ }
+
+ }
+
+ /* get type details */
+ codec_number = read_8bit(wave_offset+0x10,streamFile);
+ loop_flag = read_8bit(wave_offset+0x11,streamFile);
+ channel_count = read_8bit(wave_offset+0x12,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 = dsp_nibbles_to_samples(read_32bitBE(wave_offset+0x1c,streamFile));
+ vgmstream->sample_rate = (uint16_t)read_16bitBE(wave_offset+0x14,streamFile);
+ /* channels and loop flag are set by allocate_vgmstream */
+ vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(wave_offset+0x18,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)
+ vgmstream->meta_type = meta_RWAV;
+ else
+ vgmstream->meta_type = meta_RWSD;
+
+ if (vgmstream->coding_type == coding_NGC_DSP) {
+ off_t coef_offset;
+ int i,j;
+
+ for (j=0;j<vgmstream->channels;j++) {
+ if (rwar || rwav)
+ {
+ /* 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 stream_size read far below just happens to
+ * hit on this properly for stereo. The second element is the
+ * offset of the coefficient table for the channel. */
+ coef_offset = info_chunk +
+ read_32bitBE(info_chunk +
+ read_32bitBE(info_chunk+
+ read_32bitBE(info_chunk+0x10,streamFile)+j*4,
+ streamFile) + 4, streamFile);
+ } else {
+ coef_offset=wave_offset+0x6c+j*0x30;
+ }
+ for (i=0;i<16;i++) {
+ vgmstream->ch[j].adpcm_coef[i]=read_16bitBE(coef_offset+i*2,streamFile);
+ }
+ }
+ }
+
+ if (rwar || rwav)
+ {
+ /* */
+ }
+ else
+ {
+ if (version == 2)
+ start_offset = read_32bitBE(8,streamFile);
+ }
+ stream_size = read_32bitBE(wave_offset+0x50,streamFile);
+
+ /* open the file for reading by each channel */
+ {
+ int i;
+ for (i=0;i<channel_count;i++) {
+ 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*stream_size;
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/rwx.c b/lib/vgmstream/src/meta/rwx.c
new file mode 100644
index 0000000000..ac00279504
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/sat_dvi.c b/lib/vgmstream/src/meta/sat_dvi.c
new file mode 100644
index 0000000000..8b763bed72
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/sat_sap.c b/lib/vgmstream/src/meta/sat_sap.c
new file mode 100644
index 0000000000..3d1f2ba29a
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/sdt.c b/lib/vgmstream/src/meta/sdt.c
new file mode 100644
index 0000000000..1959ef8a86
--- /dev/null
+++ b/lib/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[260];
+ 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 = 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/sfl.c b/lib/vgmstream/src/meta/sfl.c
new file mode 100644
index 0000000000..8e72b34157
--- /dev/null
+++ b/lib/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[260];
+
+ 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/lib/vgmstream/src/meta/sli.c b/lib/vgmstream/src/meta/sli.c
new file mode 100644
index 0000000000..d94499246f
--- /dev/null
+++ b/lib/vgmstream/src/meta/sli.c
@@ -0,0 +1,121 @@
+#include "../vgmstream.h"
+
+#ifdef VGM_USE_VORBIS
+
+#include <ctype.h>
+#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[260];
+ 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/lib/vgmstream/src/meta/spt_spd.c b/lib/vgmstream/src/meta/spt_spd.c
new file mode 100644
index 0000000000..7d5caa3cba
--- /dev/null
+++ b/lib/vgmstream/src/meta/spt_spd.c
@@ -0,0 +1,96 @@
+#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[260];
+ char filenameSPT[260];
+
+ int i;
+ int channel_count;
+ int loop_flag;
+
+ /* 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;
+
+ channel_count = read_32bitBE(0x00,streamFileSPT);
+ loop_flag = read_32bitBE(0x04,streamFileSPT);
+
+ /* 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);
+ vgmstream->num_samples=read_32bitBE(0x14,streamFileSPT)*14/16/channel_count;
+ vgmstream->coding_type = coding_NGC_DSP;
+
+ if(loop_flag) {
+ vgmstream->loop_start_sample = 0;
+ vgmstream->loop_end_sample = read_32bitBE(0x14,streamFileSPT)*14/16/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=0x4000; /* Unknown now, never seen 2ch files in psd+spt */
+ }
+
+
+
+ vgmstream->meta_type = meta_SPT_SPD;
+
+ /* open the file for reading */
+ {
+ for (i=0;i<channel_count;i++) {
+ /* Not sure, i'll put a fake value here for now */
+ vgmstream->ch[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/lib/vgmstream/src/meta/ss_stream.c b/lib/vgmstream/src/meta/ss_stream.c
new file mode 100644
index 0000000000..d6e0d6dede
--- /dev/null
+++ b/lib/vgmstream/src/meta/ss_stream.c
@@ -0,0 +1,61 @@
+#include "meta.h"
+#include "../util.h"
+
+/* SS_STREAM
+
+ SS_STREAM is format used by various UBI Soft Games
+
+ 2008-11-15 - Fastelbja : First version ...
+*/
+
+VGMSTREAM * init_vgmstream_ss_stream(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ int loop_flag=0;
+ int channel_count;
+ int i;
+
+ /* check extension, case insensitive */
+ streamFile->get_name(streamFile,filename,sizeof(filename));
+ if (strcasecmp("ss7",filename_extension(filename))) goto fail;
+
+ loop_flag = 0;
+ channel_count=read_8bit(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 = 44100;
+
+ 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) -0x44)* 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;i<channel_count;i++) {
+ vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
+ vgmstream->ch[i].offset = 0x44;
+ 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/lib/vgmstream/src/meta/str_asr.c b/lib/vgmstream/src/meta/str_asr.c
new file mode 100644
index 0000000000..bfaa20f181
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/str_snds.c b/lib/vgmstream/src/meta/str_snds.c
new file mode 100644
index 0000000000..f2dc585471
--- /dev/null
+++ b/lib/vgmstream/src/meta/str_snds.c
@@ -0,0 +1,134 @@
+#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[260];
+
+ 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 */
+ 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;
+ 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) {
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/svs.c b/lib/vgmstream/src/meta/svs.c
new file mode 100644
index 0000000000..4e8eddd708
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/thp.c b/lib/vgmstream/src/meta/thp.c
new file mode 100644
index 0000000000..298bae7168
--- /dev/null
+++ b/lib/vgmstream/src/meta/thp.c
@@ -0,0 +1,97 @@
+#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[260];
+ 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 */
+ 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;i<numComponents;i++) {
+ if(read_8bit(componentTypeOffset+i,streamFile)==1) {
+ channel_count=read_32bitBE(componentDataOffset,streamFile);
+
+ /* build the VGMSTREAM */
+ vgmstream = allocate_vgmstream(channel_count,loop_flag);
+ if (!vgmstream) goto fail;
+
+ vgmstream->channels=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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/vgs.c b/lib/vgmstream/src/meta/vgs.c
new file mode 100644
index 0000000000..3890780f46
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/vs.c b/lib/vgmstream/src/meta/vs.c
new file mode 100644
index 0000000000..b7abe1f86e
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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_offset<get_streamfile_size(streamFile));
+
+ vs_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/lib/vgmstream/src/meta/wii_mus.c b/lib/vgmstream/src/meta/wii_mus.c
new file mode 100644
index 0000000000..a6cdd979e5
--- /dev/null
+++ b/lib/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[260];
+
+ 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/lib/vgmstream/src/meta/wii_smp.c b/lib/vgmstream/src/meta/wii_smp.c
new file mode 100644
index 0000000000..adb7040be3
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/wii_sng.c b/lib/vgmstream/src/meta/wii_sng.c
new file mode 100644
index 0000000000..1ba6e13a85
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/wii_sts.c b/lib/vgmstream/src/meta/wii_sts.c
new file mode 100644
index 0000000000..c63aa96b8b
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/ws_aud.c b/lib/vgmstream/src/meta/ws_aud.c
new file mode 100644
index 0000000000..4020d09957
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xbox_ims.c b/lib/vgmstream/src/meta/xbox_ims.c
new file mode 100644
index 0000000000..782d32d5a6
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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_offset<get_streamfile_size(streamFile));
+
+ matx_block_update(0,vgmstream);
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/meta/xbox_stma.c b/lib/vgmstream/src/meta/xbox_stma.c
new file mode 100644
index 0000000000..ed995ec4b9
--- /dev/null
+++ b/lib/vgmstream/src/meta/xbox_stma.c
@@ -0,0 +1,64 @@
+#include "meta.h"
+#include "../util.h"
+
+/* STMA
+
+ STMA (found in Midnight Club 2)
+*/
+
+VGMSTREAM * init_vgmstream_xbox_stma(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ int loop_flag=0;
+ int channel_count;
+ int i;
+
+ /* check extension, case insensitive */
+ streamFile->get_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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xbox_wavm.c b/lib/vgmstream/src/meta/xbox_wavm.c
new file mode 100644
index 0000000000..2d2413b919
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
diff --git a/lib/vgmstream/src/meta/xbox_wvs.c b/lib/vgmstream/src/meta/xbox_wvs.c
new file mode 100644
index 0000000000..036fd466e9
--- /dev/null
+++ b/lib/vgmstream/src/meta/xbox_wvs.c
@@ -0,0 +1,67 @@
+#include "meta.h"
+#include "../util.h"
+
+/* WVS
+
+ WVS (found in Metal Arms - Glitch in the System)
+*/
+
+VGMSTREAM * init_vgmstream_xbox_wvs(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
diff --git a/lib/vgmstream/src/meta/xbox_xmu.c b/lib/vgmstream/src/meta/xbox_xmu.c
new file mode 100644
index 0000000000..983cf71a3a
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xbox_xvas.c b/lib/vgmstream/src/meta/xbox_xvas.c
new file mode 100644
index 0000000000..c0d76920a7
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xbox_xwav.c b/lib/vgmstream/src/meta/xbox_xwav.c
new file mode 100644
index 0000000000..3b446e1b93
--- /dev/null
+++ b/lib/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[260];
+
+ 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;i<channel_count;i++,j++) {
+ if((j&2) && (i!=0)) {
+ j=0;
+ start_offset+=36*2;
+ }
+
+ vgmstream->ch[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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xss.c b/lib/vgmstream/src/meta/xss.c
new file mode 100644
index 0000000000..8cfa351730
--- /dev/null
+++ b/lib/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[260];
+ 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/xwb.c b/lib/vgmstream/src/meta/xwb.c
new file mode 100644
index 0000000000..eaf1218ca1
--- /dev/null
+++ b/lib/vgmstream/src/meta/xwb.c
@@ -0,0 +1,103 @@
+#include "meta.h"
+#include "../util.h"
+/* XWB (found in King of Fighters 2003 (XBOX)) */
+VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+ int loop_flag = 0;
+ int channel_count;
+ int coding;
+ int coding_flag;
+ int num_samples;
+
+ /* 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 */
+ goto fail;
+#if 0
+ /* check if the file is been used as container */
+ if (read_32bitBE(0x2C,streamFile) != 0x01000000)
+ goto fail;
+#endif
+ /* if it's looped it should be 2, didn't see anything else... */
+ loop_flag = (uint8_t)(read_8bit(0x50,streamFile));
+
+ if (loop_flag == 2) {
+ loop_flag = 1;
+ } else if (loop_flag < 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 */
+ start_offset = read_32bitLE(0x20,streamFile);
+ vgmstream->channels = channel_count;
+ vgmstream->sample_rate = 44100; /* read_32bitLE(0x08,streamFile); */
+
+ coding_flag = (uint8_t)(read_8bit(0x52,streamFile));
+ switch (coding_flag) {
+ case 0:
+ coding = coding_PCM16LE;
+ vgmstream->layout_type = layout_interleave;
+ vgmstream->interleave_block_size = 0x2;
+ num_samples = read_32bitLE(0x5C,streamFile)/2/channel_count;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x60,streamFile)/2/channel_count;
+ vgmstream->loop_end_sample = read_32bitLE(0x5C,streamFile)/2/channel_count;
+ }
+ break;
+ case 1:
+ coding = coding_XBOX;
+ vgmstream->layout_type = layout_none;
+ num_samples = read_32bitLE(0x5C,streamFile)/36/channel_count*64;
+ if (loop_flag) {
+ vgmstream->loop_start_sample = read_32bitLE(0x60,streamFile)/36/channel_count*64;
+ vgmstream->loop_end_sample = read_32bitLE(0x5C,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;i<channel_count;i++) {
+ vgmstream->ch[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;
+}
diff --git a/lib/vgmstream/src/meta/ydsp.c b/lib/vgmstream/src/meta/ydsp.c
new file mode 100644
index 0000000000..007faa3048
--- /dev/null
+++ b/lib/vgmstream/src/meta/ydsp.c
@@ -0,0 +1,83 @@
+#include "meta.h"
+#include "../util.h"
+
+/* YDSP (from WWE Day of Reckoning) */
+VGMSTREAM * init_vgmstream_ydsp(STREAMFILE *streamFile) {
+ VGMSTREAM * vgmstream = NULL;
+ char filename[260];
+ off_t start_offset;
+
+ int loop_flag;
+ int channel_count;
+
+ /* 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)!=0);
+ channel_count = 2; /* (uint32_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->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;
+ }
+
+ vgmstream->meta_type = meta_YDSP;
+
+ /* 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;i<channel_count;i++) {
+ vgmstream->ch[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/lib/vgmstream/src/meta/zwdsp.c b/lib/vgmstream/src/meta/zwdsp.c
new file mode 100644
index 0000000000..8fd52636f7
--- /dev/null
+++ b/lib/vgmstream/src/meta/zwdsp.c
@@ -0,0 +1,88 @@
+#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[260];
+ off_t start_offset;
+
+ int loop_flag;
+ int channel_count;
+
+ /* 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;
+ }
+
+ channel_count = read_32bitBE(0x1C,streamFile);
+
+ /* 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;
+ }
+
+
+ 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);
+ }
+ }
+ }
+
+ /* 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+
+ ((get_streamfile_size(streamFile)-start_offset)/2)*i;
+
+ }
+ }
+
+ return vgmstream;
+
+ /* clean up anything we may have opened */
+fail:
+ if (vgmstream) close_vgmstream(vgmstream);
+ return NULL;
+}
diff --git a/lib/vgmstream/src/streamfile.c b/lib/vgmstream/src/streamfile.c
new file mode 100644
index 0000000000..6fc6fc54b2
--- /dev/null
+++ b/lib/vgmstream/src/streamfile.c
@@ -0,0 +1,276 @@
+#ifndef _MSC_VER
+#include <unistd.h>
+#endif
+#include "streamfile.h"
+#include "util.h"
+
+#ifdef _WIN32
+#define IS_VALID_STREAM(stream) (stream != NULL && (stream->_ptr != NULL))
+#else
+#define IS_VALID_STREAM(stream) (stream)
+#endif
+
+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) {
+ strcpy(buffer,streamfile->name);
+}
+
+#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 (IS_VALID_STREAM(streamFile->infile) && ((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;
+
+ strcpy(streamfile->name,filename);
+
+ 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<dst_length-1 && offset+i < file_length;i++)
+ {
+ char in_char = read_8bit(offset+i,infile);
+ /* check for end of line */
+ if (in_char == 0x0d &&
+ read_8bit(offset+i+1,infile) == 0x0a)
+ {
+ extra_bytes = 2;
+ if (line_done_ptr) *line_done_ptr = 1;
+ break;
+ }
+
+ dst[i]=in_char;
+ }
+
+ dst[i]='\0';
+
+ /* did we fill the buffer? */
+ if (i==dst_length) {
+ /* did the bytes we missed just happen to be the end of the line? */
+ if (read_8bit(offset+i,infile) == 0x0d &&
+ read_8bit(offset+i+1,infile) == 0x0a)
+ {
+ extra_bytes = 2;
+ /* if so be proud! */
+ if (line_done_ptr) *line_done_ptr = 1;
+ }
+ }
+
+ /* did we hit the file end? */
+ if (offset+i == file_length)
+ {
+ /* then we did in fact finish reading the last line */
+ if (line_done_ptr) *line_done_ptr = 1;
+ }
+
+ return i+extra_bytes;
+}
diff --git a/lib/vgmstream/src/streamfile.h b/lib/vgmstream/src/streamfile.h
new file mode 100644
index 0000000000..d9df519e99
--- /dev/null
+++ b/lib/vgmstream/src/streamfile.h
@@ -0,0 +1,142 @@
+/*
+* streamfile.h - definitions for buffered file reading with STREAMFILE
+*/
+
+#ifndef _STREAMFILE_H
+#define _STREAMFILE_H
+
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include "streamtypes.h"
+#include "util.h"
+
+#if defined(__MSVCRT__) || defined(_MSC_VER) || defined(XBMC)
+#define fseeko fseek
+#define ftello ftell
+#endif
+#if defined(__MSVCRT__) || defined(_MSC_VER)
+#include <io.h>
+#define dup _dup
+#ifdef fileno
+#undef fileno
+#endif
+#define fileno _fileno
+#define fdopen _fdopen
+#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/lib/vgmstream/src/streamtypes.h b/lib/vgmstream/src/streamtypes.h
new file mode 100644
index 0000000000..e87e4d393f
--- /dev/null
+++ b/lib/vgmstream/src/streamtypes.h
@@ -0,0 +1,20 @@
+/*
+ * streamtypes.h - widely used type definitions
+ */
+
+
+#ifndef _STREAMTYPES_H
+#define _STREAMTYPES_H
+
+#ifdef _MSC_VER
+#include <pstdint.h>
+#define inline _inline
+#define strcasecmp _stricmp
+#define snprintf _snprintf
+#else
+#include <stdint.h>
+#endif
+
+typedef int16_t sample;
+
+#endif
diff --git a/lib/vgmstream/src/util.c b/lib/vgmstream/src/util.c
new file mode 100644
index 0000000000..42d7a1c169
--- /dev/null
+++ b/lib/vgmstream/src/util.c
@@ -0,0 +1,144 @@
+#include <string.h>
+#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<sample_count;insample++,outsample+=channel_count) {
+ outbuffer[outsample]=inbuffer[insample];
+ }
+}
+
+/* failed attempt at interleave in place */
+/*
+void interleave_stereo(sample * buffer, int32_t sample_count) {
+ int32_t tomove, belongs;
+ sample moving,temp;
+
+ tomove = sample_count;
+ moving = buffer[tomove];
+
+ do {
+ if (tomove<sample_count)
+ belongs = tomove*2;
+ else
+ belongs = (tomove-sample_count)*2+1;
+
+ printf("move %d to %d\n",tomove,belongs);
+
+ temp = buffer[belongs];
+ buffer[belongs] = moving;
+ moving = temp;
+
+ tomove = belongs;
+ } while (tomove != sample_count);
+}
+*/
+
+void put_16bitLE(uint8_t * buf, int16_t i) {
+ buf[0] = (i & 0xFF);
+ buf[1] = i >> 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);
+}
+
+/* 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);
+}
+
+/* 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<length-1 && dst[i];i++); /* find end of dst */
+ for (j=0;i<length-1 && src[j];i++,j++)
+ dst[i]=src[j];
+ dst[i]='\0';
+}
+
+/* length is maximum length of dst. dst will always be double-null-terminated if
+ * length > 1 */
+void concatn_doublenull(int length, char * dst, const char * src) {
+ int i,j;
+ if (length <= 1) return;
+ for (i=0;i<length-2 && (dst[i] || dst[i+1]);i++); /* find end of dst */
+ if (i==length-2) {
+ dst[i]='\0';
+ dst[i+1]='\0';
+ return;
+ }
+ if (i>0) i++;
+ for (j=0;i<length-2 && (src[j] || src[j+1]);i++,j++) dst[i]=src[j];
+ dst[i]='\0';
+ dst[i+1]='\0';
+}
diff --git a/lib/vgmstream/src/util.h b/lib/vgmstream/src/util.h
new file mode 100644
index 0000000000..57fcca0313
--- /dev/null
+++ b/lib/vgmstream/src/util.h
@@ -0,0 +1,66 @@
+/*
+ * util.h - utility functions
+ */
+
+#include "streamtypes.h"
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+/* host endian independent multi-byte integer reading */
+
+static inline int16_t get_16bitBE(uint8_t * p) {
+ return (p[0]<<8) | (p[1]);
+}
+
+static inline int16_t get_16bitLE(uint8_t * p) {
+ return (p[0]) | (p[1]<<8);
+}
+
+static inline int32_t get_32bitBE(uint8_t * p) {
+ return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | (p[3]);
+}
+
+static inline int32_t get_32bitLE(uint8_t * p) {
+ return (p[0]) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
+}
+
+void put_16bitLE(uint8_t * buf, int16_t i);
+
+void put_32bitLE(uint8_t * buf, int32_t i);
+
+/* signed nibbles come up a lot */
+static int nibble_to_int[16] = {0,1,2,3,4,5,6,7,-8,-7,-6,-5,-4,-3,-2,-1};
+
+static inline int get_high_nibble_signed(uint8_t n) {
+ /*return ((n&0x70)-(n&0x80))>>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 concatn(int length, char * dst, const char * src);
+void concatn_doublenull(int length, char * dst, const char * src);
+
+#endif
diff --git a/lib/vgmstream/src/vgmstream.c b/lib/vgmstream/src/vgmstream.c
new file mode 100644
index 0000000000..8c00eda69b
--- /dev/null
+++ b/lib/vgmstream/src/vgmstream.c
@@ -0,0 +1,2209 @@
+#ifdef _MSC_VER
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#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
+ 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_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_fsb3,
+ init_vgmstream_fsb4,
+ init_vgmstream_rwx,
+ init_vgmstream_xwb,
+ init_vgmstream_xa30,
+ init_vgmstream_musc,
+ init_vgmstream_musx_v004,
+ 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,
+ 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_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_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_rsd3pcm,
+ init_vgmstream_rsd4pcmb,
+ init_vgmstream_rsd4pcm,
+ init_vgmstream_rsd4vag,
+ init_vgmstream_rsd6vag,
+ init_vgmstream_rsd6wadp,
+ init_vgmstream_rsd6xadp,
+ init_vgmstream_bgw,
+ init_vgmstream_spw,
+ init_vgmstream_ps2_ass,
+ init_vgmstream_waa_wac_wad_wam,
+ init_vgmstream_ps2_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_wav_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_iadp,
+ init_vgmstream_aax,
+ init_vgmstream_ngc_ffcc_str,
+};
+
+#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;i<INIT_VGMSTREAM_FCNS;i++) {
+ VGMSTREAM * vgmstream = (init_vgmstream_fcns[i])(streamFile);
+ if (vgmstream) {
+ /* these are little hacky checks */
+
+ /* everything should have a reasonable sample rate
+ * (a verification of the metadata) */
+ if (!check_sample_rate(vgmstream->sample_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->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
+#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
+
+ if (vgmstream->coding_type==coding_ACM) {
+ mus_acm_codec_data *data = vgmstream->codec_data;
+ int i;
+
+ data->current_file = 0;
+ for (i=0;i<data->file_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;i<data->segment_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;i<data->segment_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);
+ }
+}
+
+/* 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
+
+#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
+
+ if (vgmstream->coding_type==coding_ACM) {
+ mus_acm_codec_data *data = vgmstream->codec_data;
+
+ if (data) {
+ if (data->files) {
+ int i;
+ for (i=0; i<data->file_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;i<data->segment_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;i<data->segment_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;
+ }
+
+ /* now that the special cases have had their chance, clean up the standard items */
+ for (i=0;i<vgmstream->channels;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;j<vgmstream->channels;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_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:
+ 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;
+ }
+}
+
+int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
+ switch (vgmstream->coding_type) {
+ case coding_CRI_ADX:
+ case coding_CRI_ADX_enc:
+ case coding_L5_555:
+ return 32;
+ case coding_NGC_DSP:
+ return 14;
+ case coding_PCM16LE:
+ case coding_PCM16LE_int:
+ case coding_PCM16BE:
+ case coding_PCM8:
+ 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_ACM:
+ case coding_NWA0:
+ case coding_NWA1:
+ case coding_NWA2:
+ case coding_NWA3:
+ case coding_NWA4:
+ case coding_NWA5:
+ return 1;
+ case coding_NDS_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_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:
+ return 64;
+ case coding_EAXA:
+ return 28;
+ 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_NDS_PROCYON:
+ return 30;
+ 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:
+ case coding_L5_555:
+ return 18;
+ case coding_NGC_DSP:
+ return 8;
+ case coding_PCM16LE:
+ case coding_PCM16LE_int:
+ case coding_PCM16BE:
+ return 2;
+ case coding_PCM8:
+ case coding_PCM8_int:
+ case coding_PCM8_SB_int:
+ case coding_PCM8_U_int:
+ case coding_SDX2:
+ case coding_SDX2_int:
+ case coding_NWA0:
+ case coding_NWA1:
+ case coding_NWA2:
+ case coding_NWA3:
+ case coding_NWA4:
+ case coding_NWA5:
+ return 1;
+ case coding_NDS_IMA:
+ return vgmstream->interleave_block_size;
+ case coding_NGC_DTK:
+ return 32;
+ case coding_EACS_IMA:
+ return 1;
+ case coding_DVI_IMA:
+ case coding_IMA:
+ case coding_G721:
+ 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:
+ return 36;
+ 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_MSADPCM:
+ 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;chan<vgmstream->channels;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:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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_PCM16BE:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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_int:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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_XBOX:
+ for (chan=0;chan<vgmstream->channels;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_NGC_DTK:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;chan++) {
+ 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;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;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_XA:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;chan++) {
+ decode_ea_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
+ case coding_SDX2:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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_DVI_IMA:
+ case coding_INT_DVI_IMA:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;chan++) {
+ decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
+ vgmstream->channels,vgmstream->samples_into_block,
+ samples_to_do);
+ }
+ break;
+ case coding_WS:
+ for (chan=0;chan<vgmstream->channels;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
+ 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);
+ }
+ break;
+ case coding_AICA:
+ for (chan=0;chan<vgmstream->channels;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;chan<vgmstream->channels;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;chan<vgmstream->channels;chan++) {
+ decode_l5_555(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
+ vgmstream->channels,vgmstream->samples_into_block,
+ samples_to_do);
+ }
+
+ 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;i<vgmstream->channels;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;i<vgmstream->channels;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
+#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 (%.2lf seconds)\n"
+ "loop end: %d samples (%.2lf 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 (%.2lf 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_PCM8:
+ snprintf(temp,TEMPSIZE,"8-bit 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:
+ snprintf(temp,TEMPSIZE,"encrypted CRI ADX 4-bit ADPCM");
+ break;
+ case coding_NDS_IMA:
+ snprintf(temp,TEMPSIZE,"NDS-style 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_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_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_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_INT_IMA:
+ snprintf(temp,TEMPSIZE,"Interleaved 4-bit IMA ADPCM");
+ break;
+ case coding_IMA:
+ snprintf(temp,TEMPSIZE,"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
+ 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 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_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;
+#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;
+ 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_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_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;
+#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:
+ snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB3) Header");
+ break;
+ case meta_FSB4:
+ snprintf(temp,TEMPSIZE,"FMOD Sample Bank (FSB4) 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_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_PCM:
+ snprintf(temp,TEMPSIZE,"PCM file with custom header");
+ 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");
+ 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,"assumed XA2 file by .xa2 extension");
+ 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_RSD3PCM:
+ snprintf(temp,TEMPSIZE,"RSD3/PCM Header");
+ break;
+ case meta_RSD4PCMB:
+ snprintf(temp,TEMPSIZE,"RSD4/PCMB Header");
+ break;
+ case meta_RSD4PCM:
+ snprintf(temp,TEMPSIZE,"RSD4/PCM 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_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_IDSP2:
+ 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_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,"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_WAV_DCS:
+ snprintf(temp,TEMPSIZE,"Evil Twin WAV+DCS Header");
+ 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_IADP:
+ snprintf(temp,TEMPSIZE,"Dr MUTO 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_FFCC_STR:
+ snprintf(temp,TEMPSIZE,"Final Fantasy: Crystal Chronicles STR 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[260];
+ 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 && i<DFS_PAIR_COUNT; i++) {
+ for (j=0; dfs_name==-1 && j<2; j++) {
+ /* find a postfix on the name */
+ if (!memcmp(ext-strlen(dfs_pairs[i][j]),
+ dfs_pairs[i][j],
+ strlen(dfs_pairs[i][j]))) {
+ int other_name=j^1;
+ int moveby;
+ dfs_name=j;
+
+ /* move the extension */
+ moveby = strlen(dfs_pairs[i][other_name]) -
+ strlen(dfs_pairs[i][dfs_name]);
+ memmove(ext+moveby,ext,strlen(ext)+1); /* terminator, too */
+
+ /* make the new name */
+ memcpy(ext+moveby-strlen(dfs_pairs[i][other_name]),dfs_pairs[i][other_name],strlen(dfs_pairs[i][other_name]));
+ }
+ }
+ }
+
+ /* did we find a name for the other file? */
+ if (dfs_name==-1) goto fail;
+
+#if 0
+ printf("input is: %s\n"
+ "other file would be: %s\n",
+ filename,filename2);
+#endif
+
+ dual_stream = streamFile->open(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/lib/vgmstream/src/vgmstream.h b/lib/vgmstream/src/vgmstream.h
new file mode 100644
index 0000000000..82f377a147
--- /dev/null
+++ b/lib/vgmstream/src/vgmstream.h
@@ -0,0 +1,608 @@
+/*
+ * vgmstream.h - definitions for VGMSTREAM, encapsulating a multi-channel, looped audio stream
+ */
+
+#ifndef _VGMSTREAM_H
+#define _VGMSTREAM_H
+
+/* Vorbis and MPEG 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
+
+#include "streamfile.h"
+#include "coding/g72x_state.h"
+#ifdef VGM_USE_VORBIS
+#include <vorbis/vorbisfile.h>
+#endif
+#ifdef VGM_USE_MPEG
+#include <mpg123.h>
+#endif
+#include "coding/acm_decoder.h"
+#include "coding/nwa_decoder.h"
+
+/* 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_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, /* encrypted CRI ADX */
+ 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_XA, /* PSX CD-XA */
+ coding_XBOX, /* XBOX IMA */
+ coding_EAXA, /* EA/XA ADPCM */
+ coding_EA_ADPCM, /* EA 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_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_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
+
+ 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_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,
+
+#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_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 */
+
+ /* 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_RSTM_SPM, /* RSTM with 44->22khz hack */
+ meta_THP,
+ meta_RSTM_shrunken, /* Atlus' mutant shortened RSTM */
+
+ /* 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 */
+
+ /* 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_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_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, /* FMOD Sample Bank, version 3 */
+ meta_FSB4, /* FMOD Sample Bank, version 4 */
+ 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_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, /* Ephemeral Fantasia, 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, /* XA2 XG3 file */
+ meta_IDSP, /* Chronicles of Narnia */
+ 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_IDSP2, /* Chronicles of Narnia */
+ 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_RSD3PCM, /* RSD3PCM */
+ meta_RSD4PCMB, /* RSD4PCMB */
+ meta_RSD4PCM, /* RSD4PCM */
+ meta_RSD4VAG, /* RSD4VAG */
+ meta_RSD6VAG, /* RSD6VAG */
+ meta_RSD6WADP, /* RSD6WADP */
+ meta_RSD6XADP, /* RSD6XADP */
+
+ meta_PS2_ASS, /* ASS */
+ meta_PS2_SEG, /* Eragon */
+ 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_WAV_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_XBOX_WAVM, /* XBOX WAVM File */
+ meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
+ meta_XBOX_WVS, /* XBOX 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 */
+#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_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_IADP, /* Gamecube Interleave DSP */
+
+} 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;
+ };
+
+ 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;
+} 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 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 */
+ 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;
+
+ /* 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_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
+
+/* 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;
+
+/* 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/lib/vgmstream/win32/win32.sln b/lib/vgmstream/win32/win32.sln
new file mode 100644
index 0000000000..fee7843cf9
--- /dev/null
+++ b/lib/vgmstream/win32/win32.sln
@@ -0,0 +1,19 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vgmstream", "win32.vcproj", "{3600E1C5-FECA-468C-83F3-FE467DBE2A66}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug|Win32.ActiveCfg = Debug|Win32
+ {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug|Win32.Build.0 = Debug|Win32
+ {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release|Win32.ActiveCfg = Release|Win32
+ {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/lib/vgmstream/win32/win32.vcproj b/lib/vgmstream/win32/win32.vcproj
new file mode 100644
index 0000000000..53123a9efa
--- /dev/null
+++ b/lib/vgmstream/win32/win32.vcproj
@@ -0,0 +1,1000 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="libvgmstream_dll"
+ ProjectGUID="{3600E1C5-FECA-468C-83F3-FE467DBE2A66}"
+ RootNamespace="libvgmstream_dll"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
+ IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\ext_includes"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;WIN32_EXPORTS;_CRT_SECURE_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4267;4018;4244;4312"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="..\..\..\..\..\system\players\paplayer\vgmstream.dll"
+ LinkIncremental="1"
+ IgnoreDefaultLibraryNames="LIBCMTD"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="win32.pdb"
+ SubSystem="2"
+ ProfileGuidedDatabase=""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="win32.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)libs\$(ProjectName)\$(ConfigurationName)\"
+ IntermediateDirectory="$(SolutionDir)objs\$(ProjectName)\$(ConfigurationName)\"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\ext_includes"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN32_EXPORTS;_CRT_SECURE_NO_WARNINGS;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="3"
+ DisableSpecificWarnings="4267;4018;4244;4312"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ OutputFile="..\..\..\..\..\system\players\paplayer\vgmstream.dll"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(TargetName).pdb"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ ProfileGuidedDatabase=""
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="win32.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="coding"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath="..\src\coding\acm_decoder.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\coding.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\g72x_state.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\nwa_decoder.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath="..\src\coding\acm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\adx_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\aica_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\eaxa_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\g721_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ima_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\l5_555_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\mpeg_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\msadpcm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\nds_procyon_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ngc_afc_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ngc_dsp_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ngc_dtk_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\nwa_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ogg_vorbis_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\pcm_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\psx_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\sdx2_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\ws_decoder.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\coding\xa_decoder.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath="..\src\streamfile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\streamtypes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\util.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vgmstream.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath="..\src\streamfile.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\util.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vgmstream.c"
+ >
+ </File>
+ <File
+ RelativePath="..\XBMCVGM.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="meta"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath="..\src\meta\meta.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath="..\src\meta\aax.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\acm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\adx_header.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\afc_header.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\agsc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ahx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\aifc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\aix.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ast.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\bgw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\brstm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\capdsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\Cstr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\dc_asd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\dc_idvi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\dc_kcey.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\dc_str.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\dc_wav_dcs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\de2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ea_header.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ea_old.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\emff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\fsb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\gca.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\gcsw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\genh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\gsp_gsb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\halpst.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\idsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ish_isd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ivb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\kraw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\msvp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\mus_acm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\musc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\musx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\naomi_spsd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\nds_sad.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\nds_strm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_adpdtk.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_bh2pcm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_caf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_dsp_std.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_ffcc_str.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_iadp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_pdt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_ssm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_tydsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_waa_wac_wad_wam.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ngc_ymf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\nwa.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ogg_vorbis_file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\pcm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\pos.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_ads.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_ass.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_aus.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_bg00.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_bmdx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_ccc.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_dxh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_enth.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_exst.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_filp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_gbts.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_hgc1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_ikm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_ild.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_int.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_joe.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_kces.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_leg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_mib.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_mic.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_mihb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_npsf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_p2bt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_pnb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_psh.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_psw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_rkv.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_rnd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_rstm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_rws.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_rxw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_seg.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_sfs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_sl3.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_str.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_svag.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_tec.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_vag.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_vas.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_vpk.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_xa2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ps2_xa30.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\psx_cdxa.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\psx_fag.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\psx_gms.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\raw.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\riff.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\rs03.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\rsd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\rsf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\rwsd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\rwx.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\sat_dvi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\sat_sap.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\sdt.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\sfl.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\sli.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\spt_spd.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ss_stream.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\str_asr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\str_snds.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\svs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\thp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\vgs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\vs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\wii_mus.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\wii_smp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\wii_sng.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\wii_sts.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ws_aud.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_ims.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_stma.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_wavm.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_wvs.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_xmu.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_xvas.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xbox_xwav.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xss.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\xwb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\ydsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\meta\zwdsp.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="layout"
+ >
+ <Filter
+ Name="Header Files"
+ >
+ <File
+ RelativePath="..\src\layout\layout.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ >
+ <File
+ RelativePath="..\src\layout\aax_layout.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\aix_layout.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\ast_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\caf_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\de2_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\ea_block.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\emff_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\filp_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\gsb_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\halpst_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\ims_block.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\interleave.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\interleave_byte.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\mus_acm_layout.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\nolayout.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\str_snds_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\thp_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\vs_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\ws_aud_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\wsi_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\xa_blocked.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\layout\xvas_block.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/lib/vgmstream/win32/win32.vcxproj b/lib/vgmstream/win32/win32.vcxproj
new file mode 100644
index 0000000000..4975f6af57
--- /dev/null
+++ b/lib/vgmstream/win32/win32.vcxproj
@@ -0,0 +1,345 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>libvgmstream_dll</ProjectName>
+ <ProjectGuid>{3600E1C5-FECA-468C-83F3-FE467DBE2A66}</ProjectGuid>
+ <RootNamespace>libvgmstream_dll</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ <Import Project="..\..\..\project\VS2010Express\XBMC for Windows.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ <Import Project="..\..\..\project\VS2010Express\XBMC for Windows.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">vgmstream</TargetName>
+ <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">vgmstream</TargetName>
+ <CustomBuildAfterTargets Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Build</CustomBuildAfterTargets>
+ <CustomBuildAfterTargets Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Build</CustomBuildAfterTargets>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\ext_includes;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;WIN32_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4267;4018;4244;4312;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)\$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ <IgnoreSpecificDefaultLibraries>
+ </IgnoreSpecificDefaultLibraries>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ <CustomBuildStep>
+ <Command>copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)"</Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Message>Copy output</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)</Outputs>
+ <Inputs>$(TargetPath)</Inputs>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\ext_includes;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;WIN32_EXPORTS;_CRT_SECURE_NO_WARNINGS;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <DisableSpecificWarnings>4267;4018;4244;4312;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <Link>
+ <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>$(OutDir)\$(TargetName).pdb</ProgramDatabaseFile>
+ <SubSystem>Windows</SubSystem>
+ <OptimizeReferences>true</OptimizeReferences>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <ProfileGuidedDatabase>
+ </ProfileGuidedDatabase>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(OutDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <PostBuildEvent>
+ <Command>
+ </Command>
+ </PostBuildEvent>
+ <CustomBuildStep>
+ <Command>copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)"</Command>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Message>Copy output</Message>
+ </CustomBuildStep>
+ <CustomBuildStep>
+ <Outputs>$(SolutionDir)..\..\system\players\paplayer\$(TargetFileName)</Outputs>
+ <Inputs>$(TargetPath)</Inputs>
+ </CustomBuildStep>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\coding\acm_decoder.h" />
+ <ClInclude Include="..\src\coding\coding.h" />
+ <ClInclude Include="..\src\coding\g72x_state.h" />
+ <ClInclude Include="..\src\coding\nwa_decoder.h" />
+ <ClInclude Include="..\src\streamfile.h" />
+ <ClInclude Include="..\src\streamtypes.h" />
+ <ClInclude Include="..\src\util.h" />
+ <ClInclude Include="..\src\vgmstream.h" />
+ <ClInclude Include="..\src\meta\meta.h" />
+ <ClInclude Include="..\src\layout\layout.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\coding\acm_decoder.c" />
+ <ClCompile Include="..\src\coding\adx_decoder.c" />
+ <ClCompile Include="..\src\coding\aica_decoder.c" />
+ <ClCompile Include="..\src\coding\eaxa_decoder.c" />
+ <ClCompile Include="..\src\coding\g721_decoder.c" />
+ <ClCompile Include="..\src\coding\ima_decoder.c" />
+ <ClCompile Include="..\src\coding\l5_555_decoder.c" />
+ <ClCompile Include="..\src\coding\mpeg_decoder.c" />
+ <ClCompile Include="..\src\coding\msadpcm_decoder.c" />
+ <ClCompile Include="..\src\coding\nds_procyon_decoder.c" />
+ <ClCompile Include="..\src\coding\ngc_afc_decoder.c" />
+ <ClCompile Include="..\src\coding\ngc_dsp_decoder.c" />
+ <ClCompile Include="..\src\coding\ngc_dtk_decoder.c" />
+ <ClCompile Include="..\src\coding\nwa_decoder.c" />
+ <ClCompile Include="..\src\coding\ogg_vorbis_decoder.c" />
+ <ClCompile Include="..\src\coding\pcm_decoder.c" />
+ <ClCompile Include="..\src\coding\psx_decoder.c" />
+ <ClCompile Include="..\src\coding\sdx2_decoder.c" />
+ <ClCompile Include="..\src\coding\ws_decoder.c" />
+ <ClCompile Include="..\src\coding\xa_decoder.c" />
+ <ClCompile Include="..\src\streamfile.c" />
+ <ClCompile Include="..\src\util.c" />
+ <ClCompile Include="..\src\vgmstream.c" />
+ <ClCompile Include="..\XBMCVGM.cpp" />
+ <ClCompile Include="..\src\meta\aax.c" />
+ <ClCompile Include="..\src\meta\acm.c" />
+ <ClCompile Include="..\src\meta\adx_header.c" />
+ <ClCompile Include="..\src\meta\afc_header.c" />
+ <ClCompile Include="..\src\meta\agsc.c" />
+ <ClCompile Include="..\src\meta\ahx.c" />
+ <ClCompile Include="..\src\meta\aifc.c" />
+ <ClCompile Include="..\src\meta\aix.c" />
+ <ClCompile Include="..\src\meta\ast.c" />
+ <ClCompile Include="..\src\meta\bgw.c" />
+ <ClCompile Include="..\src\meta\brstm.c" />
+ <ClCompile Include="..\src\meta\capdsp.c" />
+ <ClCompile Include="..\src\meta\Cstr.c" />
+ <ClCompile Include="..\src\meta\dc_asd.c" />
+ <ClCompile Include="..\src\meta\dc_idvi.c" />
+ <ClCompile Include="..\src\meta\dc_kcey.c" />
+ <ClCompile Include="..\src\meta\dc_str.c" />
+ <ClCompile Include="..\src\meta\dc_wav_dcs.c" />
+ <ClCompile Include="..\src\meta\de2.c" />
+ <ClCompile Include="..\src\meta\ea_header.c" />
+ <ClCompile Include="..\src\meta\ea_old.c" />
+ <ClCompile Include="..\src\meta\emff.c" />
+ <ClCompile Include="..\src\meta\fsb.c" />
+ <ClCompile Include="..\src\meta\gca.c" />
+ <ClCompile Include="..\src\meta\gcsw.c" />
+ <ClCompile Include="..\src\meta\genh.c" />
+ <ClCompile Include="..\src\meta\gsp_gsb.c" />
+ <ClCompile Include="..\src\meta\halpst.c" />
+ <ClCompile Include="..\src\meta\idsp.c" />
+ <ClCompile Include="..\src\meta\ish_isd.c" />
+ <ClCompile Include="..\src\meta\ivb.c" />
+ <ClCompile Include="..\src\meta\kraw.c" />
+ <ClCompile Include="..\src\meta\msvp.c" />
+ <ClCompile Include="..\src\meta\mus_acm.c" />
+ <ClCompile Include="..\src\meta\musc.c" />
+ <ClCompile Include="..\src\meta\musx.c" />
+ <ClCompile Include="..\src\meta\naomi_spsd.c" />
+ <ClCompile Include="..\src\meta\nds_sad.c" />
+ <ClCompile Include="..\src\meta\nds_strm.c" />
+ <ClCompile Include="..\src\meta\ngc_adpdtk.c" />
+ <ClCompile Include="..\src\meta\ngc_bh2pcm.c" />
+ <ClCompile Include="..\src\meta\ngc_caf.c" />
+ <ClCompile Include="..\src\meta\ngc_dsp_std.c" />
+ <ClCompile Include="..\src\meta\ngc_ffcc_str.c" />
+ <ClCompile Include="..\src\meta\ngc_iadp.c" />
+ <ClCompile Include="..\src\meta\ngc_pdt.c" />
+ <ClCompile Include="..\src\meta\ngc_ssm.c" />
+ <ClCompile Include="..\src\meta\ngc_tydsp.c" />
+ <ClCompile Include="..\src\meta\ngc_waa_wac_wad_wam.c" />
+ <ClCompile Include="..\src\meta\ngc_ymf.c" />
+ <ClCompile Include="..\src\meta\nwa.c" />
+ <ClCompile Include="..\src\meta\ogg_vorbis_file.c" />
+ <ClCompile Include="..\src\meta\pcm.c" />
+ <ClCompile Include="..\src\meta\pos.c" />
+ <ClCompile Include="..\src\meta\ps2_ads.c" />
+ <ClCompile Include="..\src\meta\ps2_ass.c" />
+ <ClCompile Include="..\src\meta\ps2_aus.c" />
+ <ClCompile Include="..\src\meta\ps2_bg00.c" />
+ <ClCompile Include="..\src\meta\ps2_bmdx.c" />
+ <ClCompile Include="..\src\meta\ps2_ccc.c" />
+ <ClCompile Include="..\src\meta\ps2_dxh.c" />
+ <ClCompile Include="..\src\meta\ps2_enth.c" />
+ <ClCompile Include="..\src\meta\ps2_exst.c" />
+ <ClCompile Include="..\src\meta\ps2_filp.c" />
+ <ClCompile Include="..\src\meta\ps2_gbts.c" />
+ <ClCompile Include="..\src\meta\ps2_hgc1.c" />
+ <ClCompile Include="..\src\meta\ps2_ikm.c" />
+ <ClCompile Include="..\src\meta\ps2_ild.c" />
+ <ClCompile Include="..\src\meta\ps2_int.c" />
+ <ClCompile Include="..\src\meta\ps2_joe.c" />
+ <ClCompile Include="..\src\meta\ps2_kces.c" />
+ <ClCompile Include="..\src\meta\ps2_leg.c" />
+ <ClCompile Include="..\src\meta\ps2_mib.c" />
+ <ClCompile Include="..\src\meta\ps2_mic.c" />
+ <ClCompile Include="..\src\meta\ps2_mihb.c" />
+ <ClCompile Include="..\src\meta\ps2_npsf.c" />
+ <ClCompile Include="..\src\meta\ps2_p2bt.c" />
+ <ClCompile Include="..\src\meta\ps2_pnb.c" />
+ <ClCompile Include="..\src\meta\ps2_psh.c" />
+ <ClCompile Include="..\src\meta\ps2_psw.c" />
+ <ClCompile Include="..\src\meta\ps2_rkv.c" />
+ <ClCompile Include="..\src\meta\ps2_rnd.c" />
+ <ClCompile Include="..\src\meta\ps2_rstm.c" />
+ <ClCompile Include="..\src\meta\ps2_rws.c" />
+ <ClCompile Include="..\src\meta\ps2_rxw.c" />
+ <ClCompile Include="..\src\meta\ps2_seg.c" />
+ <ClCompile Include="..\src\meta\ps2_sfs.c" />
+ <ClCompile Include="..\src\meta\ps2_sl3.c" />
+ <ClCompile Include="..\src\meta\ps2_str.c" />
+ <ClCompile Include="..\src\meta\ps2_svag.c" />
+ <ClCompile Include="..\src\meta\ps2_tec.c" />
+ <ClCompile Include="..\src\meta\ps2_vag.c" />
+ <ClCompile Include="..\src\meta\ps2_vas.c" />
+ <ClCompile Include="..\src\meta\ps2_vpk.c" />
+ <ClCompile Include="..\src\meta\ps2_xa2.c" />
+ <ClCompile Include="..\src\meta\ps2_xa30.c" />
+ <ClCompile Include="..\src\meta\psx_cdxa.c" />
+ <ClCompile Include="..\src\meta\psx_fag.c" />
+ <ClCompile Include="..\src\meta\psx_gms.c" />
+ <ClCompile Include="..\src\meta\raw.c" />
+ <ClCompile Include="..\src\meta\riff.c" />
+ <ClCompile Include="..\src\meta\rs03.c" />
+ <ClCompile Include="..\src\meta\rsd.c" />
+ <ClCompile Include="..\src\meta\rsf.c" />
+ <ClCompile Include="..\src\meta\rwsd.c" />
+ <ClCompile Include="..\src\meta\rwx.c" />
+ <ClCompile Include="..\src\meta\sat_dvi.c" />
+ <ClCompile Include="..\src\meta\sat_sap.c" />
+ <ClCompile Include="..\src\meta\sdt.c" />
+ <ClCompile Include="..\src\meta\sfl.c" />
+ <ClCompile Include="..\src\meta\sli.c" />
+ <ClCompile Include="..\src\meta\spt_spd.c" />
+ <ClCompile Include="..\src\meta\ss_stream.c" />
+ <ClCompile Include="..\src\meta\str_asr.c" />
+ <ClCompile Include="..\src\meta\str_snds.c" />
+ <ClCompile Include="..\src\meta\svs.c" />
+ <ClCompile Include="..\src\meta\thp.c" />
+ <ClCompile Include="..\src\meta\vgs.c" />
+ <ClCompile Include="..\src\meta\vs.c" />
+ <ClCompile Include="..\src\meta\wii_mus.c" />
+ <ClCompile Include="..\src\meta\wii_smp.c" />
+ <ClCompile Include="..\src\meta\wii_sng.c" />
+ <ClCompile Include="..\src\meta\wii_sts.c" />
+ <ClCompile Include="..\src\meta\ws_aud.c" />
+ <ClCompile Include="..\src\meta\xbox_ims.c" />
+ <ClCompile Include="..\src\meta\xbox_stma.c" />
+ <ClCompile Include="..\src\meta\xbox_wavm.c" />
+ <ClCompile Include="..\src\meta\xbox_wvs.c" />
+ <ClCompile Include="..\src\meta\xbox_xmu.c" />
+ <ClCompile Include="..\src\meta\xbox_xvas.c" />
+ <ClCompile Include="..\src\meta\xbox_xwav.c" />
+ <ClCompile Include="..\src\meta\xss.c" />
+ <ClCompile Include="..\src\meta\xwb.c" />
+ <ClCompile Include="..\src\meta\ydsp.c" />
+ <ClCompile Include="..\src\meta\zwdsp.c" />
+ <ClCompile Include="..\src\layout\aax_layout.c" />
+ <ClCompile Include="..\src\layout\aix_layout.c" />
+ <ClCompile Include="..\src\layout\ast_blocked.c" />
+ <ClCompile Include="..\src\layout\blocked.c" />
+ <ClCompile Include="..\src\layout\caf_blocked.c" />
+ <ClCompile Include="..\src\layout\de2_blocked.c" />
+ <ClCompile Include="..\src\layout\ea_block.c" />
+ <ClCompile Include="..\src\layout\emff_blocked.c" />
+ <ClCompile Include="..\src\layout\filp_blocked.c" />
+ <ClCompile Include="..\src\layout\gsb_blocked.c" />
+ <ClCompile Include="..\src\layout\halpst_blocked.c" />
+ <ClCompile Include="..\src\layout\ims_block.c" />
+ <ClCompile Include="..\src\layout\interleave.c" />
+ <ClCompile Include="..\src\layout\interleave_byte.c" />
+ <ClCompile Include="..\src\layout\mus_acm_layout.c" />
+ <ClCompile Include="..\src\layout\nolayout.c" />
+ <ClCompile Include="..\src\layout\str_snds_blocked.c" />
+ <ClCompile Include="..\src\layout\thp_blocked.c" />
+ <ClCompile Include="..\src\layout\vs_blocked.c" />
+ <ClCompile Include="..\src\layout\ws_aud_blocked.c" />
+ <ClCompile Include="..\src\layout\wsi_blocked.c" />
+ <ClCompile Include="..\src\layout\xa_blocked.c" />
+ <ClCompile Include="..\src\layout\xvas_block.c" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/vgmstream/win32/win32.vcxproj.filters b/lib/vgmstream/win32/win32.vcxproj.filters
new file mode 100644
index 0000000000..2fe00ebfcd
--- /dev/null
+++ b/lib/vgmstream/win32/win32.vcxproj.filters
@@ -0,0 +1,612 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="coding">
+ <UniqueIdentifier>{732b002c-1974-4554-9ef6-8333f62f4e77}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="coding\Header Files">
+ <UniqueIdentifier>{f50aab92-7740-403b-847e-5d05d8f8890e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="coding\Source Files">
+ <UniqueIdentifier>{bc913f6c-2310-43f9-9aed-1c48c0506489}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="meta">
+ <UniqueIdentifier>{eb1ead8a-54be-4d36-be29-dae1f2a8341e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="meta\Header Files">
+ <UniqueIdentifier>{df36a847-cf51-485b-81a7-1e0754cd5f69}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="meta\Source Files">
+ <UniqueIdentifier>{0b740a87-d188-4d5e-b2b5-701ec24abc39}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="layout">
+ <UniqueIdentifier>{994cb7da-a1a3-4bb1-90e8-819e45bb1289}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="layout\Header Files">
+ <UniqueIdentifier>{48ce4671-a794-4aab-9733-96ee67961247}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="layout\Source Files">
+ <UniqueIdentifier>{959bbe75-3072-4008-b0d4-7d819b32add0}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\src\coding\acm_decoder.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\coding\coding.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\coding\g72x_state.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\coding\nwa_decoder.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\streamfile.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\streamtypes.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\util.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\vgmstream.h">
+ <Filter>coding\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\meta\meta.h">
+ <Filter>meta\Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\src\layout\layout.h">
+ <Filter>layout\Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\src\coding\acm_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\adx_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\aica_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\eaxa_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\g721_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ima_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\l5_555_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\mpeg_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\msadpcm_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\nds_procyon_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ngc_afc_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ngc_dsp_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ngc_dtk_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\nwa_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ogg_vorbis_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\pcm_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\psx_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\sdx2_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\ws_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\coding\xa_decoder.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\streamfile.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\util.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\vgmstream.c">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\XBMCVGM.cpp">
+ <Filter>coding\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\aax.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\acm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\adx_header.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\afc_header.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\agsc.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ahx.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\aifc.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\aix.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ast.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\bgw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\brstm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\capdsp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\Cstr.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\dc_asd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\dc_idvi.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\dc_kcey.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\dc_str.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\dc_wav_dcs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\de2.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ea_header.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ea_old.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\emff.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\fsb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\gca.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\gcsw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\genh.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\gsp_gsb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\halpst.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\idsp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ish_isd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ivb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\kraw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\msvp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\mus_acm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\musc.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\musx.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\naomi_spsd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\nds_sad.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\nds_strm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_adpdtk.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_bh2pcm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_caf.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_dsp_std.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_ffcc_str.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_iadp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_pdt.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_ssm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_tydsp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_waa_wac_wad_wam.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ngc_ymf.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\nwa.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ogg_vorbis_file.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\pcm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\pos.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_ads.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_ass.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_aus.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_bg00.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_bmdx.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_ccc.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_dxh.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_enth.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_exst.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_filp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_gbts.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_hgc1.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_ikm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_ild.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_int.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_joe.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_kces.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_leg.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_mib.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_mic.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_mihb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_npsf.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_p2bt.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_pnb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_psh.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_psw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_rkv.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_rnd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_rstm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_rws.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_rxw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_seg.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_sfs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_sl3.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_str.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_svag.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_tec.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_vag.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_vas.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_vpk.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_xa2.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ps2_xa30.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\psx_cdxa.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\psx_fag.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\psx_gms.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\raw.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\riff.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\rs03.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\rsd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\rsf.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\rwsd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\rwx.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\sat_dvi.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\sat_sap.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\sdt.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\sfl.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\sli.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\spt_spd.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ss_stream.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\str_asr.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\str_snds.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\svs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\thp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\vgs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\vs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\wii_mus.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\wii_smp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\wii_sng.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\wii_sts.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ws_aud.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_ims.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_stma.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_wavm.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_wvs.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_xmu.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_xvas.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xbox_xwav.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xss.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\xwb.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\ydsp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\meta\zwdsp.c">
+ <Filter>meta\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\aax_layout.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\aix_layout.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\ast_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\caf_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\de2_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\ea_block.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\emff_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\filp_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\gsb_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\halpst_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\ims_block.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\interleave.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\interleave_byte.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\mus_acm_layout.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\nolayout.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\str_snds_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\thp_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\vs_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\ws_aud_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\wsi_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\xa_blocked.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\src\layout\xvas_block.c">
+ <Filter>layout\Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file