diff --git a/src/formats.c b/src/formats.c index a2713aaf..7a6e685c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -191,7 +191,6 @@ static const char* extension_list[] = { "hdr", "hgc1", "his", - "hlwav", "hps", "hsf", "hx2", @@ -1028,7 +1027,7 @@ static const meta_info meta_info_list[] = { {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, {meta_WII_BNS, "Nintendo BNS header"}, {meta_WII_WAS, "Sumo Digital iSWS header"}, - {meta_XBOX_HLWAV, "Half Life 2 bgm header"}, + {meta_XBOX_HLWAV, "Half-Life 2 .WAV header"}, {meta_MYSPD, "U-Sing .MYSPD header"}, {meta_HIS, "Her Interactive HIS header"}, {meta_PS2_AST, "KOEI AST header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index a301fc29..56dde1e7 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -512,7 +512,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 1bf4f290..82c5ac4c 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1072,9 +1072,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/mib_mih.c b/src/meta/mib_mih.c index 6e451b56..e015f56b 100644 --- a/src/meta/mib_mih.c +++ b/src/meta/mib_mih.c @@ -5,8 +5,8 @@ VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; STREAMFILE * streamHeader = NULL; - off_t start_offset; - size_t data_size, frame_size, frame_last, frame_count; + off_t header_offset, start_offset; + size_t data_size, frame_size, frame_last, frame_count, name_size; int channel_count, loop_flag, sample_rate; /* check extension */ @@ -16,18 +16,28 @@ VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { streamHeader = open_streamfile_by_ext(streamFile,"mih"); if (!streamHeader) goto fail; - if (read_32bitBE(0x00,streamHeader) != 0x40000000) /* header size */ - goto fail; + header_offset = 0x00; + + if (read_32bitLE(0x00,streamHeader) != 0x40) { /* header size */ + name_size = read_32bitLE(0x00, streamHeader); + if (read_32bitLE(0x04 + name_size, streamHeader) == 0x40 && + read_32bitLE(0x04 + name_size + 0x04, streamHeader) == 0x40) { + /* Marc Ecko's Getting Up (PS2) has a name at the start */ + header_offset = 0x04 + name_size + 0x04; + } else { + goto fail; + } + } loop_flag = 0; /* MIB+MIH don't loop (nor use PS-ADPCM flags) per spec */ start_offset = 0x00; /* 0x04: padding size (always 0x20, MIH header must be multiple of 0x40) */ - frame_last = (uint32_t)read_32bitLE(0x05,streamHeader) & 0x00FFFFFF; /* 24b */ - channel_count = read_32bitLE(0x08,streamHeader); - sample_rate = read_32bitLE(0x0c,streamHeader); - frame_size = read_32bitLE(0x10,streamHeader); - frame_count = read_32bitLE(0x14,streamHeader); + frame_last = (uint32_t)read_32bitLE(header_offset + 0x05,streamHeader) & 0x00FFFFFF; /* 24b */ + channel_count = read_32bitLE(header_offset + 0x08,streamHeader); + sample_rate = read_32bitLE(header_offset + 0x0c,streamHeader); + frame_size = read_32bitLE(header_offset + 0x10,streamHeader); + frame_count = read_32bitLE(header_offset + 0x14,streamHeader); if (frame_count == 0) { /* rarely [Gladius (PS2)] */ frame_count = get_streamfile_size(streamFile) / (frame_size * channel_count); } diff --git a/src/meta/xbox_hlwav.c b/src/meta/xbox_hlwav.c deleted file mode 100644 index 6a62ec3c..00000000 --- a/src/meta/xbox_hlwav.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* HLWAV (from Half Life 2 [XBOX]) */ -VGMSTREAM * init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("hlwav",filename_extension(filename))) goto fail; - - /* check header and size */ - if ((read_32bitBE(0x00,streamFile) != 0x14000000)) goto fail; - if (((read_32bitLE(0x4,streamFile) + (read_32bitLE(0x8,streamFile))) != get_streamfile_size(streamFile))) goto fail; - - loop_flag = (read_32bitLE(0xC,streamFile)!= 0xFFFFFFFF); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x8,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = 22050; - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = read_32bitLE(0x4,streamFile)/2/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile)/2/channel_count; - vgmstream->loop_end_sample = read_32bitLE(0xC,streamFile)/2/channel_count; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2; - vgmstream->meta_type = meta_XBOX_HLWAV; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/xmv_valve.c b/src/meta/xmv_valve.c index 6bc81a28..c0e58752 100644 --- a/src/meta/xmv_valve.c +++ b/src/meta/xmv_valve.c @@ -1,10 +1,82 @@ #include "meta.h" #include "../coding/coding.h" -/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine */ +/* .WAV - from Half-Life 2 (Xbox) */ +VGMSTREAM *init_vgmstream_xbox_hlwav(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; + uint32_t header_size, data_size, start_offset, sample_rate; + int32_t loop_start; + uint8_t format, freq_mode, channels; + int loop_flag; + + /* checks */ + if (!check_extensions(streamFile, "wav,lwav")) + goto fail; + + /* check header and size */ + header_size = read_u32le(0x00, streamFile); + if (header_size != 0x14) + goto fail; + + data_size = read_u32le(0x04, streamFile); + start_offset = read_u32le(0x08, streamFile); + if (data_size != get_streamfile_size(streamFile) - start_offset) + goto fail; + + loop_start = read_s32le(0x0c, streamFile); + format = read_u8(0x12, streamFile); + freq_mode = read_u8(0x13, streamFile) & 0x0F; + channels = (read_u8(0x13, streamFile) >> 4) & 0x0F; + + switch (freq_mode) { + case 0x00: sample_rate = 11025; break; + case 0x01: sample_rate = 22050; break; + case 0x02: sample_rate = 44100; break; + default: goto fail; + } + + loop_flag = (loop_start != -1); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + /* fill in the vital statistics */ + vgmstream->meta_type = meta_XBOX_HLWAV; + vgmstream->sample_rate = sample_rate; + vgmstream->loop_start_sample = loop_start; + + switch (format) { + case 0x00: /* PCM */ + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 16); + vgmstream->loop_end_sample = vgmstream->num_samples; /* always loops from the end */ + break; + case 0x01: /* XBOX ADPCM */ + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, channels); + vgmstream->loop_end_sample = vgmstream->num_samples; + break; + default: + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +/* .360.WAV, .PS3.WAV - from Valve games running on Source Engine, evolution of Xbox .WAV format */ /* [The Orange Box (X360), Portal 2 (PS3/X360), Counter-Strike: Global Offensive (PS3/X360)] */ -VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { - VGMSTREAM* vgmstream = NULL; +VGMSTREAM *init_vgmstream_xmv_valve(STREAMFILE *streamFile) { + VGMSTREAM *vgmstream = NULL; int32_t loop_start; uint32_t start_offset, data_size, sample_rate, num_samples; uint16_t /*loop_block, loop_start_skip,*/ loop_end_skip; @@ -16,26 +88,26 @@ VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { goto fail; /* check header magic */ - if (read_32bitBE(0x00, streamFile) != 0x58575620) /* "XMV " */ + if (read_u32be(0x00, streamFile) != 0x58575620) /* "XMV " */ goto fail; /* only version 4 is known */ - if (read_32bitBE(0x04, streamFile) != 0x04) + if (read_u32be(0x04, streamFile) != 0x04) goto fail; - start_offset = read_32bitBE(0x10, streamFile); - data_size = read_32bitBE(0x14, streamFile); - num_samples = read_32bitBE(0x18, streamFile); - loop_start = read_32bitBE(0x1c, streamFile); + start_offset = read_u32be(0x10, streamFile); + data_size = read_u32be(0x14, streamFile); + num_samples = read_u32be(0x18, streamFile); + loop_start = read_s32be(0x1c, streamFile); /* XMA only */ - //loop_block = read_16bitBE(0x20, streamFile); - //loop_start_skip = read_16bitBE(0x22, streamFile); - loop_end_skip = read_16bitBE(0x24, streamFile); + //loop_block = read_u16be(0x20, streamFile); + //loop_start_skip = read_u16be(0x22, streamFile); + loop_end_skip = read_u16be(0x24, streamFile); - format = read_8bit(0x28, streamFile); - freq_mode = read_8bit(0x2a, streamFile); - channels = read_8bit(0x2b, streamFile); + format = read_u8(0x28, streamFile); + freq_mode = read_u8(0x2a, streamFile); + channels = read_u8(0x2b, streamFile); switch (freq_mode) { case 0x00: sample_rate = 11025; break; @@ -64,7 +136,7 @@ VGMSTREAM* init_vgmstream_xmv_valve(STREAMFILE* streamFile) { break; #ifdef VGM_USE_FFMPEG case 0x01: { /* XMA */ - ffmpeg_codec_data* ffmpeg_data; + ffmpeg_codec_data *ffmpeg_data; uint8_t buf[0x100]; int block_count, block_size; size_t bytes;