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;
-}