diff --git a/src/formats.c b/src/formats.c index 1043ec80..f098ac6c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -925,7 +925,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_EXST, "Sony EXST header"}, {meta_SVAG_KCET, "Konami SVAG header"}, {meta_PS_HEADERLESS, "Headerless PS-ADPCM raw header"}, - {meta_PS2_MIB_MIH, "Sony MultiStream MIH+MIB header"}, + {meta_MIB_MIH, "Sony MultiStream MIH+MIB header"}, {meta_DSP_MPDSP, "Single DSP header stereo by .mpdsp extension"}, {meta_PS2_MIC, "KOEI .MIC header"}, {meta_DSP_JETTERS, "Double DSP header stereo by _lr.dsp extension"}, diff --git a/src/meta/mib_mih.c b/src/meta/mib_mih.c index e015f56b..bb4a3920 100644 --- a/src/meta/mib_mih.c +++ b/src/meta/mib_mih.c @@ -1,72 +1,72 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* MIB+MIH - SCEE MultiStream interleaved bank (header+data) [namCollection: Ace Combat 2 (PS2), Rampage: Total Destruction (PS2)] */ -VGMSTREAM * init_vgmstream_mib_mih(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - 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 */ - if (!check_extensions(streamFile, "mib")) - goto fail; - - streamHeader = open_streamfile_by_ext(streamFile,"mih"); - if (!streamHeader) 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(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); - } - - data_size = frame_count * frame_size; - if (frame_last) - data_size -= frame_size - frame_last; /* last frame has less usable data */ - data_size *= channel_count; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - - vgmstream->meta_type = meta_PS2_MIB_MIH; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = frame_size; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - close_streamfile(streamHeader); - return vgmstream; - -fail: -close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* MIB+MIH - SCEE MultiStream interleaved bank (header+data) [namCollection: Ace Combat 2 (PS2), Rampage: Total Destruction (PS2)] */ +VGMSTREAM* init_vgmstream_mib_mih(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sh = NULL; + off_t header_offset, start_offset; + size_t data_size, frame_size, frame_last, frame_count; + int channels, loop_flag, sample_rate; + + /* check extension */ + if (!check_extensions(sf, "mib")) + goto fail; + + sh = open_streamfile_by_ext(sf,"mih"); + if (!sh) goto fail; + + header_offset = 0x00; + + if (read_u32le(0x00,sh) != 0x40) { /* header size */ + /* Marc Ecko's Getting Up (PS2) has a name at the start (hack, not standard .mib+mih) */ + size_t name_size = read_u32le(0x00, sh); + if (read_u32le(0x04 + name_size, sh) == 0x40 && + read_u32le(0x04 + name_size + 0x04, sh) == 0x40) { + 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 = read_u32le(header_offset + 0x05,sh) & 0x00FFFFFF; /* 24b */ + channels = read_u32le(header_offset + 0x08,sh); + sample_rate = read_u32le(header_offset + 0x0c,sh); + frame_size = read_u32le(header_offset + 0x10,sh); + frame_count = read_u32le(header_offset + 0x14,sh); + if (frame_count == 0) { /* rarely [Gladius (PS2)] */ + frame_count = get_streamfile_size(sf) / (frame_size * channels); + } + + data_size = frame_count * frame_size; + if (frame_last) + data_size -= frame_size - frame_last; /* last frame has less usable data */ + data_size *= channels; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MIB_MIH; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(data_size, channels); + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = frame_size; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + close_streamfile(sh); + return vgmstream; + +fail: + close_streamfile(sh); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/msb_msh.c b/src/meta/msb_msh.c index 424bb6c9..14ade6c7 100644 --- a/src/meta/msb_msh.c +++ b/src/meta/msb_msh.c @@ -1,85 +1,82 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* MSB+MSH - SCEE MultiStream flat bank [namCollection: Ace Combat 2 (PS2) sfx, EyeToy Play (PS2)] */ -VGMSTREAM * init_vgmstream_msb_msh(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - off_t start_offset, header_offset = 0; - size_t stream_size; - int loop_flag = 0, channel_count, sample_rate; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* checks */ - if (!check_extensions(streamFile, "msb")) - goto fail; - - streamHeader = open_streamfile_by_ext(streamFile, "msh"); - if (!streamHeader) goto fail; - - if (read_32bitLE(0x00,streamHeader) != get_streamfile_size(streamHeader)) - goto fail; - /* 0x04: unknown */ - - /* parse entries */ - { - int i; - int entries = read_32bitLE(0x08,streamHeader); - - total_subsongs = 0; - if (target_subsong == 0) target_subsong = 1; - - for (i = 0; i < entries; i++) { - if (read_32bitLE(0x0c + 0x10*i, streamHeader) == 0) /* size 0 = empty entry */ - continue; - - total_subsongs++; - if (total_subsongs == target_subsong && !header_offset) { - header_offset = 0x0c + 0x10*i; - } - } - - if (!header_offset) goto fail; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - } - - - - loop_flag = 0; - channel_count = 1; - - stream_size = read_32bitLE(header_offset+0x00, streamHeader); - if (read_32bitLE(header_offset+0x04, streamHeader) != 0) /* stereo flag? */ - goto fail; - start_offset = read_32bitLE(header_offset+0x08, streamHeader); - sample_rate = read_32bitLE(header_offset+0x0c, streamHeader); /* Ace Combat 2 seems to set wrong values but probably their bug */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = ps_bytes_to_samples(stream_size,channel_count); - - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - vgmstream->meta_type = meta_MSB_MSH; - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - close_streamfile(streamHeader); - return vgmstream; - -fail: - close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* MSB+MSH - SCEE MultiStream flat bank [namCollection: Ace Combat 2 (PS2) sfx, EyeToy Play (PS2)] */ +VGMSTREAM* init_vgmstream_msb_msh(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sh = NULL; + off_t start_offset, header_offset = 0; + size_t stream_size; + int loop_flag, channels, sample_rate; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!check_extensions(sf, "msb")) + goto fail; + + sh = open_streamfile_by_ext(sf, "msh"); + if (!sh) goto fail; + + if (read_u32le(0x00,sh) != get_streamfile_size(sh)) + goto fail; + /* 0x04: unknown */ + + /* parse entries */ + { + int i; + int entries = read_s32le(0x08,sh); + + total_subsongs = 0; + if (target_subsong == 0) target_subsong = 1; + + for (i = 0; i < entries; i++) { + if (read_u32le(0x0c + 0x10*i, sh) == 0) /* size 0 = empty entry */ + continue; + + total_subsongs++; + if (total_subsongs == target_subsong && !header_offset) { + header_offset = 0x0c + 0x10*i; + } + } + + if (!header_offset) goto fail; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + } + + + loop_flag = 0; + channels = 1; + + stream_size = read_u32le(header_offset+0x00, sh); + if (read_u32le(header_offset+0x04, sh) != 0) /* stereo flag? */ + goto fail; + start_offset = read_u32le(header_offset+0x08, sh); + sample_rate = read_u32le(header_offset+0x0c, sh); /* Ace Combat 2 seems to set wrong values but probably their bug */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MSB_MSH; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + close_streamfile(sh); + return vgmstream; + +fail: + close_streamfile(sh); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.h b/src/vgmstream.h index 6125faa0..dfa5bfb7 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -362,7 +362,7 @@ typedef enum { meta_PS2_EXST, /* Shadow of Colossus EXST */ meta_SVAG_KCET, meta_PS_HEADERLESS, /* headerless PS-ADPCM */ - meta_PS2_MIB_MIH, /* MIB File + MIH Header*/ + meta_MIB_MIH, meta_PS2_MIC, /* KOEI MIC File */ meta_PS2_VAGi, /* VAGi Interleaved File */ meta_PS2_VAGp, /* VAGp Mono File */