diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 3da5e54d..628c6d1d 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -298,6 +298,10 @@ RelativePath=".\meta\ps2_vag.c" > + + diff --git a/src/meta/meta.h b/src/meta/meta.h index da319a84..5588038e 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -77,4 +77,6 @@ VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_ps2_vpk(STREAMFILE *streamFile); + #endif diff --git a/src/meta/ngc_caf.c b/src/meta/ngc_caf.c index 292002f8..6b2756f0 100644 --- a/src/meta/ngc_caf.c +++ b/src/meta/ngc_caf.c @@ -1,12 +1,12 @@ -#include "meta.h" -#include "../util.h" - -extern caf_block_update(off_t block_offset, VGMSTREAM * vgmstream); - -VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[260]; - +#include "meta.h" +#include "../util.h" + +extern caf_block_update(off_t block_offset, VGMSTREAM * vgmstream); + +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; @@ -16,15 +16,15 @@ VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { 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; - + 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); @@ -38,10 +38,10 @@ VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { offset+=next_block; block_count++; } while(offsetchannels=2; vgmstream->sample_rate=32000; @@ -52,27 +52,25 @@ VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { 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; -} - + 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; +} \ No newline at end of file diff --git a/src/meta/ps2_ads.c b/src/meta/ps2_ads.c index 4440afb7..447b334a 100644 --- a/src/meta/ps2_ads.c +++ b/src/meta/ps2_ads.c @@ -9,6 +9,8 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { int loop_flag=0; int channel_count; + off_t start_offset,test_offset; + int ads_type_2=0; int i; /* check extension, case insensitive */ @@ -51,19 +53,38 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { 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) { - vgmstream->loop_start_sample = read_32bitLE(0x18,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); + if(vgmstream->interleave_block_size==0x10) { + 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->loop_end_sample = (read_32bitLE(0x1C,streamFile)*0x10)/16*28; + } } /* 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; - vgmstream->interleave_block_size = read_32bitLE(0x14,streamFile); - vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_SShd; + start_offset=0x28; + + // Hack for files with start_offset = 0x800 + ads_type_2=1; + + for(test_offset=start_offset;test_offset<0x800;test_offset+=4) { + if (read_32bitLE(test_offset,streamFile)!=0) + ads_type_2=0; + } + + if((ads_type_2==1)){ + start_offset=0x800; + } /* open the file for reading by each channel */ { @@ -74,7 +95,7 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) { vgmstream->ch[i].channel_start_offset= vgmstream->ch[i].offset= - (off_t)(0x28+vgmstream->interleave_block_size*i); + (off_t)(start_offset+vgmstream->interleave_block_size*i); } } diff --git a/src/meta/ps2_vag.c b/src/meta/ps2_vag.c index a50a5081..707084f0 100644 --- a/src/meta/ps2_vag.c +++ b/src/meta/ps2_vag.c @@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *streamFile) { if(read_32bitBE(0x20,streamFile)==0x53746572) // vag Stereo channel_count=2; case 'p': - if(read_32bitBE(0x04,streamFile)==0x00000004) { + if(read_32bitBE(0x04,streamFile)<=0x00000004) { loop_flag=(read_32bitBE(0x14,streamFile)!=0); channel_count=2; } else { @@ -128,6 +128,14 @@ VGMSTREAM * init_vgmstream_ps2_vag(STREAMFILE *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; diff --git a/src/meta/ps2_vpk.c b/src/meta/ps2_vpk.c new file mode 100644 index 00000000..7def9785 --- /dev/null +++ b/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;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); + + if (!vgmstream->ch[i].streamfile) goto fail; + + vgmstream->ch[i].channel_start_offset= + vgmstream->ch[i].offset= + (off_t)(start_offset+vgmstream->interleave_block_size*i); + } + } + + return vgmstream; + + /* clean up anything we may have opened */ +fail: + if (vgmstream) close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/streamfile.c b/src/streamfile.c index b3118dab..28fecc56 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1,193 +1,193 @@ #ifndef _MSC_VER -#include -#endif -#include "streamfile.h" -#include "util.h" - -typedef struct { - STREAMFILE sf; - FILE * infile; - off_t offset; - size_t validsize; - uint8_t * buffer; - size_t buffersize; - char name[260]; -#ifdef PROFILE_STREAMFILE - size_t bytes_read; -#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 - 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; - } - - return read_the_rest(dest,offset,length,streamfile); -} - -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; -} -#endif - -static STREAMFILE *open_stdio(STDIOSTREAMFILE *streamFile,const char * const filename,size_t buffersize) { - int newfd; - FILE *newfile; - STREAMFILE *newstreamFile; - - if (!filename) - return NULL; - // if same name, duplicate the file pointer we already have open - if (!strcmp(streamFile->name,filename)) { - if (((newfd = dup(fileno(streamFile->infile))) >= 0) && - (newfile = fdopen( newfd, "rb" ))) - { - newstreamFile = open_stdio_streamfile_buffer_by_FILE(newfile,filename,buffersize); - if (newstreamFile) { - return newstreamFile; - } - // failure, close it and try the default path (which will probably fail a second time) - fclose(newfile); - } - } - // a normal open, open a new file - return open_stdio_streamfile_buffer(filename,buffersize); -} - -static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char * const filename, size_t buffersize) { - uint8_t * buffer; - STDIOSTREAMFILE * streamfile; - - buffer = calloc(buffersize,1); - if (!buffer) { - return NULL; - } - - streamfile = calloc(1,sizeof(STDIOSTREAMFILE)); - if (!streamfile) { - free(buffer); - return NULL; - } - - streamfile->sf.read = (void*)read_stdio; - streamfile->sf.get_size = (void*)get_size_stdio; - streamfile->sf.get_offset = (void*)get_offset_stdio; - streamfile->sf.get_name = (void*)get_name_stdio; - streamfile->sf.open = (void*)open_stdio; - streamfile->sf.close = (void*)close_stdio; -#ifdef PROFILE_STREAMFILE - streamfile->sf.get_bytes_read = (void*)get_bytes_read_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; -} +#include +#endif +#include "streamfile.h" +#include "util.h" + +typedef struct { + STREAMFILE sf; + FILE * infile; + off_t offset; + size_t validsize; + uint8_t * buffer; + size_t buffersize; + char name[260]; +#ifdef PROFILE_STREAMFILE + size_t bytes_read; +#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 + 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; + } + + return read_the_rest(dest,offset,length,streamfile); +} + +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; +} +#endif + +static STREAMFILE *open_stdio(STDIOSTREAMFILE *streamFile,const char * const filename,size_t buffersize) { + int newfd; + FILE *newfile; + STREAMFILE *newstreamFile; + + if (!filename) + return NULL; + // if same name, duplicate the file pointer we already have open + if (!strcmp(streamFile->name,filename)) { + if (((newfd = dup(fileno(streamFile->infile))) >= 0) && + (newfile = fdopen( newfd, "rb" ))) + { + newstreamFile = open_stdio_streamfile_buffer_by_FILE(newfile,filename,buffersize); + if (newstreamFile) { + return newstreamFile; + } + // failure, close it and try the default path (which will probably fail a second time) + fclose(newfile); + } + } + // a normal open, open a new file + return open_stdio_streamfile_buffer(filename,buffersize); +} + +static STREAMFILE * open_stdio_streamfile_buffer_by_FILE(FILE *infile,const char * const filename, size_t buffersize) { + uint8_t * buffer; + STDIOSTREAMFILE * streamfile; + + buffer = calloc(buffersize,1); + if (!buffer) { + return NULL; + } + + streamfile = calloc(1,sizeof(STDIOSTREAMFILE)); + if (!streamfile) { + free(buffer); + return NULL; + } + + streamfile->sf.read = (void*)read_stdio; + streamfile->sf.get_size = (void*)get_size_stdio; + streamfile->sf.get_offset = (void*)get_offset_stdio; + streamfile->sf.get_name = (void*)get_name_stdio; + streamfile->sf.open = (void*)open_stdio; + streamfile->sf.close = (void*)close_stdio; +#ifdef PROFILE_STREAMFILE + streamfile->sf.get_bytes_read = (void*)get_bytes_read_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; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 196bcd0a..331aeed3 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -15,7 +15,7 @@ * List of functions that will recognize files. These should correspond pretty * directly to the metadata types */ -#define INIT_VGMSTREAM_FCNS 37 +#define INIT_VGMSTREAM_FCNS 38 VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile) = { init_vgmstream_adx, /* 0 */ init_vgmstream_brstm, /* 1 */ @@ -53,7 +53,8 @@ VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile) init_vgmstream_xbox_xwav, /* 33 */ init_vgmstream_ngc_str, /* 34 */ init_vgmstream_ea, /* 35 */ - init_vgmstream_caf /* 36 */ + init_vgmstream_caf, /* 36 */ + init_vgmstream_ps2_vpk /* 37 */ }; /* internal version with all parameters */ @@ -788,6 +789,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { break; case meta_CFN: snprintf(temp,TEMPSIZE,"Namco CAF Header"); + break; + case meta_PS2_VPK: + snprintf(temp,TEMPSIZE,"VPK Header"); break; default: snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); diff --git a/src/vgmstream.h b/src/vgmstream.h index e44b68a9..eb04e559 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -106,6 +106,7 @@ typedef enum { 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_XBOX_WAVM, /* XBOX WAVM File */ meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */ diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index fbe8b244..02511da9 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -111,8 +111,9 @@ char * extension_list[] = { "wp2\0WP2 Audio File (*.WP2)\0", "sng\0SNG Audio File (*.SNG)\0", "asf\0ASF Audio File (*.ASF)\0", - "eam\0EAM Audio File (*.EAM)\0" - "cfn\0CFN Audio File (*.CFN)\0" + "eam\0EAM Audio File (*.EAM)\0", + "cfn\0CFN Audio File (*.CFN)\0", + "vpk\0VPK Audio File (*.VPK)\0" }; void about(HWND hwndParent) {