From a3be024fe2608acdc56b33c413cb2a9711b27ab9 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Fri, 17 May 2024 12:20:45 +0300 Subject: [PATCH] MIH+MIB: merge MIC parser --- src/libvgmstream.vcxproj | 1 - src/libvgmstream.vcxproj.filters | 3 - src/meta/mib_mih.c | 99 +++++++++++++++++++++++--------- src/meta/ps2_mihb.c | 53 ----------------- 4 files changed, 73 insertions(+), 83 deletions(-) delete mode 100644 src/meta/ps2_mihb.c diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 0421dc0c..3e0ad3e5 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -584,7 +584,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index a9e47374..74eb40ad 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1573,9 +1573,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 bb4a3920..2c37bd69 100644 --- a/src/meta/mib_mih.c +++ b/src/meta/mib_mih.c @@ -1,48 +1,97 @@ #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) { +static VGMSTREAM* parse_multistream_header(STREAMFILE* sf_head, STREAMFILE* sf_body, off_t header_offset, off_t start_offset); + +/* MIH+MIB - SCEE MultiStream interleaved bank (header+data) [namCollection: Ace Combat 2 (PS2), Rampage: Total Destruction (PS2)] */ +VGMSTREAM* init_vgmstream_mib_mih(STREAMFILE* sf_body) { VGMSTREAM* vgmstream = NULL; - STREAMFILE* sh = NULL; + STREAMFILE* sf_head = 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; + if (!check_extensions(sf_body, "mib")) + return NULL; - sh = open_streamfile_by_ext(sf,"mih"); - if (!sh) goto fail; + sf_head = open_streamfile_by_ext(sf_body, "mih"); + if (!sf_head) goto fail; header_offset = 0x00; + start_offset = 0x00; - if (read_u32le(0x00,sh) != 0x40) { /* header size */ + if (read_u32le(0x00, sf_head) != 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) { + size_t name_size = read_u32le(0x00, sf_head); + if (read_u32le(0x04 + name_size + 0x00, sf_head) == 0x40 && + read_u32le(0x04 + name_size + 0x04, sf_head) == 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; + vgmstream = parse_multistream_header(sf_head, sf_body, header_offset, start_offset); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MIB_MIH; + + close_streamfile(sf_head); + return vgmstream; + +fail: + close_streamfile(sf_head); + close_vgmstream(vgmstream); + return NULL; +} + +/* MIC/MIHB - SCEE MultiStream interleaved bank (merged MIH+MIB) [Rogue Trooper (PS2), The Sims 2 (PS2)] */ +VGMSTREAM* init_vgmstream_ps2_mihb(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t header_offset, start_offset; + + /* check extension */ + /* .mic: official extension + * (extensionless): The Urbz (PS2), The Sims 2 series (PS2) + * .mihb: assumed? */ + if (!check_extensions(sf, "mic,,mihb")) + return NULL; + if (read_u32le(0x00, sf) != 0x40) /* header size */ + return NULL; + + header_offset = 0x00; + start_offset = 0x40; + + vgmstream = parse_multistream_header(sf, sf, header_offset, start_offset); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_PS2_MIHB; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} + +static VGMSTREAM* parse_multistream_header(STREAMFILE* sf_head, STREAMFILE* sf_body, off_t header_offset, off_t start_offset) { + VGMSTREAM* vgmstream = NULL; + size_t data_size, frame_size, frame_last, frame_count; + int channels, loop_flag, sample_rate; + + loop_flag = 0; /* MIB+MIH/MIC don't loop (nor use PS-ADPCM flags) per spec */ /* 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 (read_u8(header_offset + 0x04, sf_head) != 0x20) goto fail; + frame_last = read_u32le(header_offset + 0x04, sf_head) >> 8; /* 24b */ + channels = read_u32le(header_offset + 0x08, sf_head); + sample_rate = read_u32le(header_offset + 0x0c, sf_head); + frame_size = read_u32le(header_offset + 0x10, sf_head); + frame_count = read_u32le(header_offset + 0x14, sf_head); if (frame_count == 0) { /* rarely [Gladius (PS2)] */ - frame_count = get_streamfile_size(sf) / (frame_size * channels); + frame_count = (get_streamfile_size(sf_body) - start_offset) / (frame_size * channels); } - data_size = frame_count * frame_size; + data_size = frame_count * frame_size; if (frame_last) data_size -= frame_size - frame_last; /* last frame has less usable data */ data_size *= channels; @@ -52,7 +101,6 @@ VGMSTREAM* init_vgmstream_mib_mih(STREAMFILE* sf) { 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); @@ -60,13 +108,12 @@ VGMSTREAM* init_vgmstream_mib_mih(STREAMFILE* sf) { vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = frame_size; - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + if (!vgmstream_open_stream(vgmstream, sf_body, start_offset)) goto fail; - close_streamfile(sh); + return vgmstream; fail: - close_streamfile(sh); close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/ps2_mihb.c b/src/meta/ps2_mihb.c deleted file mode 100644 index c5d6f4f8..00000000 --- a/src/meta/ps2_mihb.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* MIC/MIHB - SCEE MultiStream interleaved bank (merged MIH+MIB) [Rogue Trooper (PS2), The Sims 2 (PS2)] */ -VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - size_t data_size, frame_size, frame_last, frame_count; - int channel_count, loop_flag; - - /* check extension */ - /* .mic: official extension, .mihb: assumed? */ - if (!check_extensions(streamFile, "mic,mihb")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x40000000) /* header size */ - goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x08,streamFile); - start_offset = 0x40; - - /* frame_size * frame_count * channels = data_size, but last frame has less usable data */ - { - /* 0x04: padding (0x20, MIH header must be multiple of 0x40) */ - frame_last = (uint16_t)read_16bitLE(0x05,streamFile); - frame_size = read_32bitLE(0x10,streamFile); - frame_count = read_32bitLE(0x14,streamFile); - - data_size = frame_count * frame_size; - data_size -= frame_last ? (frame_size-frame_last) : 0; - data_size *= channel_count; - } - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(0x0C,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - - vgmstream->meta_type = meta_PS2_MIHB; - 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; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -}