diff --git a/src/formats.c b/src/formats.c index 10f46b24..27ed56b8 100644 --- a/src/formats.c +++ b/src/formats.c @@ -704,7 +704,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_VAGm, "Sony VAG Mono header (VAGm)"}, {meta_PS2_pGAV, "Sony VAG Stereo Little Endian header (pGAV)"}, {meta_PSX_GMS, "assumed Grandia GMS file by .gms extension"}, - {meta_PS2_STR, "assumed STR + STH File by .str & .sth extension"}, + {meta_STR_WAV, "Blitz Games STR+WAV header"}, {meta_PS2_ILD, "ILD header"}, {meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"}, {meta_XBOX_WAVM, "Xbox WAVM raw header"}, @@ -851,7 +851,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_SND, "Might and Magic SSND Header"}, {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, {meta_ADS, "dhSS Header"}, - {meta_WII_STR, "HOTD Overkill - STR+STH WII Header"}, {meta_PS2_MCG, "Gunvari MCG Header"}, {meta_ZSD, "ZSD Header"}, {meta_RedSpark, "RedSpark Header"}, @@ -908,7 +907,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_B1S, "B1S header"}, {meta_PS2_WAD, "WAD header"}, {meta_DSP_XIII, "XIII dsp header"}, - {meta_NGC_DSP_STH_STR, "STH dsp header"}, {meta_DSP_CABELAS, "Cabelas games dsp header"}, {meta_PS2_ADM, "Dragon Quest V .ADM raw header"}, {meta_PS2_LPCM, "LPCM header"}, diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index 585b6835..2c2816ca 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -400,10 +400,6 @@ RelativePath=".\meta\dsp_bdsp.c" > - - @@ -1038,10 +1034,6 @@ RelativePath=".\meta\ps2_ster.c" > - - @@ -1286,6 +1278,10 @@ RelativePath=".\meta\str_snds.c" > + + @@ -1398,10 +1394,6 @@ RelativePath=".\meta\wii_sng.c" > - - diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 01508a31..e1c05038 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -218,7 +218,6 @@ - @@ -353,7 +352,6 @@ - @@ -403,6 +401,7 @@ + @@ -427,7 +426,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index b7e46897..b624bf6a 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -244,9 +244,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -634,9 +631,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -784,6 +778,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -856,9 +853,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/dsp_sth_str.c b/src/meta/dsp_sth_str.c deleted file mode 100644 index 4db018c1..00000000 --- a/src/meta/dsp_sth_str.c +++ /dev/null @@ -1,320 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* - STH+STR - found in SpongebobSquarepants: Creature From The Krusty Krab (NGC) -*/ - -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamFileSTR = NULL; - char filename[PATH_LIMIT]; - char filenameSTR[PATH_LIMIT]; - int i, j; - int channel_count; - int loop_flag; - off_t coef_table[8] = {0x12C,0x18C,0x1EC,0x24C,0x2AC,0x30C,0x36C,0x3CC}; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("sth",filename_extension(filename))) goto fail; - - strcpy(filenameSTR,filename); - strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); - streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!streamFileSTR) goto fail; - - if (read_32bitBE(0x0,streamFile) != 0x0) - { - goto fail; - } - - if (read_32bitBE(0x4,streamFile) != 0x800) - { - goto fail; - } - - /* Not really channel_count, just 'included tracks * channels per track */ - loop_flag = (read_32bitBE(0xD8,streamFile) != 0xFFFFFFFF); - channel_count = (read_32bitBE(0x70,streamFile)) * (read_32bitBE(0x88,streamFile)); - - if (channel_count > 8) - { - goto fail; - } - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x24,streamFile); - vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; - vgmstream->coding_type = coding_NGC_DSP; - - if(loop_flag) - { - vgmstream->loop_start_sample = read_32bitBE(0xD8,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile); - } - - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else - { - vgmstream->layout_type = layout_interleave; - if (channel_count == 2) - { - vgmstream->interleave_block_size=0x10000; - } - else - { - vgmstream->interleave_block_size=0x8000; - } - } - - vgmstream->meta_type = meta_NGC_DSP_STH_STR; - - /* open the file for reading */ - for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; - } - - // COEFFS - for (j=0;jchannels;j++) - { - for (i=0;i<16;i++) - { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } - } - - close_streamfile(streamFileSTR); streamFileSTR=NULL; - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (streamFileSTR) close_streamfile(streamFileSTR); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - - -/* - STH+STR - found in Taz Wanted (NGC), Cubix Robots for Everyone: Showdown (NGC) -*/ - -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamFileSTR = NULL; - char filename[PATH_LIMIT]; - char filenameSTR[PATH_LIMIT]; - int i, j; - int channel_count; - int loop_flag; - off_t coef_table[8] = {0xDC,0x13C,0x19C,0x1FC,0x25C,0x2BC,0x31C,0x37C}; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("sth",filename_extension(filename))) goto fail; - - strcpy(filenameSTR,filename); - strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); - streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!streamFileSTR) goto fail; - - if (read_32bitBE(0x0,streamFile) != 0x0) - { - goto fail; - } - - if (read_32bitBE(0x4,streamFile) != 0x900) - { - goto fail; - } - - /* Not really channel_count, just 'included tracks * channels per track */ - loop_flag = (read_32bitBE(0xB8,streamFile) != 0xFFFFFFFF); - channel_count = read_32bitBE(0x50,streamFile)*2; - - if (channel_count > 8) - { - goto fail; - } - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x24,streamFile); - vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; - vgmstream->coding_type = coding_NGC_DSP; - - if(loop_flag) - { - vgmstream->loop_start_sample = read_32bitBE(0xB8,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0xBC,streamFile); - } - - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else - { - vgmstream->layout_type = layout_interleave; - if (channel_count == 2) - { - vgmstream->interleave_block_size=0x10000; - } - else - { - vgmstream->interleave_block_size=0x8000; - } - } - - vgmstream->meta_type = meta_NGC_DSP_STH_STR; - - /* open the file for reading */ - for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; - } - - // COEFFS - for (j=0;jchannels;j++) - { - for (i=0;i<16;i++) - { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } - } - - close_streamfile(streamFileSTR); streamFileSTR=NULL; - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (streamFileSTR) close_streamfile(streamFileSTR); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - - -/* - STH+STR - found in Tak and the Guardians of Gross (WII) -*/ - -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamFileSTR = NULL; - char filename[PATH_LIMIT]; - char filenameSTR[PATH_LIMIT]; - int i, j; - int channel_count; - int loop_flag; - off_t coef_table[8] = {read_32bitBE(0x7C,streamFile),read_32bitBE(0x80,streamFile),read_32bitBE(0x84,streamFile),read_32bitBE(0x88,streamFile),read_32bitBE(0x8C,streamFile),read_32bitBE(0x90,streamFile),read_32bitBE(0x94,streamFile),read_32bitBE(0x98,streamFile)}; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("sth",filename_extension(filename))) goto fail; - - strcpy(filenameSTR,filename); - strcpy(filenameSTR+strlen(filenameSTR)-3,"str"); - streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!streamFileSTR) goto fail; - - if (read_32bitBE(0x0,streamFile) != 0x0) - { - goto fail; - } - - if ((read_32bitBE(0x4,streamFile) != 0x700) && - (read_32bitBE(0x4,streamFile) != 0x800)) - { - goto fail; - } - - /* Not really channel_count, just 'included tracks * channels per track */ - loop_flag = 0; - channel_count = read_32bitBE(0x70,streamFile); - - if (channel_count > 8) - { - goto fail; - } - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x38,streamFile); - vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14; - vgmstream->coding_type = coding_NGC_DSP; - - if(loop_flag) - { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = 0; - } - - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else - { - vgmstream->layout_type = layout_interleave; - if (channel_count == 2 || channel_count == 4) - { - vgmstream->interleave_block_size=0x8000; - } - else - { - vgmstream->interleave_block_size=0x4000; - } - } - - vgmstream->meta_type = meta_NGC_DSP_STH_STR; - - /* open the file for reading */ - for (i=0;ich[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000); - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; - } - - // COEFFS - for (j=0;jchannels;j++) - { - for (i=0;i<16;i++) - { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile); - } - } - - close_streamfile(streamFileSTR); streamFileSTR=NULL; - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (streamFileSTR) close_streamfile(streamFileSTR); - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/meta.h b/src/meta/meta.h index 34ff328a..4b4d7b0a 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -69,8 +69,6 @@ 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); @@ -385,8 +383,6 @@ VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_wii_str(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_ps2_mcg(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_zsd(STREAMFILE *streamFile); @@ -490,10 +486,6 @@ VGMSTREAM * init_vgmstream_dsp_str_ig(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE* streamFile); @@ -773,4 +765,6 @@ VGMSTREAM * init_vgmstream_ckb(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_wv6(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_str_wav(STREAMFILE *streamFile); + #endif /*_META_H*/ diff --git a/src/meta/ps2_str.c b/src/meta/ps2_str.c deleted file mode 100644 index d02dcba1..00000000 --- a/src/meta/ps2_str.c +++ /dev/null @@ -1,96 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* STR - - 2008-05-19 - Fastelbja : Test version ... -*/ - -VGMSTREAM * init_vgmstream_ps2_str(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; - STREAMFILE * infileSTH = NULL; - char filename[PATH_LIMIT]; - - char * filenameSTH = NULL; - - int i, channel_count, loop_flag; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("str",filename_extension(filename))) goto fail; - - /* check for .MIH file */ - filenameSTH=(char *)malloc(strlen(filename)+1); - - if (!filenameSTH) goto fail; - - strcpy(filenameSTH,filename); - strcpy(filenameSTH+strlen(filenameSTH)-3,"STH"); - - infileSTH = streamFile->open(streamFile,filenameSTH,STREAMFILE_DEFAULT_BUFFER_SIZE); - - /* STH File is necessary, so we can't confuse those file */ - /* with others .STR file as it is a very common extension */ - if (!infileSTH) goto fail; - - if(read_32bitLE(0x2C,infileSTH)==0) - goto fail; - - if((read_32bitLE(0x2C,infileSTH)==0x07) || - (read_32bitLE(0x2C,infileSTH)==0x06)) - channel_count=2; - if(read_32bitLE(0x2C,infileSTH)==0x05) - channel_count=1; - - loop_flag = read_32bitLE(0x2C,infileSTH) & 0x01; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x24,infileSTH); - - vgmstream->interleave_block_size=0x4000; - - if(read_32bitLE(0x40,infileSTH)==0x01) - vgmstream->interleave_block_size = 0x8000; - - vgmstream->num_samples=read_32bitLE(0x20,infileSTH); - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - - vgmstream->meta_type = meta_PS2_STR; - - if(loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x20,infileSTH); - } - - close_streamfile(infileSTH); infileSTH=NULL; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset+=(off_t)(vgmstream->interleave_block_size*i); - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (infileSTH) close_streamfile(infileSTH); - if (filenameSTH) {free(filenameSTH); filenameSTH=NULL;} - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/str_wav.c b/src/meta/str_wav.c new file mode 100644 index 00000000..9ac552d5 --- /dev/null +++ b/src/meta/str_wav.c @@ -0,0 +1,452 @@ +#include "meta.h" +#include "../coding/coding.h" + + +typedef enum { PSX, DSP, XBOX, WMA } strwav_codec; +typedef struct { + int32_t channels; + int32_t sample_rate; + int32_t num_samples; + int32_t loop_start; + int32_t loop_end; + int32_t loop_flag; + size_t interleave; + + off_t coefs_offset; + off_t dsps_table; + off_t coefs_table; + + uint32_t flags; + strwav_codec codec; +} strwav_header; + +static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav); + + +/* STR+WAV - Blitz Games streams+header */ +VGMSTREAM * init_vgmstream_str_wav(STREAMFILE *streamFile) { + VGMSTREAM * vgmstream = NULL; + STREAMFILE * streamHeader = NULL; + strwav_header strwav = {0}; + off_t start_offset; + + + /* checks */ + if (!check_extensions(streamFile, "str")) + goto fail; + + /* get external header (extracted with filenames from bigfiles) */ + { + /* try with standard file.wav.str=body + file.wav=header (or file.wma.str + file.wma for Fuzion Frenzy (Xbox)) */ + char basename[PATH_LIMIT]; + get_streamfile_basename(streamFile,basename,PATH_LIMIT); + streamHeader = open_streamfile_by_filename(streamFile, basename); + if (!streamHeader) { + /* try again with file.str=body + file.wav=header [Bad Boys II (PS2), Zapper (PS2)] */ + streamHeader = open_streamfile_by_ext(streamFile, "wav"); + if (!streamHeader) { + /* try again with file.str=body + file.sth=header (renamed/fake extension) */ + streamHeader = open_streamfile_by_ext(streamFile, "sth"); + if (!streamHeader) goto fail; + } + } + else { + if (!check_extensions(streamHeader, "wav,wma")) + goto fail; + } + } + + /* detect version */ + if (!parse_header(streamHeader, &strwav)) + goto fail; + + if (strwav.flags == 0) + goto fail; + if (strwav.channels > 8) + goto fail; + + /* &0x01: loop?, &0x02: non-mono?, &0x04: stream???, &0x08: unused? */ + if (strwav.flags != 0x07 && strwav.flags != 0x06 && strwav.flags != 0x05 && strwav.flags != 0x04 && strwav.flags != 0x02) { + VGM_LOG("STR+WAV: unknown flags\n"); + goto fail; + } + + + start_offset = 0x00; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(strwav.channels,strwav.loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = strwav.sample_rate; + vgmstream->num_samples = strwav.num_samples; + if (strwav.loop_flag) { + vgmstream->loop_start_sample = strwav.loop_start; + vgmstream->loop_end_sample = strwav.loop_end; + } + + vgmstream->meta_type = meta_STR_WAV; + + switch(strwav.codec) { + case PSX: + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = strwav.interleave; + break; + + case DSP: + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = strwav.interleave; + + /* get coefs */ + { + int i, ch; + for (ch = 0; ch < vgmstream->channels; ch++) { + for (i = 0; i < 16; i++) { + off_t coef_offset; + if (strwav.dsps_table) /* mini table with offsets to DSP headers */ + coef_offset = read_32bitBE(strwav.dsps_table+0x04*ch,streamHeader) + 0x1c; + else if (strwav.coefs_table) /* mini table with offsets to coefs then header */ + coef_offset = read_32bitBE(strwav.coefs_table+0x04*ch,streamHeader); + else + coef_offset = strwav.coefs_offset + 0x60*ch; + vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(coef_offset+i*0x02,streamHeader); + } + } + } + break; + + case XBOX: + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + if (strwav.channels > 2) goto fail; //todo multistreams are 2ch*N interleaved using ~0xD000 + break; + +#ifdef VGM_USE_FFMPEG + case WMA: { + ffmpeg_codec_data *ffmpeg_data = NULL; + + ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,get_streamfile_size(streamFile)); + if (!ffmpeg_data) goto fail; + vgmstream->codec_data = ffmpeg_data; + vgmstream->coding_type = coding_FFmpeg; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = ffmpeg_data->totalSamples; + if (vgmstream->channels != ffmpeg_data->channels) + goto fail; + + break; + } +#endif + + default: + goto fail; + } + + + if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + goto fail; + close_streamfile(streamHeader); + return vgmstream; + +fail: + close_streamfile(streamHeader); + close_vgmstream(vgmstream); + return NULL; +} + + + +/* Parse header versions. Almost every game uses its own variation (struct serialization?), + * so detection could be improved once enough versions are known. */ +static int parse_header(STREAMFILE* streamHeader, strwav_header* strwav) { + size_t header_size; + + if (read_32bitBE(0x00,streamHeader) != 0x00000000) + goto fail; + + header_size = get_streamfile_size(streamHeader); + + //todo loop start/end values may be off for some headers + + /* Fuzion Frenzy (Xbox)[2001] wma */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000900 && + read_32bitLE(0x20,streamHeader) == 0 && /* no num_samples */ + read_32bitLE(0x24,streamHeader) == read_32bitLE(0x80,streamHeader) && /* sample rate repeat */ + read_32bitLE(0x28,streamHeader) == 0x10 && + header_size == 0x110 /* no value in header */ + ) { + strwav->num_samples = read_32bitLE(0x20,streamHeader); /* 0 but will be rectified later */ + strwav->sample_rate = read_32bitLE(0x24,streamHeader); + strwav->flags = read_32bitLE(0x2c,streamHeader); + strwav->loop_start = 0; + strwav->loop_end = 0; + + strwav->channels = read_32bitLE(0x60,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = 0; + + strwav->codec = WMA; + ;VGM_LOG("STR+WAV: header Fuzion Frenzy (Xbox)\n"); + return 1; + } + + /* Taz: Wanted (GC)[2002] */ + /* Cubix Robots for Everyone: Showdown (GC)[2003] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000900 && + read_32bitBE(0x24,streamHeader) == read_32bitBE(0x90,streamHeader) && /* sample rate repeat */ + read_32bitBE(0x28,streamHeader) == 0x10 && + read_32bitBE(0xa0,streamHeader) == header_size /* ~0x3C0 */ + ) { + strwav->num_samples = read_32bitBE(0x20,streamHeader); + strwav->sample_rate = read_32bitBE(0x24,streamHeader); + strwav->flags = read_32bitBE(0x2c,streamHeader); + strwav->loop_start = read_32bitBE(0xb8,streamHeader); + strwav->loop_end = read_32bitBE(0xbc,streamHeader); + + strwav->channels = read_32bitBE(0x50,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000; + + strwav->coefs_offset = 0xdc; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header Taz: Wanted (GC)\n"); + return 1; + } + + /* The Fairly OddParents - Breakin' da Rules (Xbox)[2003] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000900 && + read_32bitLE(0x24,streamHeader) == read_32bitLE(0xb0,streamHeader) && /* sample rate repeat */ + read_32bitLE(0x28,streamHeader) == 0x10 && + read_32bitLE(0xc0,streamHeader)*0x04 + read_32bitLE(0xc4,streamHeader) == header_size /* ~0xe0 + variable */ + ) { + strwav->num_samples = read_32bitLE(0x20,streamHeader); + strwav->sample_rate = read_32bitLE(0x24,streamHeader); + strwav->flags = read_32bitLE(0x2c,streamHeader); + strwav->loop_start = read_32bitLE(0x38,streamHeader); + strwav->loop_end = strwav->num_samples; + + strwav->channels = read_32bitLE(0x70,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0xD000 : 0x0; + + strwav->codec = XBOX; + ;VGM_LOG("STR+WAV: header The Fairly OddParents (Xbox)\n"); + return 1; + } + + /* Bad Boys II (GC)[2004] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000800 && + read_32bitBE(0x24,streamHeader) == read_32bitBE(0xb0,streamHeader) && /* sample rate repeat */ + read_32bitBE(0x24,streamHeader) == read_32bitBE(read_32bitBE(0xe0,streamHeader)+0x08,streamHeader) && /* sample rate vs 1st DSP header */ + read_32bitBE(0x28,streamHeader) == 0x10 && + read_32bitBE(0xc0,streamHeader)*0x04 + read_32bitBE(0xc4,streamHeader) == header_size /* variable + variable */ + ) { + strwav->num_samples = read_32bitBE(0x20,streamHeader); + strwav->sample_rate = read_32bitBE(0x24,streamHeader); + strwav->flags = read_32bitBE(0x2c,streamHeader); + strwav->loop_start = read_32bitBE(0xd8,streamHeader); + strwav->loop_end = read_32bitBE(0xdc,streamHeader); + + strwav->channels = read_32bitBE(0x70,streamHeader) * read_32bitBE(0x88,streamHeader); /* tracks of Nch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000; + + strwav->dsps_table = 0xe0; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header Bad Boys II (GC)\n"); + return 1; + } +#if 0 + if ( read_32bitBE(0x04,streamHeader) == 0x00000800 && + read_32bitBE(0x24,streamHeader) == read_32bitBE(0xb0,streamHeader) && /* sample rate repeat */ + read_32bitBE(0x24,streamHeader) == read_32bitBE(read_32bitBE(0xf0,streamHeader)+0x08,streamHeader) && /* sample rate vs 1st DSP header */ + read_32bitBE(0x28,streamHeader) == 0x10 && + read_32bitBE(0xc0,streamHeader)*0x04 + read_32bitBE(0xc4,streamHeader) == header_size /* variable + variable */ + ) { + strwav->num_samples = read_32bitBE(0x20,streamHeader); + strwav->sample_rate = read_32bitBE(0x24,streamHeader); + strwav->flags = read_32bitBE(0x2c,streamHeader); + strwav->loop_start = read_32bitBE(0xd8,streamHeader); + strwav->loop_end = read_32bitBE(0xdc,streamHeader); + + strwav->channels = read_32bitBE(0x70,streamHeader) * read_32bitBE(0x88,streamHeader); /* tracks of Nch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000; + + strwav->dsps_table = 0xf0; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header Pac-Man World 3 (GC)\n"); + return 1; + } +#endif + /* Bad Boys II (PS2)[2004] */ + /* Pac-Man World 3 (PS2)[2005] */ + if ((read_32bitBE(0x04,streamHeader) == 0x00000800 || + read_32bitBE(0x04,streamHeader) == 0x01000800) && /* rare (PW3 mu_spectral1_explore_2) */ + read_32bitLE(0x24,streamHeader) == read_32bitLE(0x70,streamHeader) && /* sample rate repeat */ + read_32bitLE(0x28,streamHeader) == 0x10 && + read_32bitLE(0x78,streamHeader)*0x04 + read_32bitLE(0x7c,streamHeader) == header_size /* ~0xe0 + variable */ + ) { + strwav->num_samples = read_32bitLE(0x20,streamHeader); + strwav->sample_rate = read_32bitLE(0x24,streamHeader); + strwav->flags = read_32bitLE(0x2c,streamHeader); + strwav->loop_start = read_32bitLE(0x38,streamHeader); + strwav->interleave = read_32bitLE(0x40,streamHeader) == 1 ? 0x8000 : 0x4000; + strwav->loop_end = read_32bitLE(0x54,streamHeader); + + strwav->channels = read_32bitLE(0x40,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x4000 : 0x8000; + + strwav->codec = PSX; + ;VGM_LOG("STR+WAV: header Bad Boys II (PS2)\n"); + return 1; + } + + /* Zapper: One Wicked Cricket! (PS2)[2005] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000900 && + read_32bitLE(0x24,streamHeader) == read_32bitLE(0x70,streamHeader) && /* sample rate repeat */ + read_32bitLE(0x28,streamHeader) == 0x10 && + read_32bitLE(0x7c,streamHeader) == header_size /* ~0xD0 */ + ) { + strwav->num_samples = read_32bitLE(0x20,streamHeader); + strwav->sample_rate = read_32bitLE(0x24,streamHeader); + strwav->flags = read_32bitLE(0x2c,streamHeader); + strwav->loop_start = read_32bitLE(0x38,streamHeader); + strwav->loop_end = read_32bitLE(0x54,streamHeader); + + strwav->channels = read_32bitLE(0x40,streamHeader) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x4000 : 0x8000; + + strwav->codec = PSX; + ;VGM_LOG("STR+WAV: header Zapper (PS2)\n"); + return 1; + } + + /* Zapper: One Wicked Cricket! (GC)[2005] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000900 && + read_32bitBE(0x24,streamHeader) == read_32bitBE(0xB0,streamHeader) && /* sample rate repeat */ + read_32bitBE(0x28,streamHeader) == 0x10 && + read_32bitLE(0xc0,streamHeader) == header_size /* variable LE size */ + ) { + strwav->num_samples = read_32bitBE(0x20,streamHeader); + strwav->sample_rate = read_32bitBE(0x24,streamHeader); + strwav->flags = read_32bitBE(0x2c,streamHeader); + strwav->loop_start = read_32bitBE(0xd8,streamHeader); + strwav->loop_end = read_32bitBE(0xdc,streamHeader); + + strwav->channels = read_32bitBE(0x70,streamHeader) * read_32bitBE(0x88,streamHeader); /* tracks of Nch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000; + + strwav->dsps_table = 0xe0; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header Zapper (GC)\n"); + return 1; + } + + /* Pac-Man World 3 (GC)[2005] */ + /* SpongeBob SquarePants: Creature from the Krusty Krab (GC)[2006] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000800 && + read_32bitBE(0x24,streamHeader) == read_32bitBE(0xb0,streamHeader) && /* sample rate repeat */ + read_32bitBE(0x24,streamHeader) == read_32bitBE(read_32bitBE(0xf0,streamHeader)+0x08,streamHeader) && /* sample rate vs 1st DSP header */ + read_32bitBE(0x28,streamHeader) == 0x10 && + read_32bitBE(0xc0,streamHeader)*0x04 + read_32bitBE(0xc4,streamHeader) == read_32bitBE(0xe0,streamHeader) && /* main size */ + (read_32bitBE(0xe0,streamHeader) + read_32bitBE(0xe4,streamHeader)*0x40 == header_size || /* main size + extradata 1 (config? PMW3 cs2.wav) */ + read_32bitBE(0xe0,streamHeader) + read_32bitBE(0xe4,streamHeader)*0x08 == header_size) /* main size + extradata 2 (ids? SBSP 0_0_mu_hr.wav) */ + ) { + strwav->num_samples = read_32bitBE(0x20,streamHeader); + strwav->sample_rate = read_32bitBE(0x24,streamHeader); + strwav->flags = read_32bitBE(0x2c,streamHeader); + strwav->loop_start = read_32bitBE(0xd8,streamHeader); + strwav->loop_end = read_32bitBE(0xdc,streamHeader); + + strwav->channels = read_32bitBE(0x70,streamHeader) * read_32bitBE(0x88,streamHeader); /* tracks of Nch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x10000; + + strwav->dsps_table = 0xf0; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header SpongeBob SquarePants (GC)\n"); + return 1; + } + + /* SpongeBob SquarePants: Creature from the Krusty Krab (PS2)[2006] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000800 && + read_32bitLE(0x08,streamHeader) == 0x00000000 && + read_32bitLE(0x0c,streamHeader) != header_size && /* some ID */ + (header_size == 0x74 + read_32bitLE(0x64,streamHeader)*0x04 || + header_size == 0x78 + read_32bitLE(0x64,streamHeader)*0x04) + ) { + strwav->loop_start = read_32bitLE(0x24,streamHeader); //not ok? + strwav->num_samples = read_32bitLE(0x30,streamHeader); + strwav->loop_end = read_32bitLE(0x34,streamHeader); + strwav->sample_rate = read_32bitLE(0x38,streamHeader); + strwav->flags = read_32bitLE(0x3c,streamHeader); + + strwav->channels = read_32bitLE(0x64,streamHeader); /* tracks of 1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000; + + strwav->codec = PSX; + ;VGM_LOG("STR+WAV: header SpongeBob SquarePants (PS2)\n"); + return 1; + } + + /* Tak and the Guardians of Gross (PS2)[2008] */ + if ( read_32bitBE(0x04,streamHeader) == 0x00000800 && + read_32bitLE(0x08,streamHeader) != 0x00000000 && + read_32bitLE(0x0c,streamHeader) == header_size && /* ~0x80+0x04*ch */ + read_32bitLE(0x0c,streamHeader) == 0x80 + read_32bitLE(0x70,streamHeader)*0x04 + ) { + strwav->loop_start = read_32bitLE(0x24,streamHeader); //not ok? + strwav->num_samples = read_32bitLE(0x30,streamHeader); + strwav->loop_end = read_32bitLE(0x34,streamHeader); + strwav->sample_rate = read_32bitLE(0x38,streamHeader); + strwav->flags = read_32bitLE(0x3c,streamHeader); + + strwav->channels = read_32bitLE(0x70,streamHeader); /* tracks of 1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000; + + strwav->codec = PSX; + ;VGM_LOG("STR+WAV: header Tak (PS2)\n"); + return 1; + } + + /* Tak and the Guardians of Gross (Wii)[2008] */ + /* The House of the Dead: Overkill (Wii)[2009] (not Blitz but still the same format) */ + if ((read_32bitBE(0x04,streamHeader) == 0x00000800 || + read_32bitBE(0x04,streamHeader) == 0x00000700) && /* rare? */ + read_32bitLE(0x08,streamHeader) != 0x00000000 && + read_32bitBE(0x0c,streamHeader) == header_size && /* variable per DSP header */ + read_32bitBE(0x38,streamHeader) == read_32bitBE(read_32bitBE(0x7c,streamHeader)+0x38,streamHeader) /* sample rate vs 1st DSP header */ + ) { + strwav->loop_start = 0; //read_32bitLE(0x24,streamHeader); //not ok? + strwav->num_samples = read_32bitBE(0x30,streamHeader); + strwav->loop_end = read_32bitBE(0x34,streamHeader); + strwav->sample_rate = read_32bitBE(0x38,streamHeader); + strwav->flags = read_32bitBE(0x3c,streamHeader); + + strwav->channels = read_32bitBE(0x70,streamHeader); /* tracks of 1ch */ + strwav->loop_flag = strwav->flags & 0x01; + strwav->interleave = strwav->channels > 4 ? 0x4000 : 0x8000; + + strwav->coefs_table = 0x7c; + strwav->codec = DSP; + ;VGM_LOG("STR+WAV: header Tak (Wii)\n"); + return 1; + } + + + /* unknown */ + goto fail; + +fail: + return 0; +} diff --git a/src/meta/wii_str.c b/src/meta/wii_str.c deleted file mode 100644 index 460a5bad..00000000 --- a/src/meta/wii_str.c +++ /dev/null @@ -1,90 +0,0 @@ -#include "meta.h" -#include "../util.h" - -VGMSTREAM * init_vgmstream_wii_str(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; - STREAMFILE * infileSTH = NULL; - char filename[PATH_LIMIT]; - - char * filenameSTH = NULL; - - int i, j, channel_count, loop_flag; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("str",filename_extension(filename))) goto fail; - - /* check for .MIH file */ - filenameSTH=(char *)malloc(strlen(filename)+1); - - if (!filenameSTH) goto fail; - - strcpy(filenameSTH,filename); - strcpy(filenameSTH+strlen(filenameSTH)-3,"sth"); - - infileSTH = streamFile->open(streamFile,filenameSTH,STREAMFILE_DEFAULT_BUFFER_SIZE); - - /* STH File is necessary, so we can't confuse those file */ - /* with others .STR file as it is a very common extension */ - if (!infileSTH) goto fail; - - if(read_32bitLE(0x2C,infileSTH)!=0) - goto fail; - - channel_count = read_32bitBE(0x70,infileSTH); - - if(channel_count==1) - loop_flag = (read_32bitBE(0xD4,infileSTH)==0x00740000); - else - loop_flag = (read_32bitBE(0x124,infileSTH)==0x00740000); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x38,infileSTH); - - vgmstream->interleave_block_size=0x8000; - vgmstream->num_samples=read_32bitBE(0x34,infileSTH); - - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->layout_type = layout_interleave; - - vgmstream->meta_type = meta_WII_STR; - - if(loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset+=(off_t)(vgmstream->interleave_block_size*i); - - for(j=0; j<16; j++) { - vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(0xAC+(j*2)+(i*0x50),infileSTH); - } - } - } - - close_streamfile(infileSTH); infileSTH=NULL; - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (infileSTH) close_streamfile(infileSTH); - if (filenameSTH) {free(filenameSTH); filenameSTH=NULL;} - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index b2799f7e..a1a456a6 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -52,7 +52,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { 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, @@ -212,7 +211,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ps2_tk5, init_vgmstream_ps2_vsf_tta, init_vgmstream_ads, - init_vgmstream_wii_str, init_vgmstream_ps2_mcg, init_vgmstream_zsd, init_vgmstream_ps2_vgs, @@ -266,9 +264,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_ngc_dsp_mpds, init_vgmstream_dsp_str_ig, init_vgmstream_ea_swvr, - init_vgmstream_ngc_dsp_sth_str1, - init_vgmstream_ngc_dsp_sth_str2, - init_vgmstream_ngc_dsp_sth_str3, init_vgmstream_ps2_b1s, init_vgmstream_ps2_wad, init_vgmstream_dsp_xiii, @@ -424,6 +419,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = { init_vgmstream_cks, init_vgmstream_ckb, init_vgmstream_wv6, + init_vgmstream_str_wav, init_vgmstream_txth, /* should go at the end (lower priority) */ #ifdef VGM_USE_FFMPEG diff --git a/src/vgmstream.h b/src/vgmstream.h index f976b0ab..80b2c70c 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -341,7 +341,7 @@ typedef enum { meta_PS2_VAGm, /* VAGp Mono File */ meta_PS2_pGAV, /* VAGp with Little Endian Header */ meta_PSX_GMS, /* GMS File (used in PS1 & PS2) [no header_id] */ - meta_PS2_STR, /* Pacman STR+STH files */ + meta_STR_WAV, /* Blitz Games STR+WAV files */ meta_PS2_ILD, /* ILD File */ meta_PS2_PNB, /* PsychoNauts Bgm File */ meta_PS2_VAGs, /* VAG Stereo from Kingdom Hearts */ @@ -505,7 +505,6 @@ typedef enum { meta_PS2_GBTS, /* Pop'n'Music 9 Audio File */ meta_NGC_DSP_IADP, /* Gamecube Interleave DSP */ meta_PS2_TK5, /* Tekken 5 Stream Files */ - meta_WII_STR, /* House of The Dead Overkill STR+STH */ meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ meta_ZSD, /* Dragon Booster ZSD */ meta_RedSpark, /* "RedSpark" RSD (MadWorld) */ @@ -545,7 +544,6 @@ typedef enum { meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */ meta_DSP_STR_IG, /* Micro Machines, Superman Superman: Shadow of Apokolis */ meta_EA_SWVR, /* Future Cop L.A.P.D., Freekstyle */ - meta_NGC_DSP_STH_STR, /* SpongeBob Squarepants (NGC), Taz Wanted (NGC), Cubix (NGC), Tak (WII)*/ meta_PS2_B1S, /* 7 Wonders of the ancient world */ meta_PS2_WAD, /* The golden Compass */ meta_DSP_XIII, /* XIII, possibly more (Ubisoft header???) */