Merge pull request #58 from bnnm/format-list-scd

Formats: unified list, SCD fixes
This commit is contained in:
Christopher Snowhill 2017-01-03 16:25:38 -08:00 committed by GitHub
commit 1b9dcac1c6
20 changed files with 769 additions and 719 deletions

8
.gitignore vendored
View File

@ -5,6 +5,11 @@
*.vspscc *.vspscc
*.o *.o
*.a *.a
*.VC.db
*.VC.VC.opendb
Debug
Release
ipch
/ext_libs/Debug /ext_libs/Debug
/ext_libs/Release /ext_libs/Release
/ext_libs/*.exp /ext_libs/*.exp
@ -18,4 +23,7 @@
/test/Debug /test/Debug
/test/Release /test/Release
/test/*.exe /test/*.exe
/winamp/Debug
/winamp/Release
/winamp/*.dll /winamp/*.dll
/xmp-vgmstream/*.dll

View File

@ -14,9 +14,9 @@
## Compiling modules ## Compiling modules
### test.exe / in_vgmstream (Winamp) ### test.exe / in_vgmstream (Winamp) / xmp-vgmstream (XMPlay)
**With GCC**: use the *./Makefile* in the root folder, see inside for options. For compilation flags check *test/Makefile.mingw* or *winamp/Makefile.mingw*. **With GCC**: use the *./Makefile* in the root folder, see inside for options. For compilation flags check the *Makefile* in each folder.
You need to manually rebuild if you change a *.h* file (use *make clean*). You need to manually rebuild if you change a *.h* file (use *make clean*).
In Linux you may need to use *Makefile.unix.am* instead, and note that some Linux makefiles aren't up to date. In Linux you may need to use *Makefile.unix.am* instead, and note that some Linux makefiles aren't up to date.
@ -34,24 +34,25 @@ mingw32-make.exe mingw_test -f Makefile ^
``` ```
**With MSVC**: open *./vgmstream.sln* and compile in Visual Studio. **With MSVC**: open *./vgmstream.sln* and compile in Visual Studio.
For XMPlay open *xmp-vgmstream/xmp-vgmstream.sln* instead; FDK-AAC/QAAC/others may be needed (see below).
### foo_input_vgmstream (foobar2000) ### foo_input_vgmstream (foobar2000)
Requires MSVC (foobar/SDK only links to MSVC C++ DLLs) and these dependencies: Requires MSVC (foobar/SDK only links to MSVC C++ DLLs) and these dependencies:
- foobar2000 SDK, in ../foobar/: http://www.foobar2000.org/SDK - foobar2000 SDK, in *(vgmstream)/../foobar/*: http://www.foobar2000.org/SDK
- WTL includes (if needed): http://wtl.sourceforge.net/ - FDK-AAC, in *(vgmstream)/../fdk-aac/*: https://github.com/kode54/fdk-aac
- FDK-AAC, in ../fdk-aac/: https://github.com/kode54/fdk-aac - QAAC, in *(vgmstream)/../qaac/*: https://github.com/kode54/qaac
- QAAC, in ../qaac/: https://github.com/kode54/qaac - WTL91_5321_Final includes (if needed): http://wtl.sourceforge.net/
FDK-AAC/QAAC can be disabled by removing VGM_USE_MP4V2 and VGM_USE_FDKAAC. FDK-AAC/QAAC can be disabled by removing *VGM_USE_MP4V2* and *VGM_USE_FDKAAC*.
Open *./vgmstream.sln* as a base and add *fb2k/foo_input_vgmstream.vcxproj*, which expects the above. Open *./vgmstream.sln* as a base and add *fb2k/foo_input_vgmstream.vcxproj*, which expects the above, and all projects from those dependencies.
You may need to manually add includes and libs from WTL and ../foobar/foobar2000/shared/ in the compiler/linker options.
Depending on your VS version you may need to manually do the following:
- Change each project's compiler version from VS2010 to yours
- For foobar add *(vgmstream)/../WTL91_5321_Final/Include* to the compilers's *additional includes*
- For foobar add *(vgmstream)/../foobar/foobar2000/shared/shared.lib* to the linker's *additional dependencies*
VS2013 may not be compatible with the SDK. VS2013 may not be compatible with the SDK.
### xmp-vgmstream (XMPlay)
Currently only MSVC is supported, though it should be compilable with GCC.
Use *xmp-vgmstream/xmp-vgmstream.sln*; FDK-AAC/QAAC may be needed (see above).
## Development ## Development
@ -93,9 +94,8 @@ For new simple formats, assuming existing layout/coding:
- *src/meta/meta.h*: register parser's init - *src/meta/meta.h*: register parser's init
- *src/vgmstream.h*: register new meta - *src/vgmstream.h*: register new meta
- *src/vgmstream.c*: add parser init to search list, add meta description - *src/vgmstream.c*: add parser init to search list, add meta description
- *winamp/in_vgmstream.c* - *src/formats.c*: add new extension to the format list
*fb2k/in_vgmstream.cpp* *fb2k/in_vgmstream.cpp*: add new extension to the file associations list
*xml-vgmstream/DllMain.c*: add new extension to the format list
- *src/Makefile* - *src/Makefile*
*src/meta/Makefile.unix.am* *src/meta/Makefile.unix.am*
*src/libvgmstream.vcproj/vcxproj/filters*: to compile new (format-name).c parser *src/libvgmstream.vcproj/vcxproj/filters*: to compile new (format-name).c parser

View File

@ -1,4 +1,4 @@
.PHONY: buildfullrelease buildrelease mingw_test mingw_winamp sourceball mingwbin .PHONY: buildfullrelease buildrelease mingw_test mingw_winamp mingw_xmplay sourceball mingwbin
buildfullrelease: clean sourceball mingwbin buildfullrelease: clean sourceball mingwbin
@ -13,8 +13,8 @@ sourceball:
tar cvzf "vgmstream-`./version.sh`.tar.gz" vgmstream-`./version.sh`/* tar cvzf "vgmstream-`./version.sh`.tar.gz" vgmstream-`./version.sh`/*
rm -rf vgmstream-`./version.sh` rm -rf vgmstream-`./version.sh`
mingwbin: mingw_test mingw_winamp mingwbin: mingw_test mingw_winamp mingw_xmplay
zip -FS -j "vgmstream-`./version.sh`-test.zip" COPYING readme.txt test/test.exe winamp/in_vgmstream.dll ext_libs/*.dll zip -FS -j "vgmstream-`./version.sh`-test.zip" COPYING readme.txt test/test.exe winamp/in_vgmstream.dll xmp-vgmstream/xmp-vgmstream.dll ext_libs/*.dll
mingw_test: mingw_test:
$(MAKE) -C test -f Makefile.mingw test.exe $(MAKE) -C test -f Makefile.mingw test.exe
@ -22,10 +22,14 @@ mingw_test:
mingw_winamp: mingw_winamp:
$(MAKE) -C winamp in_vgmstream.dll $(MAKE) -C winamp in_vgmstream.dll
mingw_xmplay:
$(MAKE) -C xmp-vgmstream xmp-vgmstream.dll
clean: clean:
rm -rf vgmstream-* rm -f vgmstream-*.zip
$(MAKE) -C src clean
$(MAKE) -C test clean $(MAKE) -C test clean
$(MAKE) -C test -f Makefile.mingw clean $(MAKE) -C test -f Makefile.mingw clean
$(MAKE) -C winamp clean $(MAKE) -C winamp clean
$(MAKE) -C src clean $(MAKE) -C xmp-vgmstream clean
$(MAKE) -C ext_libs -f Makefile.mingw clean $(MAKE) -C ext_libs -f Makefile.mingw clean

View File

@ -19,8 +19,8 @@
#include <shared.h> #include <shared.h>
extern "C" { extern "C" {
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
#include "../src/util.h"
} }
#include "foo_vgmstream.h" #include "foo_vgmstream.h"
#include "version.h" #include "version.h"
@ -336,297 +336,18 @@ void input_vgmstream::retag(const file_info & p_info,abort_callback & p_abort) {
bool input_vgmstream::g_is_our_content_type(const char * p_content_type) {return false;} bool input_vgmstream::g_is_our_content_type(const char * p_content_type) {return false;}
bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension) { bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension) {
if(!stricmp_utf8(p_extension,"2dx9")) return 1; const char ** ext_list;
if(!stricmp_utf8(p_extension,"2pfs")) return 1; int ext_list_len;
int i;
if(!stricmp_utf8(p_extension,"aaap")) return 1; ext_list = vgmstream_get_formats();
if(!stricmp_utf8(p_extension,"aax")) return 1; ext_list_len = vgmstream_get_formats_length();
if(!stricmp_utf8(p_extension,"acm")) return 1;
if(!stricmp_utf8(p_extension,"adpcm")) return 1;
if(!stricmp_utf8(p_extension,"adm")) return 1;
if(!stricmp_utf8(p_extension,"adp")) return 1;
if(!stricmp_utf8(p_extension,"ads")) return 1;
if(!stricmp_utf8(p_extension,"adx")) return 1;
if(!stricmp_utf8(p_extension,"afc")) return 1;
if(!stricmp_utf8(p_extension,"agsc")) return 1;
if(!stricmp_utf8(p_extension,"ahx")) return 1;
if(!stricmp_utf8(p_extension,"aic")) return 1;
if(!stricmp_utf8(p_extension,"aix")) return 1;
if(!stricmp_utf8(p_extension,"akb")) return 1;
if(!stricmp_utf8(p_extension,"amts")) return 1;
if(!stricmp_utf8(p_extension,"as4")) return 1;
if(!stricmp_utf8(p_extension,"asd")) return 1;
if(!stricmp_utf8(p_extension,"asf")) return 1;
if(!stricmp_utf8(p_extension,"ast")) return 1;
if(!stricmp_utf8(p_extension,"asr")) return 1;
if(!stricmp_utf8(p_extension,"ass")) return 1;
if(!stricmp_utf8(p_extension,"at3")) return 1;
if(!stricmp_utf8(p_extension,"aud")) return 1;
if(!stricmp_utf8(p_extension,"aus")) return 1;
if(!stricmp_utf8(p_extension,"baka")) return 1; for (i=0; i < ext_list_len; i++) {
if(!stricmp_utf8(p_extension,"baf")) return 1; if (!stricmp_utf8(p_extension, ext_list[i]))
if(!stricmp_utf8(p_extension,"bar")) return 1; return 1;
if(!stricmp_utf8(p_extension,"bcstm")) return 1; }
if(!stricmp_utf8(p_extension,"bcwav")) return 1;
if(!stricmp_utf8(p_extension,"bfstm")) return 1;
if(!stricmp_utf8(p_extension,"bfwav")) return 1;
if(!stricmp_utf8(p_extension,"bfwavnsmbu")) return 1;
if(!stricmp_utf8(p_extension,"bg00")) return 1;
if(!stricmp_utf8(p_extension,"bgw")) return 1;
if(!stricmp_utf8(p_extension,"bh2pcm")) return 1;
if(!stricmp_utf8(p_extension,"bmdx")) return 1;
if(!stricmp_utf8(p_extension,"bms")) return 1;
if(!stricmp_utf8(p_extension,"bnk")) return 1;
if(!stricmp_utf8(p_extension,"bns")) return 1;
if(!stricmp_utf8(p_extension,"bnsf")) return 1;
if(!stricmp_utf8(p_extension,"bo2")) return 1;
if(!stricmp_utf8(p_extension,"brstmspm")) return 1;
if(!stricmp_utf8(p_extension,"brstm")) return 1;
if(!stricmp_utf8(p_extension,"btsnd")) return 1;
if(!stricmp_utf8(p_extension,"bvg")) return 1;
if(!stricmp_utf8(p_extension,"caf")) return 1;
if(!stricmp_utf8(p_extension,"capdsp")) return 1;
if(!stricmp_utf8(p_extension,"cbd2")) return 1;
if(!stricmp_utf8(p_extension,"ccc")) return 1;
if(!stricmp_utf8(p_extension,"cfn")) return 1;
if(!stricmp_utf8(p_extension,"ckd")) return 1;
if(!stricmp_utf8(p_extension,"cnk")) return 1;
if(!stricmp_utf8(p_extension,"cps")) return 1;
if(!stricmp_utf8(p_extension,"dcs")) return 1;
if(!stricmp_utf8(p_extension,"de2")) return 1;
if(!stricmp_utf8(p_extension,"ddsp")) return 1;
if(!stricmp_utf8(p_extension,"dmsg")) return 1;
if(!stricmp_utf8(p_extension,"dsp")) return 1;
if(!stricmp_utf8(p_extension,"dspw")) return 1;
if(!stricmp_utf8(p_extension,"dtk")) return 1;
if(!stricmp_utf8(p_extension,"dvi")) return 1;
if(!stricmp_utf8(p_extension,"dxh")) return 1;
if(!stricmp_utf8(p_extension,"eam")) return 1;
if(!stricmp_utf8(p_extension,"emff")) return 1;
if(!stricmp_utf8(p_extension,"enth")) return 1;
if(!stricmp_utf8(p_extension,"fag")) return 1;
if(!stricmp_utf8(p_extension,"filp")) return 1;
if(!stricmp_utf8(p_extension,"fsb")) return 1;
if(!stricmp_utf8(p_extension,"fwav")) return 1;
if(!stricmp_utf8(p_extension,"g1l")) return 1;
if(!stricmp_utf8(p_extension,"gbts")) return 1;
if(!stricmp_utf8(p_extension,"gca")) return 1;
if(!stricmp_utf8(p_extension,"gcm")) return 1;
if(!stricmp_utf8(p_extension,"gcub")) return 1;
if(!stricmp_utf8(p_extension,"gcw")) return 1;
if(!stricmp_utf8(p_extension,"genh")) return 1;
if(!stricmp_utf8(p_extension,"gms")) return 1;
if(!stricmp_utf8(p_extension,"gsb")) return 1;
if(!stricmp_utf8(p_extension, "hca")) return 1;
if(!stricmp_utf8(p_extension,"hgc1")) return 1;
if(!stricmp_utf8(p_extension,"his")) return 1;
if(!stricmp_utf8(p_extension,"hlwav")) return 1;
if(!stricmp_utf8(p_extension,"hps")) return 1;
if(!stricmp_utf8(p_extension,"hsf")) return 1;
if(!stricmp_utf8(p_extension,"hwas")) return 1;
if(!stricmp_utf8(p_extension,"iab")) return 1;
if(!stricmp_utf8(p_extension,"idsp")) return 1;
if(!stricmp_utf8(p_extension,"idvi")) return 1;
if(!stricmp_utf8(p_extension,"ikm")) return 1;
if(!stricmp_utf8(p_extension,"ild")) return 1;
if(!stricmp_utf8(p_extension,"int")) return 1;
if(!stricmp_utf8(p_extension,"isd")) return 1;
if(!stricmp_utf8(p_extension,"isws")) return 1;
if(!stricmp_utf8(p_extension,"ivaud")) return 1;
if(!stricmp_utf8(p_extension,"ivag")) return 1;
if(!stricmp_utf8(p_extension,"ivb")) return 1;
if(!stricmp_utf8(p_extension,"joe")) return 1;
if(!stricmp_utf8(p_extension,"jstm")) return 1;
if(!stricmp_utf8(p_extension,"kces")) return 1;
if(!stricmp_utf8(p_extension,"kcey")) return 1;
if(!stricmp_utf8(p_extension,"khv")) return 1;
if(!stricmp_utf8(p_extension,"kovs")) return 1;
if(!stricmp_utf8(p_extension,"kraw")) return 1;
if(!stricmp_utf8(p_extension,"leg")) return 1;
if(!stricmp_utf8(p_extension,"logg")) return 1;
if(!stricmp_utf8(p_extension,"lpcm")) return 1;
if(!stricmp_utf8(p_extension,"lps")) return 1;
if(!stricmp_utf8(p_extension,"lsf")) return 1;
if(!stricmp_utf8(p_extension,"lwav")) return 1;
if(!stricmp_utf8(p_extension,"matx")) return 1;
if(!stricmp_utf8(p_extension,"mca")) return 1;
if(!stricmp_utf8(p_extension,"mcg")) return 1;
if(!stricmp_utf8(p_extension,"mi4")) return 1;
if(!stricmp_utf8(p_extension,"mib")) return 1;
if(!stricmp_utf8(p_extension,"mic")) return 1;
if(!stricmp_utf8(p_extension,"mihb")) return 1;
if(!stricmp_utf8(p_extension,"mnstr")) return 1;
if(!stricmp_utf8(p_extension,"mpdsp")) return 1;
if(!stricmp_utf8(p_extension,"mpds")) return 1;
if(!stricmp_utf8(p_extension,"msa")) return 1;
if(!stricmp_utf8(p_extension,"msf")) return 1;
if(!stricmp_utf8(p_extension,"mss")) return 1;
if(!stricmp_utf8(p_extension,"msvp")) return 1;
if(!stricmp_utf8(p_extension,"mtaf")) return 1;
if(!stricmp_utf8(p_extension,"mus")) return 1;
if(!stricmp_utf8(p_extension,"musc")) return 1;
if(!stricmp_utf8(p_extension,"musx")) return 1;
if(!stricmp_utf8(p_extension,"mwv")) return 1;
if(!stricmp_utf8(p_extension,"mxst")) return 1;
if(!stricmp_utf8(p_extension,"myspd")) return 1;
if(!stricmp_utf8(p_extension,"ndp")) return 1;
if(!stricmp_utf8(p_extension,"ngca")) return 1;
if(!stricmp_utf8(p_extension,"npsf")) return 1;
if(!stricmp_utf8(p_extension,"nus3bank")) return 1;
if(!stricmp_utf8(p_extension,"nwa")) return 1;
if(!stricmp_utf8(p_extension,"omu")) return 1;
if(!stricmp_utf8(p_extension,"otm")) return 1;
if(!stricmp_utf8(p_extension,"p2bt")) return 1;
if(!stricmp_utf8(p_extension,"p3d")) return 1;
if(!stricmp_utf8(p_extension,"past")) return 1;
if(!stricmp_utf8(p_extension,"pcm")) return 1;
if(!stricmp_utf8(p_extension,"pdt")) return 1;
if(!stricmp_utf8(p_extension,"pnb")) return 1;
if(!stricmp_utf8(p_extension,"pona")) return 1;
if(!stricmp_utf8(p_extension,"pos")) return 1;
if(!stricmp_utf8(p_extension,"ps2stm")) return 1;
if(!stricmp_utf8(p_extension,"psh")) return 1;
if(!stricmp_utf8(p_extension,"psnd")) return 1;
if(!stricmp_utf8(p_extension,"psw")) return 1;
if(!stricmp_utf8(p_extension,"ras")) return 1;
if(!stricmp_utf8(p_extension,"raw")) return 1;
if(!stricmp_utf8(p_extension,"rkv")) return 1;
if(!stricmp_utf8(p_extension,"rnd")) return 1;
if(!stricmp_utf8(p_extension,"rrds")) return 1;
if(!stricmp_utf8(p_extension,"rsd")) return 1;
if(!stricmp_utf8(p_extension,"rsf")) return 1;
if(!stricmp_utf8(p_extension,"rstm")) return 1;
if(!stricmp_utf8(p_extension,"rvws")) return 1;
if(!stricmp_utf8(p_extension,"rwar")) return 1;
if(!stricmp_utf8(p_extension,"rwav")) return 1;
if(!stricmp_utf8(p_extension,"rws")) return 1;
if(!stricmp_utf8(p_extension,"rwsd")) return 1;
if(!stricmp_utf8(p_extension,"rwx")) return 1;
if(!stricmp_utf8(p_extension,"rxw")) return 1;
if(!stricmp_utf8(p_extension,"s14")) return 1;
if(!stricmp_utf8(p_extension,"sab")) return 1;
if(!stricmp_utf8(p_extension,"sad")) return 1;
if(!stricmp_utf8(p_extension,"sap")) return 1;
if(!stricmp_utf8(p_extension,"sc")) return 1;
if(!stricmp_utf8(p_extension,"scd")) return 1;
if(!stricmp_utf8(p_extension,"sck")) return 1;
if(!stricmp_utf8(p_extension,"sd9")) return 1;
if(!stricmp_utf8(p_extension,"sdt")) return 1;
if(!stricmp_utf8(p_extension,"seg")) return 1;
if(!stricmp_utf8(p_extension,"sf0")) return 1;
if(!stricmp_utf8(p_extension,"sfl")) return 1;
if(!stricmp_utf8(p_extension,"sfs")) return 1;
if(!stricmp_utf8(p_extension,"sfx")) return 1;
if(!stricmp_utf8(p_extension,"sgb")) return 1;
if(!stricmp_utf8(p_extension,"sgd")) return 1;
if(!stricmp_utf8(p_extension,"sgx")) return 1;
if(!stricmp_utf8(p_extension,"sl3")) return 1;
if(!stricmp_utf8(p_extension,"sli")) return 1;
if(!stricmp_utf8(p_extension,"smp")) return 1;
if(!stricmp_utf8(p_extension,"smpl")) return 1;
if(!stricmp_utf8(p_extension,"snd")) return 1;
if(!stricmp_utf8(p_extension,"snds")) return 1;
if(!stricmp_utf8(p_extension,"sng")) return 1;
if(!stricmp_utf8(p_extension,"sns")) return 1;
if(!stricmp_utf8(p_extension,"spd")) return 1;
if(!stricmp_utf8(p_extension,"spm")) return 1;
if(!stricmp_utf8(p_extension,"sps")) return 1;
if(!stricmp_utf8(p_extension,"spsd")) return 1;
if(!stricmp_utf8(p_extension,"spw")) return 1;
if(!stricmp_utf8(p_extension,"ss2")) return 1;
if(!stricmp_utf8(p_extension,"ss3")) return 1;
if(!stricmp_utf8(p_extension,"ss7")) return 1;
if(!stricmp_utf8(p_extension,"ssm")) return 1;
if(!stricmp_utf8(p_extension,"sss")) return 1;
if(!stricmp_utf8(p_extension,"ster")) return 1;
if(!stricmp_utf8(p_extension,"stma")) return 1;
if(!stricmp_utf8(p_extension,"str")) return 1;
if(!stricmp_utf8(p_extension,"strm")) return 1;
if(!stricmp_utf8(p_extension,"sts")) return 1;
if(!stricmp_utf8(p_extension,"stx")) return 1;
if(!stricmp_utf8(p_extension,"svag")) return 1;
if(!stricmp_utf8(p_extension,"svs")) return 1;
if(!stricmp_utf8(p_extension,"swav")) return 1;
if(!stricmp_utf8(p_extension,"swd")) return 1;
if(!stricmp_utf8(p_extension,"tec")) return 1;
if(!stricmp_utf8(p_extension,"thp")) return 1;
if(!stricmp_utf8(p_extension,"tk1")) return 1;
if(!stricmp_utf8(p_extension,"tk5")) return 1;
if(!stricmp_utf8(p_extension,"tra")) return 1;
if(!stricmp_utf8(p_extension,"tun")) return 1;
if(!stricmp_utf8(p_extension,"tydsp")) return 1;
if(!stricmp_utf8(p_extension,"um3")) return 1;
if(!stricmp_utf8(p_extension,"vag")) return 1;
if(!stricmp_utf8(p_extension,"vas")) return 1;
if(!stricmp_utf8(p_extension,"vawx")) return 1;
if(!stricmp_utf8(p_extension,"vb")) return 1;
if(!stricmp_utf8(p_extension,"vbk")) return 1;
if(!stricmp_utf8(p_extension,"vgs")) return 1;
if(!stricmp_utf8(p_extension,"vgv")) return 1;
if(!stricmp_utf8(p_extension,"vig")) return 1;
if(!stricmp_utf8(p_extension,"vms")) return 1;
if(!stricmp_utf8(p_extension,"voi")) return 1;
if(!stricmp_utf8(p_extension,"vpk")) return 1;
if(!stricmp_utf8(p_extension,"vs")) return 1;
if(!stricmp_utf8(p_extension,"vsf")) return 1;
if(!stricmp_utf8(p_extension,"waa")) return 1;
if(!stricmp_utf8(p_extension,"wac")) return 1;
if(!stricmp_utf8(p_extension,"wad")) return 1;
if(!stricmp_utf8(p_extension,"wam")) return 1;
if(!stricmp_utf8(p_extension,"wavm")) return 1;
if(!stricmp_utf8(p_extension,"was")) return 1;
if(!stricmp_utf8(p_extension,"wii")) return 1;
if(!stricmp_utf8(p_extension,"wmus")) return 1;
if(!stricmp_utf8(p_extension,"wp2")) return 1;
if(!stricmp_utf8(p_extension,"wpd")) return 1;
if(!stricmp_utf8(p_extension,"wsd")) return 1;
if(!stricmp_utf8(p_extension,"wsi")) return 1;
if(!stricmp_utf8(p_extension,"wvs")) return 1;
if(!stricmp_utf8(p_extension,"xa")) return 1;
if(!stricmp_utf8(p_extension,"xa2")) return 1;
if(!stricmp_utf8(p_extension,"xa30")) return 1;
if(!stricmp_utf8(p_extension,"xau")) return 1;
if(!stricmp_utf8(p_extension,"xma")) return 1;
if(!stricmp_utf8(p_extension,"xma2")) return 1;
if(!stricmp_utf8(p_extension,"xmu")) return 1;
if(!stricmp_utf8(p_extension,"xnb")) return 1;
if(!stricmp_utf8(p_extension,"xsf")) return 1;
if(!stricmp_utf8(p_extension,"xss")) return 1;
if(!stricmp_utf8(p_extension,"xvag")) return 1;
if(!stricmp_utf8(p_extension,"xvas")) return 1;
if(!stricmp_utf8(p_extension,"xwav")) return 1;
if(!stricmp_utf8(p_extension,"xwb")) return 1;
if(!stricmp_utf8(p_extension,"xwm")) return 1;
if(!stricmp_utf8(p_extension,"ydsp")) return 1;
if(!stricmp_utf8(p_extension,"ymf")) return 1;
if(!stricmp_utf8(p_extension,"zsd")) return 1;
if(!stricmp_utf8(p_extension,"zwdsp")) return 1;
if(!stricmp_utf8(p_extension,"vgmstream")) return 1;
return 0; return 0;
} }
@ -676,7 +397,10 @@ static input_singletrack_factory_t<input_vgmstream> g_input_vgmstream_factory;
DECLARE_COMPONENT_VERSION(APP_NAME,PLUGIN_VERSION,PLUGIN_DESCRIPTION); DECLARE_COMPONENT_VERSION(APP_NAME,PLUGIN_VERSION,PLUGIN_DESCRIPTION);
VALIDATE_COMPONENT_FILENAME("foo_input_vgmstream.dll"); VALIDATE_COMPONENT_FILENAME("foo_input_vgmstream.dll");
// File types go down here (and in the large chunk of IFs above // Registered file types, to associate an extension with foobar2000 in Windows.
// Accepted types go in input_vgmstream::g_is_our_path; both lists don't need to match.
// todo do we really want to associate every single vgmstream format?
//
// these are declared statically, and if anyone has a better idea i'd like to hear it - josh. // these are declared statically, and if anyone has a better idea i'd like to hear it - josh.
DECLARE_MULTIPLE_FILE_TYPE("2DX9 Audio File (*.2DX9)", 2dx9); DECLARE_MULTIPLE_FILE_TYPE("2DX9 Audio File (*.2DX9)", 2dx9);
DECLARE_MULTIPLE_FILE_TYPE("2PFS Audio File (*.2PFS)", 2pfs); DECLARE_MULTIPLE_FILE_TYPE("2PFS Audio File (*.2PFS)", 2pfs);

View File

@ -311,7 +311,7 @@ META_OBJS=meta/adx_header.o \
EXT_LIBS = ../ext_libs/clHCA.o EXT_LIBS = ../ext_libs/clHCA.o
OBJECTS=vgmstream.o streamfile.o util.o header.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) $(EXT_LIBS) OBJECTS=vgmstream.o streamfile.o util.o header.o formats.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) $(EXT_LIBS)
libvgmstream.a: $(OBJECTS) libvgmstream.a: $(OBJECTS)
$(AR) crs libvgmstream.a $(OBJECTS) $(AR) crs libvgmstream.a $(OBJECTS)

View File

@ -4,7 +4,7 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix AM_MAKEFLAGS=-f Makefile.unix
libvgmstream_la_LDFLAGS = coding/libcoding.la layout/liblayout.la meta/libmeta.la libvgmstream_la_LDFLAGS = coding/libcoding.la layout/liblayout.la meta/libmeta.la
libvgmstream_la_SOURCES = vgmstream.c util.c streamfile.c header.c ../ext_libs/clHCA.c libvgmstream_la_SOURCES = vgmstream.c util.c streamfile.c header.c formats.c ../ext_libs/clHCA.c
SUBDIRS = coding layout meta SUBDIRS = coding layout meta

335
src/formats.c Normal file
View File

@ -0,0 +1,335 @@
#include "formats.h"
//#define VGM_REGISTER_TYPE(extension) ...
//#define VGM_REGISTER_TYPE_COMMON(extension) ... /* for common extensions like aiff */
/* some extensions could be #ifdef but no really needed */
/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */
static const char* extension_list[] = {
"2dx9",
"2pfs",
"aa3", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"aaap",
"aax",
//"ac3", //FFmpeg, not parsed //common?
"acm",
"adm",
"adp",
"adpcm",
"ads",
"adx",
"afc",
"agsc",
"ahx",
"aifc",
"aifcl",
//"aiff", //common
"aix",
"akb", //AAC
"amts",
"as4",
"asd",
"asf",
"asr",
"ass",
"ast",
"at3",
"aud",
"aus",
"b1s",
"baf",
"baka",
"bar",
"bcstm",
"bcwav",
"bdsp",
"bfstm",
"bfwav",
"bfwavnsmbu",
"bg00",
"bgw",
"bh2pcm",
"bmdx",
"bms",
"bnk",
"bns",
"bnsf",
"bo2",
"brstm",
"brstmspm",
"btsnd",
"bvg",
"caf",
"capdsp",
"cbd2",
"ccc",
"cfn",
"ckd",
"cnk",
"cps",
"dcs",
"ddsp",
"de2",
"dmsg",
"dsp",
"dspw",
"dtk",
"dvi",
"dxh",
"eam",
"emff",
"enth",
"fag",
"ffw",
"filp",
"fsb",
"fwav",
"g1l",
"gbts",
"gca",
"gcm",
"gcub",
"gcw",
"genh",
"gms",
"gsb",
"hca",
"hgc1",
"his",
"hlwav",
"hps",
"hsf",
"hwas",
"iab",
"iadp",
"idsp",
"idvi",
"ikm",
"ild",
"int",
"isd",
"isws",
"ivaud",
"ivag",
"ivb",
"joe",
"jstm",
"kces",
"kcey",
"khv",
"kovs",
"kraw",
"leg",
"logg",
"lpcm",
"lps",
"lsf",
"lwav",
"matx",
"mca",
"mcg",
"mi4",
"mib",
"mic",
"mihb",
"mnstr",
"mpdsp",
"mpds",
"msa",
"msf",
"mss",
"msvp",
"mtaf",
"mus",
"musc",
"musx",
"mwv",
"mxst",
"myspd",
"ndp",
"ngca",
"npsf",
"nus3bank", //todo not existing?
"nwa",
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"omu",
"otm",
"p2bt",
"p3d",
"past",
"pcm",
"pdt",
"pnb",
"pona",
"pos",
"ps2stm",
"psh",
"psnd",
"psw",
"ras",
"raw",
"rkv",
"rnd",
"rrds",
"rsd",
"rsf",
"rstm",
"rvws",
"rwar",
"rwav",
"rws",
"rwsd",
"rwx",
"rxw",
"s14",
"sab",
"sad",
"sap",
"sc",
"scd",
"sck",
"sd9",
"sdt",
"seg",
"sf0",
"sfl",
"sfs",
"sfx",
"sgb",
"sgd",
"sgx",
"sl3",
"sli",
"smp",
"smpl",
"snd",
"snds",
"sng",
"sns",
"spd",
"spm",
"sps",
"spsd",
"spw",
"ss2",
"ss3",
"ss7",
"ssm",
"sss",
"ster",
"sth",
//"stm", //common
"stma",
"str",
"strm",
"sts",
"stx",
"svag",
"svs",
"swav",
"swd",
"tec",
"thp",
"tk1",
"tk5",
"tra",
"tun",
"tydsp",
"um3",
"vag",
"vas",
"vawx",
"vb",
"vbk",
"vgs",
"vgv",
"vig",
"vms",
"voi",
"vpk",
"vs",
"vsf",
"waa",
"wac",
"wad",
"wam",
"was",
"wavm",
"wb",
"wii",
"wmus",
"wp2",
"wpd",
"wsd",
"wsi",
"wvs",
"xa",
"xa2",
"xa30",
"xag",
"xau",
"xma",
"xma2",
"xmu",
"xnb",
"xsf",
"xss",
"xvag",
"xvas",
"xwav",
"xwb",
"xwm", //FFmpeg, not parsed (XWMA)
"xwma", //FFmpeg, not parsed (XWMA)
"ydsp",
"ymf",
"zsd",
"zwdsp",
"vgmstream"
//, NULL //end mark
};
/**
* List of supported formats.
*
* For plugins that need to know (test.exe doesn't use it)
*/
const char ** vgmstream_get_formats() {
return extension_list;
}
/**
* Number of elements in the list.
*/
int vgmstream_get_formats_length() {
return sizeof(extension_list) / sizeof(char*);
}

15
src/formats.h Normal file
View File

@ -0,0 +1,15 @@
/*
* formats.h - utils to parse supported formats
*/
#ifndef _FORMATS_H_
#define _FORMATS_H_
/* rough number of chars counting all extensions (actually <1500 and extra space) */
#define VGM_EXTENSION_LIST_CHAR_SIZE 2000
const char ** vgmstream_get_formats();
int vgmstream_get_formats_length();
#endif /* _FORMATS_H_ */

View File

@ -147,6 +147,10 @@
Filter="h;hpp;hxx;hm;inl;inc;xsd" Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
> >
<File
RelativePath=".\formats.h"
>
</File>
<File <File
RelativePath=".\header.h" RelativePath=".\header.h"
> >
@ -173,6 +177,10 @@
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
> >
<File
RelativePath=".\formats.c"
>
</File>
<File <File
RelativePath=".\header.c" RelativePath=".\header.c"
> >

View File

@ -82,6 +82,7 @@
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\ext_includes\clHCA.h" /> <ClInclude Include="..\ext_includes\clHCA.h" />
<ClInclude Include="formats.h" />
<ClInclude Include="header.h" /> <ClInclude Include="header.h" />
<ClInclude Include="streamfile.h" /> <ClInclude Include="streamfile.h" />
<ClInclude Include="streamtypes.h" /> <ClInclude Include="streamtypes.h" />
@ -139,6 +140,7 @@
<ClCompile Include="meta\wii_ras.c" /> <ClCompile Include="meta\wii_ras.c" />
<ClCompile Include="meta\wpd.c" /> <ClCompile Include="meta\wpd.c" />
<ClCompile Include="meta\x360_tra.c" /> <ClCompile Include="meta\x360_tra.c" />
<ClCompile Include="formats.c" />
<ClCompile Include="header.c" /> <ClCompile Include="header.c" />
<ClCompile Include="streamfile.c" /> <ClCompile Include="streamfile.c" />
<ClCompile Include="util.c" /> <ClCompile Include="util.c" />

View File

@ -47,6 +47,9 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="formats.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="header.h"> <ClInclude Include="header.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -85,6 +88,9 @@
</ClInclude> </ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="formats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="header.c"> <ClCompile Include="header.c">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>

View File

@ -102,9 +102,12 @@ typedef struct {
meta_t meta_type; meta_t meta_type;
layout_t layout_type; layout_t layout_type;
// XOR setup with a single byte (SCD) /* XOR setup (SCD) */
unsigned char scd_xor; int decryption_enabled;
off_t scd_xor_len; void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
uint8_t scd_xor;
off_t scd_xor_length;
} vgm_vorbis_info_t; } vgm_vorbis_info_t;
VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf); VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const char * filename, ov_callbacks *callbacks, off_t other_header_bytes, const vgm_vorbis_info_t *vgm_inf);

View File

@ -92,14 +92,9 @@ static size_t read_func_scd(void *ptr, size_t size, size_t nmemb, void * datasou
items_read = bytes_read / size; items_read = bytes_read / size;
/* first bytes are xor'd with a constant byte */ /* may be encrypted */
if (ov_streamfile->offset < ov_streamfile->scd_xor_len) { if (ov_streamfile->decryption_enabled) {
int num_crypt = ov_streamfile->scd_xor_len-ov_streamfile->offset; ov_streamfile->decryption_callback(ptr, size, nmemb, ov_streamfile, bytes_read);
int i;
if (num_crypt > bytes_read) num_crypt=bytes_read;
for (i=0;i<num_crypt;i++)
((uint8_t*)ptr)[i] ^= ov_streamfile->scd_xor;
} }
ov_streamfile->offset += items_read * size; ov_streamfile->offset += items_read * size;
@ -281,7 +276,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
default_callbacks.close_func = close_func; default_callbacks.close_func = close_func;
default_callbacks.tell_func = tell_func; default_callbacks.tell_func = tell_func;
if (vgm_inf->scd_xor != 0) { if (vgm_inf->decryption_enabled) {
default_callbacks.read_func = read_func_scd; default_callbacks.read_func = read_func_scd;
} }
@ -292,8 +287,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
temp_streamfile.offset = 0; temp_streamfile.offset = 0;
temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile); temp_streamfile.size = get_streamfile_size(temp_streamfile.streamfile);
temp_streamfile.other_header_bytes = other_header_bytes; temp_streamfile.other_header_bytes = other_header_bytes;
temp_streamfile.decryption_enabled = vgm_inf->decryption_enabled;
temp_streamfile.decryption_callback = vgm_inf->decryption_callback;
temp_streamfile.scd_xor = vgm_inf->scd_xor; temp_streamfile.scd_xor = vgm_inf->scd_xor;
temp_streamfile.scd_xor_len = vgm_inf->scd_xor_len; temp_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
/* can we open this as a proper ogg vorbis file? */ /* can we open this as a proper ogg vorbis file? */
memset(&temp_ovf, 0, sizeof(temp_ovf)); memset(&temp_ovf, 0, sizeof(temp_ovf));
@ -314,8 +311,10 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, const ch
data->ov_streamfile.offset = 0; data->ov_streamfile.offset = 0;
data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile); data->ov_streamfile.size = get_streamfile_size(data->ov_streamfile.streamfile);
data->ov_streamfile.other_header_bytes = other_header_bytes; data->ov_streamfile.other_header_bytes = other_header_bytes;
data->ov_streamfile.decryption_enabled = vgm_inf->decryption_enabled;
data->ov_streamfile.decryption_callback = vgm_inf->decryption_callback;
data->ov_streamfile.scd_xor = vgm_inf->scd_xor; data->ov_streamfile.scd_xor = vgm_inf->scd_xor;
data->ov_streamfile.scd_xor_len = vgm_inf->scd_xor_len; data->ov_streamfile.scd_xor_length = vgm_inf->scd_xor_length;
/* open the ogg vorbis file for real */ /* open the ogg vorbis file for real */
if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL, if (ov_open_callbacks(&data->ov_streamfile, &data->ogg_vorbis_file, NULL,

View File

@ -20,12 +20,40 @@ typedef struct _SCDINTSTREAMFILE
static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size); static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * filename, off_t start_offset, off_t interleave_block_size, off_t stride_size, size_t total_size);
/* V3 decryption table found in the .exe */
static const uint8_t scd_ogg_v3_lookuptable[256] = { /* FF XIV Heavensward */
0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F
0x32, 0x52, 0x16, 0x1B, 0x3C, 0xA1, 0x54, 0x7B, 0x1B, 0x97, 0xA6, 0x93, 0x1A, 0x4B, 0xAA, 0xA6, // 10-1F
0x7A, 0x7B, 0x1B, 0x97, 0xA6, 0xF7, 0x02, 0xBB, 0xAA, 0xA6, 0xBB, 0xF7, 0x2A, 0x51, 0xBE, 0x03, // 20-2F
0xF4, 0x2A, 0x51, 0xBE, 0x03, 0xF4, 0x2A, 0x51, 0xBE, 0x12, 0x06, 0x56, 0x27, 0x32, 0x32, 0x36, // 30-3F
0x32, 0xB2, 0x1A, 0x3B, 0xBC, 0x91, 0xD4, 0x7B, 0x58, 0xFC, 0x0B, 0x55, 0x2A, 0x15, 0xBC, 0x40, // 40-4F
0x92, 0x0B, 0x5B, 0x7C, 0x0A, 0x95, 0x12, 0x35, 0xB8, 0x63, 0xD2, 0x0B, 0x3B, 0xF0, 0xC7, 0x14, // 50-5F
0x51, 0x5C, 0x94, 0x86, 0x94, 0x59, 0x5C, 0xFC, 0x1B, 0x17, 0x3A, 0x3F, 0x6B, 0x37, 0x32, 0x32, // 60-6F
0x30, 0x32, 0x72, 0x7A, 0x13, 0xB7, 0x26, 0x60, 0x7A, 0x13, 0xB7, 0x26, 0x50, 0xBA, 0x13, 0xB4, // 70-7F
0x2A, 0x50, 0xBA, 0x13, 0xB5, 0x2E, 0x40, 0xFA, 0x13, 0x95, 0xAE, 0x40, 0x38, 0x18, 0x9A, 0x92, // 80-8F
0xB0, 0x38, 0x00, 0xFA, 0x12, 0xB1, 0x7E, 0x00, 0xDB, 0x96, 0xA1, 0x7C, 0x08, 0xDB, 0x9A, 0x91, // 90-9F
0xBC, 0x08, 0xD8, 0x1A, 0x86, 0xE2, 0x70, 0x39, 0x1F, 0x86, 0xE0, 0x78, 0x7E, 0x03, 0xE7, 0x64, // A0-AF
0x51, 0x9C, 0x8F, 0x34, 0x6F, 0x4E, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, 0x41, 0xFC, 0x0B, 0xD5, 0xAE, // B0-BF
0x41, 0xFC, 0x3B, 0x70, 0x71, 0x64, 0x33, 0x32, 0x12, 0x32, 0x32, 0x36, 0x70, 0x34, 0x2B, 0x56, // C0-CF
0x22, 0x70, 0x3A, 0x13, 0xB7, 0x26, 0x60, 0xBA, 0x1B, 0x94, 0xAA, 0x40, 0x38, 0x00, 0xFA, 0xB2, // D0-DF
0xE2, 0xA2, 0x67, 0x32, 0x32, 0x12, 0x32, 0xB2, 0x32, 0x32, 0x32, 0x32, 0x75, 0xA3, 0x26, 0x7B, // E0-EF
0x83, 0x26, 0xF9, 0x83, 0x2E, 0xFF, 0xE3, 0x16, 0x7D, 0xC0, 0x1E, 0x63, 0x21, 0x07, 0xE3, 0x01, // F0-FF
};
static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; char filename[PATH_LIMIT];
off_t start_offset, meta_offset_offset, meta_offset, post_meta_offset; off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset, stream_size;
int headers_entries;
int32_t loop_start, loop_end; int32_t loop_start, loop_end;
int target_stream = 1; /* N=Nth stream, 0=auto (first) */
int loop_flag = 0; int loop_flag = 0;
int channel_count; int channel_count;
int codec_id; int codec_id;
@ -42,55 +70,75 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
if (read_32bitBE(0,streamFile) != 0x53454442) goto fail; if (read_32bitBE(0,streamFile) != 0x53454442) goto fail;
/* SSCF */ /* SSCF */
if (read_32bitBE(4,streamFile) != 0x53534346) goto fail; if (read_32bitBE(4,streamFile) != 0x53534346) goto fail;
if (read_32bitBE(8,streamFile) == 2 ||
read_32bitBE(8,streamFile) == 3) { /** main header section **/
/* version 2 BE, as seen in FFXIII demo for PS3 */ if (read_32bitBE(8,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */
/* version 3 BE, as seen in FFXIII for PS3 */ read_32bitBE(8,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */
read_32bit = read_32bitBE; read_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
//size_offset = 0x14; //size_offset = 0x14;
meta_offset_offset = 0x40 + read_16bit(0xe,streamFile); } else if (read_32bitLE(8,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */
} else if (read_32bitLE(8,streamFile) == 3 ||
read_32bitLE(8,streamFile) == 2) { read_32bitLE(8,streamFile) == 2) {
/* version 2/3 LE, as seen in FFXIV for ?? */
read_32bit = read_32bitLE; read_32bit = read_32bitLE;
read_16bit = read_16bitLE; read_16bit = read_16bitLE;
//size_offset = 0x10; //size_offset = 0x10;
meta_offset_offset = 0x40 + read_16bit(0xe,streamFile);
} else goto fail; } else goto fail;
/* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */ /* 0xc: probably 00=LE, 01=BE */
/* 0xd: unk (always 0x04) */
tables_offset = read_16bit(0xe,streamFile);
#if 0 #if 0
/* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */
/* check file size with header value */ /* check file size with header value */
if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile)) if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile))
goto fail; goto fail;
#endif #endif
meta_offset = read_32bit(meta_offset_offset,streamFile); /** offset tables **/
/* 0x00: table1_unknown entries */
/* 0x02: table2_headers entries */
/* 0x04: table3_unknown entries */
/* 0x06: unknown (varies) */
/* 0x08: table1_unknown start offset */
/* 0x0c: table2_headers start offset */
/* 0x10: table3_unknown start offset */
/* 0x14: unknown (0x0) */
/* 0x18: unknown offset */
/* 0x1c: unknown (0x0) */
headers_entries = read_16bit(tables_offset+0x02,streamFile);
VGM_ASSERT(headers_entries > 1, "SCD: multiple streams found (%i entries)\n", headers_entries);
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
if (target_stream > headers_entries) goto fail;
headers_offset = read_32bit(tables_offset+0x0c,streamFile);
/** header table entries (each is an uint32_t offset to stream header) **/
meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile);
/** stream header **/
stream_size = read_32bit(meta_offset + 0x0, streamFile);
channel_count = read_32bit(meta_offset+4,streamFile);
/* 0x8 sample rate */
codec_id = read_32bit(meta_offset+0xc,streamFile);
/* check that chunk size equals stream size (?) */
loop_start = read_32bit(meta_offset+0x10,streamFile); loop_start = read_32bit(meta_offset+0x10,streamFile);
loop_end = read_32bit(meta_offset+0x14,streamFile); loop_end = read_32bit(meta_offset+0x14,streamFile);
loop_flag = (loop_end > 0); loop_flag = (loop_end > 0);
channel_count = read_32bit(meta_offset+4,streamFile);
codec_id = read_32bit(meta_offset+0xc,streamFile);
post_meta_offset = meta_offset + 0x20; post_meta_offset = meta_offset + 0x20;
/* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks /* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks before anything else */
before anything else */
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile); aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
for (; aux_chunk_count > 0; aux_chunk_count --) for (; aux_chunk_count > 0; aux_chunk_count--) {
{
/* skip aux chunks */ /* skip aux chunks */
/*printf("skipping %08x\n", read_32bitBE(post_meta_offset, streamFile));*/
post_meta_offset += read_32bit(post_meta_offset+4,streamFile); post_meta_offset += read_32bit(post_meta_offset+4,streamFile);
} }
start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile); start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile);
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS
if (codec_id == 0x6) if (codec_id == 0x6)
{ {
@ -130,18 +178,28 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
// failed with Ogg, try deobfuscating header // failed with Ogg, try deobfuscating header
{ {
// skip chunks before xor_byte // skip chunks before xor_byte
unsigned char xor_byte; uint8_t xor_version, xor_byte;
xor_version = read_8bit(post_meta_offset + 0, streamFile);
xor_byte = read_8bit(post_meta_offset + 2, streamFile); xor_byte = read_8bit(post_meta_offset + 2, streamFile);
if (xor_byte == 0) { if (xor_byte == 0) {
return NULL; return NULL;
} }
if (xor_version <= 2) {
inf.decryption_enabled = 1;
inf.decryption_callback = scd_ogg_decrypt_v2_callback;
inf.scd_xor = xor_byte; inf.scd_xor = xor_byte;
inf.scd_xor_len = vorb_header_size; inf.scd_xor_length = vorb_header_size; /* header is XOR'ed */
} else if (xor_version == 3) {
inf.decryption_enabled = 1;
inf.decryption_callback = scd_ogg_decrypt_v3_callback;
inf.scd_xor = stream_size & 0xFF; /* xor_byte is not used? */
inf.scd_xor_length = stream_size; /* full file is XOR'ed */
}
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf); result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
/* always? */
return result; return result;
} }
} }
@ -160,7 +218,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
/* PCM */ /* PCM */
vgmstream->coding_type = coding_PCM16LE_int; vgmstream->coding_type = coding_PCM16LE_int;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(meta_offset+0,streamFile) / 2 / channel_count; vgmstream->num_samples = stream_size / 2 / channel_count;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = loop_start / 2 / channel_count; vgmstream->loop_start_sample = loop_start / 2 / channel_count;
@ -175,6 +233,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
struct mpg123_frameinfo mi; struct mpg123_frameinfo mi;
coding_t ct; coding_t ct;
/* Drakengard 3, some Kingdom Hearts */
if (vgmstream->sample_rate == 47999) if (vgmstream->sample_rate == 47999)
vgmstream->sample_rate = 48000; vgmstream->sample_rate = 48000;
if (vgmstream->sample_rate == 44099) if (vgmstream->sample_rate == 44099)
@ -189,7 +248,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->coding_type = ct; vgmstream->coding_type = ct;
vgmstream->layout_type = layout_mpeg; vgmstream->layout_type = layout_mpeg;
if (mi.vbr != MPG123_CBR) goto fail; if (mi.vbr != MPG123_CBR) goto fail;
vgmstream->num_samples = mpeg_bytes_to_samples(read_32bit(meta_offset+0,streamFile), &mi); vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, &mi);
vgmstream->num_samples -= vgmstream->num_samples%576; vgmstream->num_samples -= vgmstream->num_samples%576;
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi); vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi);
@ -206,7 +265,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_MSADPCM; vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile); vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile);
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bit(meta_offset+0,streamFile), vgmstream->interleave_block_size, vgmstream->channels); vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
if (loop_flag) { if (loop_flag) {
vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels); vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels);
@ -307,6 +366,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
break; break;
#endif #endif
default: default:
VGM_LOG("SCD: unknown codec_id %x\n", codec_id);
goto fail; goto fail;
} }
@ -460,3 +520,43 @@ static STREAMFILE *open_scdint_with_STREAMFILE(STREAMFILE *file, const char * fi
return &scd->sf; return &scd->sf;
} }
static void scd_ogg_decrypt_v2_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) {
ogg_vorbis_streamfile * ov_streamfile = (ogg_vorbis_streamfile*)datasource;
/* header is XOR'd with a constant byte */
if (ov_streamfile->offset < ov_streamfile->scd_xor_length) {
int i, num_crypt;
num_crypt = ov_streamfile->scd_xor_length - ov_streamfile->offset;
if (num_crypt > bytes_read)
num_crypt = bytes_read;
for (i = 0; i < num_crypt; i++) {
((uint8_t*)ptr)[i] ^= (uint8_t)ov_streamfile->scd_xor;
}
}
}
static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read) {
ogg_vorbis_streamfile *ov_streamfile = (ogg_vorbis_streamfile*)datasource;
/* file is XOR'd with a table (algorithm and table by Ioncannon) */
if (ov_streamfile->offset < ov_streamfile->scd_xor_length) {
int i, num_crypt;
uint8_t byte1, byte2, xorByte;
num_crypt = bytes_read;
byte1 = ov_streamfile->scd_xor & 0x7F;
byte2 = ov_streamfile->scd_xor & 0x3F;
for (i = 0; i < num_crypt; i++) {
xorByte = scd_ogg_v3_lookuptable[(byte2 + ov_streamfile->offset + i) & 0xFF];
xorByte &= 0xFF;
xorByte ^= ((uint8_t*)ptr)[i];
xorByte ^= byte1;
((uint8_t*)ptr)[i] = (uint8_t)xorByte;
}
}
}

View File

@ -175,42 +175,3 @@ void concatn(int length, char * dst, const char * src) {
dst[i]=src[j]; dst[i]=src[j];
dst[i]='\0'; 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';
}
/* length is maximum length of dst. dst will always be double-null-terminated if
* length > 1, if src won't fit, truncate */
void concatn_fitting_doublenull(int length, char * dst, const char * src) {
int i,j,k;
if (length <= 1) return;
for (i=0;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++;
k = i;
for (j=0;i<length-2 && (src[j] || src[j+1]);i++,j++) dst[i]=src[j];
if (i == length-2 && (src[j] || src[j+1])) {
i = k;
}
dst[i]='\0';
dst[i+1]='\0';
}

View File

@ -69,8 +69,6 @@ void make_smpl_chunk(uint8_t * buf, int32_t loop_start, int32_t loop_end);
void swap_samples_le(sample *buf, int count); void swap_samples_le(sample *buf, int count);
void concatn(int length, char * dst, const char * src); void concatn(int length, char * dst, const char * src);
void concatn_doublenull(int length, char * dst, const char * src);
void concatn_fitting_doublenull(int length, char * dst, const char * src);
/* Simple stdout logging for debugging and regression testing purposes. /* Simple stdout logging for debugging and regression testing purposes.

View File

@ -739,9 +739,12 @@ typedef struct {
ogg_int64_t size; ogg_int64_t size;
ogg_int64_t other_header_bytes; ogg_int64_t other_header_bytes;
// XOR setup with a single byte (SCD) /* XOR setup (SCD) */
unsigned char scd_xor; int decryption_enabled;
ogg_int64_t scd_xor_len; void (*decryption_callback)(void *ptr, size_t size, size_t nmemb, void *datasource, int bytes_read);
uint8_t scd_xor;
off_t scd_xor_length;
} ogg_vorbis_streamfile; } ogg_vorbis_streamfile;
typedef struct { typedef struct {

View File

@ -13,9 +13,11 @@
#include <commctrl.h> #include <commctrl.h>
#include <stdio.h> #include <stdio.h>
#include <io.h> #include <io.h>
#include <string.h>
#include <ctype.h>
#include "../src/formats.h"
#include "../src/vgmstream.h" #include "../src/vgmstream.h"
#include "../src/util.h"
#include "in2.h" #include "in2.h"
#include "wa_ipc.h" #include "wa_ipc.h"
#include "resource.h" #include "resource.h"
@ -71,308 +73,14 @@ int decode_pos_samples = 0;
int stream_length_samples = 0; int stream_length_samples = 0;
int fade_samples = 0; int fade_samples = 0;
#define EXTENSION_LIST_SIZE 10240 /* Winamp Play extension list, needed to accept/play and associate extensions in Windows */
#define EXTENSION_LIST_SIZE VGM_EXTENSION_LIST_CHAR_SIZE * 6
char working_extension_list[EXTENSION_LIST_SIZE] = {0}; char working_extension_list[EXTENSION_LIST_SIZE] = {0};
char * extension_list[] = { #define EXT_BUFFER_SIZE 200
"2dx9\0""2DX9 Audio File (*.2DX9)\0", static void add_extension(int length, char * dst, const char * src);
"2pfs\0""2PFS Audio File (*.2PFS)\0", static void build_extension_list();
"aax\0AAX Audio File (*.AAX)\0",
"aaap\0AAAP Audio File (*.AAAP)\0",
"aax\0AAX Audio File (*.AAX)\0",
"acm\0ACM Audio File (*.ACM)\0",
"adm\0ADM Audio File (*.ADM)\0",
"adpcm\0ADPCM Audio File (*.ADPCM)\0",
"adp\0ADP Audio File (*.ADP)\0",
"ads\0PS2 ADS Audio File (*.ADS)\0",
"adx\0ADX Audio File (*.ADX)\0",
"afc\0AFC Audio File (*.AFC)\0",
"agsc\0AGSC Audio File (*.AGSC)\0",
"ahx\0AHX Audio File (*.AHX)\0",
"aifc\0AIFC Audio File (*.AIFC)\0",
"aix\0AIX Audio File (*.AIX)\0",
"amts\0AMTS Audio File (*.AMTS)\0",
"as4\0AS4 Audio File (*.AS4)\0",
"asd\0ASD Audio File (*.ASD)\0",
"asf\0ASF Audio File (*.ASF)\0",
"ast\0AST Audio File (*.AST)\0",
"asr\0ASR Audio File (*.ASR)\0",
"ass\0ASS Audio File (*.ASS)\0",
"at3\0AT3 Audio File (*.AT3)\0",
"aud\0AUD Audio File (*.AUD)\0",
"aus\0AUS Audio File (*.AUS)\0",
"b1s\0B1S Audio File (*.B1S)\0",
"baka\0BAKA Audio File (*.BAKA)\0",
"baf\0BAF Audio File (*.BAF)\0",
"bar\0BAR Audio File (*.BAR)\0",
"bcstm\0BCSTM Audio File (*.BCSTM)\0",
"bcwav\0BCWAV (*.BCWAV)\0",
"bdsp\0BDSP Audio File (*.BDSP)\0",
"bfstm\0BFSTM Audio File (*.BFSTM)\0",
"bfwav;bfwavnsmbu;fwav\0BFWAV Audio File (*.BFWAV)\0",
"bg00\0BG00 Audio File (*.BG00)\0",
"bgw\0BGW Audio File (*.BGW)\0",
"bh2pcm\0BH2PCM Audio File (*.BH2PCM)\0",
"bmdx\0BMDX Audio File (*.BMDX)\0",
"bms\0BMS (*.BMS)\0",
"bnk\0BNK Audio File (*.BNK)\0",
"bns\0BNS Audio File (*.BNS)\0",
"bnsf\0BNSF Audio File (*.BNSF)\0",
"bo2\0BO2 Audio File (*.BO2)\0",
"brstm;brstmspm\0BRSTM Audio File (*.BRSTM)\0",
"btsnd\0BTSND Audio File (*.BTSND)\0",
"bvg\0BVG Audio File (*.BVG)\0",
"caf\0CAF Audio File (*.CAF)\0",
"capdsp\0CAPDSP Audio File (*.CAPDSP)\0", /* Capcom custom coefs */
"cbd2\0CBD2 Audio File (*.CBD2)\0",
"ccc\0CCC Audio File (*.CCC)\0",
"cfn\0CFN Audio File (*.CFN)\0",
"ckd\0CKD Audio File (*.CKD)\0",
"cnk\0CNK Audio File (*.CNK)\0",
"cps\0CPS Audio File (*.CPS)\0",
"dcs\0DCS Audio File (*.DCS)\0",
"de2\0DE2 Audio File (*.DE2)\0",
"ddsp\0DDSP Audio File (*.DDSP)\0",
"dmsg\0DMSG Audio File (*.DMSG)\0",
"dsp\0DSP Audio File (*.DSP)\0",
"dspw\0DSPW Audio File (*.DSPW)\0",
"dtk\0DTK Audio File (*.DTK)\0",
"dvi\0DVI Audio File (*.DVI)\0",
"dxh\0DXH Audio File (*.DXH)\0",
"eam\0EAM Audio File (*.EAM)\0",
"emff\0EMFF Audio File (*.EMFF)\0",
"enth\0ENTH Audio File (*.ENTH)\0",
"fag\0FAG Audio File (*.FAG)\0",
"ffw\0FFW Audio File (*.FFW)\0",
"filp\0FILP Audio File (*.FILP)\0",
"fsb\0FSB Audio File (*.FSB)\0",
"g1l\0G1L Audio File (*.G1L)\0",
"gbts\0GBTS Audio File (*.GBTS)\0",
"gca\0GCA Audio File (*.GCA)\0",
"gcm\0GCM Audio File (*.GCM)\0",
"gcub\0GCUB Audio File (*.GCUB)\0",
"gcw\0GCW Audio File (*.GCW)\0",
"genh\0GENH Audio File (*.GENH)\0",
"gms\0GMS Audio File (*.GMS)\0",
"gsb\0GSB Audio File (*.GSB)\0",
"hca\0HCA Audio File (*.HCA)\0",
"hgc1\0HGC1 Audio File (*.HGC1)\0",
"his\0HIS Audio File (*.HIS)\0",
"hlwav\0HLWAV Audio File (*.HLWAV)\0",
"hps\0HALPST Audio File (*.HPS)\0",
"hsf\0HSF Audio File (*.HSF)\0",
"hwas\0HWAS Audio File (*.HWAS)\0",
"iab\0IAB Audio File (*.IAB)\0",
"iadp\0IADP Audio File (*.IADP)\0",
"idsp\0IDSP Audio File (*.IDSP)\0",
"idvi\0IDVI Audio File (*.IDVI)\0",
"ikm\0IKM Audio File (*.IKM)\0",
"ild\0ILD Audio File (*.ILD)\0",
"int\0PS2 RAW Interleaved PCM (*.INT)\0",
"isd\0ISD Audio File (*.ISD)\0",
"isws\0ISWS Audio File (*.ISWS)\0",
"ivaud\0IVAUD Audio File (*.IVAUD)\0",
"ivag\0IVAG Audio File (*.IVAG)\0",
"ivb\0IVB Audio File (*.IVB)\0",
"joe\0JOE Audio File (*.JOE)\0",
"jstm\0JSTM Audio File (*.JSTM)\0",
"kces\0KCES Audio File (*.KCES)\0",
"kcey\0KCEY Audio File (*.KCEY)\0",
"khv\0KHV Audio File (*.KHV)\0",
"kovs\0KOVS Audio File (*.KOVS)\0",
"kraw\0KRAW Audio File (*.KRAW)\0",
"leg\0LEG Audio File (*.LEG)\0",
"logg\0LOGG Audio File (*.LOGG)\0",
"lpcm\0LPCM Audio File (*.LPCM)\0",
"lps\0LPS Audio File (*.LPS)\0",
"lsf\0LSF Audio File (*.LSF)\0",
"lwav\0LWAV Audio File (*.LWAV)\0",
"matx\0MATX Audio File (*.MATX)\0",
"mca\0MCA Audio File (*.MCA)\0",
"mcg\0MCG Audio File (*.MCG)\0",
"mi2\0PS2 MI2 Audio File (*.MI2)\0",
"mi4\0PS2 MI4 Audio File (*.MI4)\0",
"mib\0PS2 MIB Audio File (*.MIB)\0",
"mic\0PS2 MIC Audio File (*.MIC)\0",
"mihb\0MIHB Audio File (*.MIHB)\0",
"mnstr\0MNSTR Audio File (*.MNSTR)\0",
"mpdsp\0MPDSP Audio File (*.MPDSP)\0",
"mpds\0MPDS Audio File (*.MPDS)\0",
"msa\0MSA Audio File (*.MSA)\0",
"msf\0MSF Audio File (*.MSF)\0",
"mss\0MSS Audio File (*.MSS)\0",
"msvp\0MSVP Audio File (*.MSVP)\0",
"mtaf\0MTAF Audio File (*.MTAF)\0",
"mus\0MUS Playlist File (*.MUS)\0",
"musc\0MUSC Audio File (*.MUSC)\0",
"musx\0MUSX Audio File (*.MUSX)\0",
"mwv\0MWV Audio File (*.MWV)\0",
"mxst\0MxSt Audio File (*.MxSt)\0",
"myspd\0MYSPD Audio File (*.MYSPD)\0",
"ndp\0NDP Audio File (*.NDP)\0",
"ngca\0NGCA Audio File (*.NGCA)\0",
"npsf\0PS2 NPSF Audio File (*.NPSF)\0",
"nus3bank\0NUS3BANK Audio File (*.NUS3BANK)\0",
"nwa\0NWA Audio File (*.NWA)\0",
"omu\0OMU Audio File (*.OMU)\0",
"otm\0OTM Audio File (*.OTM)\0",
"p2bt\0P2BT Audio File (*.P2BT)\0",
"p3d\0P3D Audio File (*.P3D)\0",
"past\0PAST Audio File (*.PAST)\0",
"pcm\0PCM Audio File (*.PCM)\0",
"pdt\0PDT Audio File (*.PDT)\0",
"pnb\0PNB Audio File (*.PNB)\0",
"pona\0PONA Audio File (*.PONA)\0",
"pos\0POS Audio File (*.POS)\0",
"ps2stm\0PS2STM Audio File (*.PS2STM)\0",
"psh\0PSH Audio File (*.PSH)\0",
"psnd\0PSND Audio File (*.PSND)\0",
"psw\0PSW Audio File (*.PSW)\0",
"ras\0RAS Audio File (*.RAS)\0",
"raw\0RAW Audio File (*.RAW)\0",
"rkv\0RKV Audio File (*.RKV)\0",
"rnd\0RND Audio File (*.RND)\0",
"rrds\0RRDS Audio File (*.RRDS)\0",
"rsd\0RSD Audio File (*.RSD)\0",
"rsf\0RSF Audio File (*.RSF)\0",
"rstm\0RSTM Audio File (*.RSTM)\0",
"rvws\0RVWS Audio File (*.RVWS)\0",
"rwar\0RWAR Audio File (*.RWSD)\0",
"rwav\0RWAV Audio File (*.RWAV)\0",
"rws\0RWS Audio File (*.RWS)\0",
"rwsd\0RWSD Audio File (*.RWSD)\0",
"rwx\0RWX Audio File (*.RWX)\0",
"rxw\0PS2 RXWS File (*.RXW)\0",
"s14\0S14 Audio File (*.S14)\0",
"sab\0SAB Audio File (*.SAB)\0",
"sad\0SAD Audio File (*.SAD)\0",
"sap\0SAP Audio File (*.SAP)\0",
"sc\0SC Audio File (*.SC)\0",
"scd\0SCD Audio File (*.SCD)\0",
"sck\0SCK Audio File (*.SCK)\0",
"sd9\0SD9 Audio File (*.SD9)\0",
"sdt\0SDT Audio File (*.SDT)\0",
"seg\0SEG Audio File (*.SEG)\0",
"sf0\0SF0 Audio File (*.SF0)\0",
"sfl\0SFL Audio File (*.SFL)\0",
"sfs\0SFS Audio File (*.SFS)\0",
"sfx\0SFX Audio File (*.SFX)\0",
"sgb\0SGB Audio File (*.SGB)\0",
"sgd\0SGD Audio File (*.SGD)\0",
"sgx\0SGX Audio File (*.SGX)\0",
"sl3\0SL3 Audio File (*.SL3)\0",
"sli\0SLI Audio File (*.SLI)\0",
"smp\0SMP Audio File (*.SMP)\0",
"smpl\0SMPL Audio File (*.SMPL)\0",
"snd\0SND Audio File (*.SND)\0",
"snds\0SNDS Audio File (*.SNDS)\0",
"sng\0SNG Audio File (*.SNG)\0",
"sns\0SNS Audio File (*.SNS)\0",
"spd\0SPD Audio File (*.SPD)\0",
"spm\0SPM Audio File (*.SPM)\0",
"sps\0SPS Audio File (*.SPS)\0",
"spsd\0SPSD Audio File (*.SPSD)\0",
"spw\0SPW Audio File (*.SPW)\0",
"ss2\0PS2 SS2 Audio File (*.SS2)\0",
"ss3\0SS3 Audio File (*.SS3)\0",
"ss7\0SS7 Audio File (*.SS7)\0",
"ssm\0SSM Audio File (*.SSM)\0",
"sss\0SSS Audio File (*.SSS)\0",
"ster\0STER Audio File (*.STER)\0",
"sth\0STH Audio File (*.STH)\0",
"stma\0STMA Audio File (*.STMA)\0",
"str\0STR Audio File (*.STR)\0",
"strm\0STRM Audio File (*.STRM)\0",
"sts\0PS2 EXST Audio File (*.STS)\0",
"stx\0STX Audio File (*.STX)\0",
"svag\0PS2 SVAG Audio File (*.SVAG)\0",
"svs\0SVS Audio File (*.SVS)\0",
"swav\0SWAV Audio File (*.SWAV)\0",
"swd\0SWD Audio File (*.SWD)\0",
"tec\0TEC Audio File (*.TEC)\0",
"thp\0THP Audio File (*.THP)\0",
"tk1\0TK1 Audio File (*.TK1)\0",
"tk5\0TK5 Audio File (*.TK5)\0",
"tra\0TRA Audio File (*.TRA)\0",
"tun\0TUN Audio File (*.TUN)\0",
"tydsp\0TYDSP Audio File (*.TYDSP)\0",
"um3\0UM3 Audio File (*.UM3)\0",
"vag\0VAG Audio File (*.VAG)\0",
"vas\0VAS Audio File (*.VAS)\0",
"vawx\0VAWX Audio File (*.VAWX)\0",
"vb\0VB Audio File (*.VB)\0",
"vbk\0VBK Audio File (*.VBK)\0",
"vgs\0VGS Audio File (*.VGS)\0",
"vig\0VIG Audio File (*.VIG)\0",
"vms\0VMS Audio File (*.VMS)\0",
"vpk\0VPK Audio File (*.VPK)\0",
"vs\0VS Audio File (*.VS)\0",
"vsf\0VSF Audio File (*.VSF)\0",
"vgv\0VGV Audio File (*.VGV)\0",
"voi\0VOI Audio File (*.VOI)\0",
"waa\0WAA Audio File (*.WAA)\0",
"wac\0WAC Audio File (*.WAC)\0",
"wad\0WAD Audio File (*.WAD)\0",
"wam\0WAM Audio File (*.WAM)\0",
"wavm\0WAVM Audio File (*.WAVM)\0",
"was\0WAS Audio File (*.WAS)\0",
"wb\0WB Audio File (*.WB)\0",
"wii\0WII Audio File (*.WII)\0",
"wmus\0WMUS Audio File (*.WMUS)\0",
"wp2\0WP2 Audio File (*.WP2)\0",
"wpd\0WPD Audio File (*.WPD)\0",
"wsd\0WSD Audio File (*.WSD)\0",
"wsi\0WSI Audio File (*.WSI)\0",
"wvs\0WVS Audio File (*.WVS)\0",
"xa\0PSX CD-XA File (*.XA)\0",
"xa2\0XA2 Audio File (*.XA2)\0",
"xa30\0XA30 Audio File (*.XA30)\0",
"xau\0XAU Audio File (*.XAU)\0",
"xma\0XMA Audio File (*.XMA)\0",
"xma2\0XMA2 Audio File (*.XMA2)\0",
"xmu\0XMU Audio File (*.XMU)\0",
"xnb\0XNB Audio File (*.XNB)\0",
"xsf\0XSF Audio File (*.XSF)\0",
"xss\0XSS Audio File (*.XSS)\0",
"xvag\0XVAG Audio File (*.XVAG)\0",
"xvas\0XVAS Audio File (*.XVAS)\0",
"xwav\0XWAV Audio File (*.XWAV)\0",
"xwb\0XWB Audio File (*.XWB)\0",
"xwm\0XWM Audio File (*.XWM)\0",
"xag\0XAG Audio File (*.XAG)\0",
"ydsp\0YDSP Audio File (*.YDSP)\0",
"ymf\0YMF Audio File (*.YMF)\0",
"zsd\0ZSD Audio File (*.ZSD)\0",
"zwdsp\0ZWDSP Audio File (*.ZWDSP)\0",
"vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0",
};
void about(HWND hwndParent) { void about(HWND hwndParent) {
MessageBox(hwndParent, MessageBox(hwndParent,
@ -383,17 +91,6 @@ void about(HWND hwndParent) {
} }
void quit() {} void quit() {}
void build_extension_list() {
int i;
working_extension_list[0]='\0';
working_extension_list[1]='\0';
for (i=0;i<sizeof(extension_list)/sizeof(extension_list[0]);i++) {
concatn_fitting_doublenull(EXTENSION_LIST_SIZE,working_extension_list,
extension_list[i]);
}
}
void GetINIFileName(char * iniFile) { void GetINIFileName(char * iniFile) {
/* if we're running on a newer winamp version that better supports /* if we're running on a newer winamp version that better supports
* saving of settings to a per-user directory, use that directory - if not * saving of settings to a per-user directory, use that directory - if not
@ -929,3 +626,63 @@ __declspec( dllexport ) In_Module * winampGetInModule2()
return &input_module; return &input_module;
} }
/**
* Creates Winamp's extension list, a single string that ends with \0\0.
* Each extension must be in this format: "extension\0Description\0"
*/
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
int i;
working_extension_list[0]='\0';
working_extension_list[1]='\0';
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
add_extension(EXTENSION_LIST_SIZE, working_extension_list, ext_list[i]);
}
}
/**
* Adds ext to Winamp's extension list.
*/
static void add_extension(int length, char * dst, const char * ext) {
char buf[EXT_BUFFER_SIZE];
char ext_upp[EXT_BUFFER_SIZE];
int ext_len, written;
int i,j;
if (length <= 1)
return;
ext_len = strlen(ext);
/* find end of dst (double \0), saved in i */
for (i=0; i<length-2 && (dst[i] || dst[i+1]); i++)
;
/* check if end reached or not enough room to add */
if (i == length-2 || i + EXT_BUFFER_SIZE+2 > length-2 || ext_len * 3 + 20+2 > EXT_BUFFER_SIZE) {
dst[i]='\0';
dst[i+1]='\0';
return;
}
if (i > 0)
i++;
/* uppercase ext */
for (j=0; j < ext_len; j++)
ext_upp[j] = toupper(ext[j]);
ext_upp[j] = '\0';
/* copy new extension + double null terminate */
written = sprintf(buf, "%s%c%s Audio File (*.%s)%c", ext,'\0',ext_upp,ext_upp,'\0'); /*ex: "vgmstream\0vgmstream Audio File (*.VGMSTREAM)\0" */
for (j=0; j < written; i++,j++)
dst[i] = buf[j];
dst[i]='\0';
dst[i+1]='\0';
}

View File

@ -10,9 +10,11 @@
#include <stdio.h> #include <stdio.h>
#include <io.h> #include <io.h>
#include <conio.h> #include <conio.h>
#include <string.h>
#include <ctype.h>
#include ".\src\vgmstream.h" #include "../src/formats.h"
#include ".\src\util.h" #include "../src/vgmstream.h"
#include "xmpin.h" #include "xmpin.h"
#include "version.h" #include "version.h"
@ -329,10 +331,20 @@ void __stdcall GetAdditionalFields(char* blerp) {
sprintf(blerp,"oh god how did this get here I am not good with computers\n"); sprintf(blerp,"oh god how did this get here I am not good with computers\n");
} }
/* XMPlay extension list, only needed to associate extensions in Windows */
/* todo: as of v3.8.2.17, any more than 1024 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */
#define EXTENSION_LIST_SIZE 1024 /*VGM_EXTENSION_LIST_CHAR_SIZE * 2*/
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
static int add_extension(int length, char * dst, const char * src);
static void build_extension_list();
XMPIN vgmstream_intf = { XMPIN vgmstream_intf = {
XMPIN_FLAG_CANSTREAM, XMPIN_FLAG_CANSTREAM,
"vgmstream for XMPlay", "vgmstream for XMPlay",
"vgmstream files\0""2dx9/aaap/aax/acm/adp/adpcm/ads/adx/afc/agsc/ahx/aifc/aiff/aix/amts/as4/asd/asf/asr/ass/ast/aud/aus/baf/baka/bar/bcstm/bcwav/bfstm/bfwav/bfwavnsmbu/bg00/bgw/bh2pcm/bmdx/bns/bnsf/bo2/brstm/caf/capdsp/ccc/cfn/cnk/dcs/dcsw/ddsp/de2/dmsg/dsp/dvi/dxh/eam/emff/enth/fag/filp/fsb/fwav/gca/gcm/gcsw/gcw/genh/gms/gsp/hca/hgc1/his/hps/hwas/idsp/idvi/ikm/ild/int/isd/ish/ivaud/ivb/joe/kces/kcey/khv/kraw/leg/logg/lps/lsf/lwav/matx/mcg/mi4/mib/mic/mihb/mpdsp/mca/msa/mss/msvp/mus/musc/musx/mwv/myspd/ndp/npsf/nus3bank/nwa/omu/otm/p3d/pcm/pdt/pnb/pos/psh/psw/raw/rkv/rnd/rrds/rsd/rsf/rstm/rwar/rwav/rws/rwsd/rwx/rxw/s14/sab/sad/sap/sc/scd/sd9/sdt/seg/sfl/sfs/sl3/sli/smp/smpl/snd/sng/sns/spd/sps/spsd/spt/spw/ss2/ss7/ssm/sss/ster/sth/stm/stma/str/strm/sts/stx/svag/svs/swav/swd/tec/thp/tk5/tydsp/um3/vag/vas/vgs/vig/vjdsp/voi/vpk/vs/vsf/waa/wac/wad/wam/was/wavm/wb/wii/wp2/wsd/wsi/wvs/xa/xa2/xa30/xma/xma2/xmu/xss/xvas/xwav/xwb/xwm/ydsp/ymf/zsd/zwdsp/vgmstream", working_extension_list,
XMPAbout, XMPAbout,
NULL, NULL,
XMP_CheckFile, XMP_CheckFile,
@ -386,5 +398,54 @@ __declspec(dllexport) XMPIN* __stdcall XMPIN_GetInterface(UINT32 face, Interface
xmpfmisc = (XMPFUNC_MISC*)faceproc(XMPFUNC_MISC_FACE); xmpfmisc = (XMPFUNC_MISC*)faceproc(XMPFUNC_MISC_FACE);
xmpffile = (XMPFUNC_FILE*)faceproc(XMPFUNC_FILE_FACE); xmpffile = (XMPFUNC_FILE*)faceproc(XMPFUNC_FILE_FACE);
build_extension_list();
return &vgmstream_intf; return &vgmstream_intf;
} }
/**
* Creates XMPlay's extension list, a single string with 2 nulls.
* Extensions must be in this format: "Description\0extension1/.../extensionN"
*/
static void build_extension_list() {
const char ** ext_list;
int ext_list_len;
int i, written;
written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0');
ext_list = vgmstream_get_formats();
ext_list_len = vgmstream_get_formats_length();
for (i=0; i < ext_list_len; i++) {
written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]);
}
working_extension_list[written-1] = '\0'; /* remove last "/" */
}
/**
* Adds ext to XMPlay's extension list.
*/
static int add_extension(int length, char * dst, const char * ext) {
int ext_len;
int i;
if (length <= 1)
return 0;
ext_len = strlen(ext);
/* check if end reached or not enough room to add */
if (ext_len+2 > length-2) {
dst[0]='\0';
return 0;
}
/* copy new extension + null terminate */
for (i=0; i < ext_len; i++)
dst[i] = ext[i];
dst[i]='/';
dst[i+1]='\0';
return i+1;
}

66
xmp-vgmstream/Makefile Normal file
View File

@ -0,0 +1,66 @@
# optional parts
VGM_ENABLE_FFMPEG=1
ifeq ($(VGM_ENABLE_FFMPEG),1)
FFMPEG_CC=-DVGM_USE_FFMPEG -DVGM_USE_FFMPEG_ACCURATE_LOOPING
FFMPEG_LD=-lavcodec -lavformat -lavutil
endif
VGM_ENABLE_MAIATRAC3PLUS=0
ifeq ($(VGM_ENABLE_MAIATRAC3PLUS),1)
MAT3P_CC=-DVGM_USE_MAIATRAC3PLUS
MAT3P_LD=-lat3plusdecoder
endif
#MPEG_CC=-DVGM_USE_MPEG
MPEG_LD=-lmpg123-0
VGM_DISABLE_MPEG=0
ifeq ($(VGM_DISABLE_MPEG),1)
MPEG_CC=-DVGM_DISABLE_MPEG
MPEG_LD=
endif
# config
export SHELL = /bin/sh
export CFLAGS=-Wall -O3 $(MPEG_CC) -DVGM_USE_G7221 -DVGM_USE_G719 $(MAT3P_CC) $(FFMPEG_CC) -DUSE_ALLOCA -DWIN32 -I../ext_includes $(EXTRA_CFLAGS)
export LDFLAGS=-L../src -L../ext_libs -lvgmstream -lvorbis $(MPEG_LD) -lg7221_decode -lg719_decode $(MAT3P_LD) $(FFMPEG_LD) -lm $(EXTRA_LDFLAGS)
export CC=gcc
export AR=ar
export STRIP=strip
.PHONY: libvgmstream.a libvorbis.a libmpg123-0.a libg7221_decode.a libg719_decode.a libat3plusdecoder.a libavcodec.a libavformat.a libavutil.a
xmp-vgmstream.dll: libvgmstream.a libvorbis.a libmpg123-0.a libg7221_decode.a libg719_decode.a libat3plusdecoder.a libavcodec.a libavformat.a libavutil.a
$(CC) -shared -static-libgcc $(CFLAGS) "-DVERSION=\"`../version.sh`\"" DllMain.c $(LDFLAGS) -o xmp-vgmstream.dll xmpin.def
$(STRIP) xmp-vgmstream.dll
libvgmstream.a:
$(MAKE) -C ../src $@
libvorbis.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libmpg123-0.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libg7221_decode.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libg719_decode.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libat3plusdecoder.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libavcodec.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libavformat.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
libavutil.a:
$(MAKE) -C ../ext_libs -f Makefile.mingw $@
clean:
rm -f xmp-vgmstream.dll