From 9be522ab5ba11df85c085e00ec6e7f2c3a352825 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Fri, 5 Jun 2020 14:30:40 +0300 Subject: [PATCH 1/4] Cleanup --- src/meta/ps2_joe.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/meta/ps2_joe.c b/src/meta/ps2_joe.c index dda438df..c3eea49d 100644 --- a/src/meta/ps2_joe.c +++ b/src/meta/ps2_joe.c @@ -8,7 +8,7 @@ VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; int channel_count, loop_flag, sample_rate; - int32_t num_samples, loop_start = 0, loop_end = 0; + int32_t num_samples; size_t file_size, data_size, unknown1, unknown2, interleave, padding_size; @@ -65,8 +65,6 @@ VGMSTREAM * init_vgmstream_ps2_joe(STREAMFILE *streamFile) { vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; vgmstream->stream_size = data_size; vgmstream->coding_type = coding_PSX; From b451c6e66770321e14c52bd461f14d168b9f1016 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Fri, 5 Jun 2020 14:31:10 +0300 Subject: [PATCH 2/4] KAT: Fixed PCM8 (should be signed) --- src/meta/kat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/kat.c b/src/meta/kat.c index 6b68b9c1..2e1f48a0 100644 --- a/src/meta/kat.c +++ b/src/meta/kat.c @@ -59,7 +59,7 @@ VGMSTREAM *init_vgmstream_kat(STREAMFILE *sf) { vgmstream->num_samples = yamaha_bytes_to_samples(data_size, channels); break; case 8: - vgmstream->coding_type = coding_PCM8_U; + vgmstream->coding_type = coding_PCM8; vgmstream->layout_type = layout_none; vgmstream->num_samples = pcm_bytes_to_samples(data_size, channels, 8); break; From 8c7771089925169dd409c76521208216c0820949 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Fri, 5 Jun 2020 14:31:56 +0300 Subject: [PATCH 3/4] Ubi SB: Fixes --- src/meta/ubi_sb.c | 48 ++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index 3ce00658..37fb622b 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -195,6 +195,7 @@ static int parse_dat_header(ubi_sb_header *sb, STREAMFILE *sf); static int parse_header(ubi_sb_header* sb, STREAMFILE* sf, off_t offset, int index); static int parse_sb(ubi_sb_header* sb, STREAMFILE* sf, int target_subsong); static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf_index, STREAMFILE* sf); +static VGMSTREAM *init_vgmstream_ubi_sb_silence(ubi_sb_header *sb, STREAMFILE *sf_index, STREAMFILE *sf); static int config_sb_platform(ubi_sb_header* sb, STREAMFILE* sf); static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf); @@ -476,7 +477,7 @@ static int bnm_parse_offsets(ubi_sb_header *sb, STREAMFILE *sf) { if (sb->is_streamed) return 1; - /* sounds are split into groups based on resource type and codec, the order is hardcoded */ + /* sounds are split into subblock based on resource type and codec, the order is hardcoded */ if (sb->version == 0x00000000 || sb->version == 0x00000200) { /* 0x14: MPDX, 0x18: MIDI, 0x1c: PCM, 0x20: APM, 0x24: streamed, 0x28: EOF */ switch (sb->stream_type) { @@ -506,7 +507,7 @@ static int bnm_parse_offsets(ubi_sb_header *sb, STREAMFILE *sf) { goto fail; } } else { - VGM_LOG("UBI BNM: Unknown group offsets for version %08x", sb->version); + VGM_LOG("UBI BNM: Unknown subblock offsets for version %08x", sb->version); goto fail; } @@ -623,11 +624,17 @@ fail: return 0; } -static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf) { +static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_index, STREAMFILE *sf) { VGMSTREAM *vgmstream = NULL; STREAMFILE *sf_data = NULL; if (sb->is_streamed) { + if (strcmp(sb->resource_name, "silence.wav") == 0) { + /* some Rayman 2 banks reference non-existent silence.wav, looks like some kind of hack? */ + sb->duration = (float)(sb->stream_size / sb->channels / 2) / (float)sb->sample_rate; + return init_vgmstream_ubi_sb_silence(sb, sf_index, sf); + } + sf_data = open_streamfile_by_filename(sf, sb->resource_name); if (!sf_data) { VGM_LOG("UBI DAT: no matching KAT found\n"); @@ -705,7 +712,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf) vgmstream = allocate_vgmstream(sb->channels, sb->loop_flag); if (!vgmstream) goto fail; - data_size = get_streamfile_size(sf) - sb->stream_offset; + data_size = get_streamfile_size(sf_data) - sb->stream_offset; vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; @@ -719,8 +726,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf) } break; } - case 0x04: - { /* standard WAV */ + case 0x04:{ /* standard WAV */ if (!sb->is_streamed) { VGM_LOG("Ubi DAT: Found RAM stream_type 0x04\n"); goto fail; @@ -1274,7 +1280,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_audio(ubi_sb_header* sb, STREAMFILE* sf_ STREAMFILE* sf_data = NULL; if (sb->is_dat) - return init_vgmstream_ubi_dat_main(sb, sf); + return init_vgmstream_ubi_dat_main(sb, sf_index, sf); /* open external stream if needed */ if (sb->is_streamed || sb->is_blk || sb->is_ps2_bnm) { @@ -1311,10 +1317,6 @@ static VGMSTREAM* init_vgmstream_ubi_sb_layer(ubi_sb_header* sb, STREAMFILE* sf_ size_t full_stream_size = sb->stream_size; int i, total_channels = 0; - if (sb->is_dat) { - return init_vgmstream_ubi_dat_main(sb, sf); - } - if (sb->is_ps2_old) { /* no blocked layout yet, just open it as normal file */ return init_vgmstream_ubi_sb_audio(sb, sf_index, sf); @@ -1709,7 +1711,7 @@ static int parse_type_audio_ps2_bnm(ubi_sb_header *sb, off_t offset, STREAMFILE sb->stream_size = read_32bit(offset + sb->cfg.audio_stream_size, sf); sb->stream_offset = read_32bit(offset + sb->cfg.audio_stream_offset, sf); sb->channels = read_8bit(offset + sb->cfg.audio_channels, sf); - sb->sample_rate = read_16bit(offset + sb->cfg.audio_sample_rate, sf); + sb->sample_rate = (uint16_t)read_16bit(offset + sb->cfg.audio_sample_rate, sf); if (sb->stream_size == 0) { VGM_LOG("UBI SB: bad stream size\n"); @@ -2360,8 +2362,8 @@ static int parse_offsets(ubi_sb_header* sb, STREAMFILE* sf) { if (sb->is_streamed) return 1; - /* Internal sounds are split into codec groups, with their offsets being relative to group start. - * A table contains sizes of each group, so we adjust offsets based on the group ID of our sound. + /* Internal sounds are split into subblock, with their offsets being relative to subblock start. + * A table contains sizes of each subblock, so we adjust offsets based on the subblock ID of our sound. * Headers normally only use 0 or 1, and section3 may only define id1 (which the internal sound would use). * May exist even for external streams only, and they often use id 1 too. */ @@ -2377,10 +2379,10 @@ static int parse_offsets(ubi_sb_header* sb, STREAMFILE* sf) { * 0x00: sec2 entry index * 0x04: sound offset * table 2 - for each entry: - * 0x00 - group ID + * 0x00 - subblock ID * 0x04 - size with padding included * 0x08 - size without padding - * 0x0c - absolute group offset + * 0x0c - absolute subblock offset */ for (i = 0; i < sb->section3_num; i++) { @@ -2405,7 +2407,7 @@ static int parse_offsets(ubi_sb_header* sb, STREAMFILE* sf) { } if (k == table2_num) { - VGM_LOG("UBI SM: Failed to find group %d in map %s\n", sb->subblock_id, sb->map_name); + VGM_LOG("UBI SM: Failed to find subblock %d in map %s\n", sb->subblock_id, sb->map_name); goto fail; } break; @@ -2417,11 +2419,11 @@ static int parse_offsets(ubi_sb_header* sb, STREAMFILE* sf) { } if (sb->stream_offset == 0) { - VGM_LOG("UBI SM: Failed to find offset for resource %d in group %d in map %s\n", sb->header_index, sb->subblock_id, sb->map_name); + VGM_LOG("UBI SM: Failed to find offset for resource %d in subblock %d in map %s\n", sb->header_index, sb->subblock_id, sb->map_name); goto fail; } } else { - /* banks store internal sounds after all headers and adjusted by the group table, find the matching entry */ + /* banks store internal sounds after all headers and adjusted by the subblock table, find the matching entry */ off_t sounds_offset = sb->section3_offset + sb->cfg.section3_entry_size*sb->section3_num; if (sb->cfg.is_padded_sounds_offset) @@ -2620,10 +2622,10 @@ static void config_sb_entry(ubi_sb_header* sb, size_t section1_size_entry, size_ sb->cfg.section2_entry_size = section2_size_entry; sb->cfg.section3_entry_size = 0x08; } -static void config_sb_audio_fs(ubi_sb_header* sb, off_t streamed_flag, off_t group_flag, off_t loop_flag) { +static void config_sb_audio_fs(ubi_sb_header* sb, off_t streamed_flag, off_t subblock_flag, off_t loop_flag) { /* audio header with standard flags */ sb->cfg.audio_streamed_flag = streamed_flag; - sb->cfg.audio_subblock_flag = group_flag; + sb->cfg.audio_subblock_flag = subblock_flag; sb->cfg.audio_loop_flag = loop_flag; sb->cfg.audio_streamed_and = 1; sb->cfg.audio_subblock_and = 1; @@ -3320,8 +3322,8 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { return 1; } - /* Brothers in Arms: Road to Hill 30 (2005)(PS2) */ - /* Brothers in Arms: Earned in Blood (2005)(PS2) */ + /* Brothers in Arms: Road to Hill 30 (2005)(PS2)-bank */ + /* Brothers in Arms: Earned in Blood (2005)(PS2)-bank */ if (sb->version == 0x000A0007 && sb->platform == UBI_PS2 && is_bia_ps2) { config_sb_entry(sb, 0x5c, 0x14c); From 0af464c10fb5f99d26c9d14aa7d74b930e43140f Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Sat, 6 Jun 2020 04:44:30 +0300 Subject: [PATCH 4/4] Ubi SB: Fixed external RAM sounds --- src/meta/ubi_sb.c | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index 37fb622b..cef0109e 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -30,6 +30,7 @@ typedef struct { off_t audio_loop_flag; off_t audio_loc_flag; off_t audio_stereo_flag; + off_t audio_internal_flag; off_t audio_num_samples; off_t audio_num_samples2; off_t audio_sample_rate; @@ -180,8 +181,9 @@ typedef struct { float duration; /* silence duration */ - int is_streamed; /* stream is in a external file */ + int is_streamed; /* sound is streamed from storage */ int is_cd_streamed; /* found in PS2 BNM */ + int is_external; /* sound is in an external file */ char resource_name[0x28]; /* filename to the external stream, or internal stream info for some games */ char readable_name[255]; /* final subsong name */ @@ -474,10 +476,10 @@ static int bnm_parse_offsets(ubi_sb_header *sb, STREAMFILE *sf) { int32_t(*read_32bit)(off_t, STREAMFILE *) = sb->big_endian ? read_32bitBE : read_32bitLE; uint32_t block_offset; - if (sb->is_streamed) + if (sb->is_external) return 1; - /* sounds are split into subblock based on resource type and codec, the order is hardcoded */ + /* sounds are split into subblocks based on resource type and codec, the order is hardcoded */ if (sb->version == 0x00000000 || sb->version == 0x00000200) { /* 0x14: MPDX, 0x18: MIDI, 0x1c: PCM, 0x20: APM, 0x24: streamed, 0x28: EOF */ switch (sb->stream_type) { @@ -628,7 +630,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_ VGMSTREAM *vgmstream = NULL; STREAMFILE *sf_data = NULL; - if (sb->is_streamed) { + if (sb->is_external) { if (strcmp(sb->resource_name, "silence.wav") == 0) { /* some Rayman 2 banks reference non-existent silence.wav, looks like some kind of hack? */ sb->duration = (float)(sb->stream_size / sb->channels / 2) / (float)sb->sample_rate; @@ -647,7 +649,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_ switch (sb->stream_type) { case 0x01: { - if (!sb->is_streamed) { /* Dreamcast bank */ + if (!sb->is_external) { /* Dreamcast bank */ if (sb->version == 0x00000000) { uint32_t entry_offset, start_offset, num_samples, codec; uint8_t buf[4]; @@ -727,7 +729,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_ break; } case 0x04:{ /* standard WAV */ - if (!sb->is_streamed) { + if (!sb->is_external) { VGM_LOG("Ubi DAT: Found RAM stream_type 0x04\n"); goto fail; } @@ -1283,7 +1285,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_audio(ubi_sb_header* sb, STREAMFILE* sf_ return init_vgmstream_ubi_dat_main(sb, sf_index, sf); /* open external stream if needed */ - if (sb->is_streamed || sb->is_blk || sb->is_ps2_bnm) { + if (sb->is_external) { sf_data = open_streamfile_by_filename(sf, sb->resource_name); if (sf_data == NULL) { VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name); @@ -1318,12 +1320,12 @@ static VGMSTREAM* init_vgmstream_ubi_sb_layer(ubi_sb_header* sb, STREAMFILE* sf_ int i, total_channels = 0; if (sb->is_ps2_old) { - /* no blocked layout yet, just open it as normal file */ + /* no blocked layout yet, just open it as a normal file */ return init_vgmstream_ubi_sb_audio(sb, sf_index, sf); } /* open external stream if needed */ - if (sb->is_streamed || sb->is_blk) { + if (sb->is_external) { sf_data = open_streamfile_by_filename(sf,sb->resource_name); if (sf_data == NULL) { VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name); @@ -1595,7 +1597,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf ;VGM_LOG("UBI SB: target at %x + %x, extra=%x, name=%s, sb=%i, t=%i\n", (uint32_t)sb->header_offset, sb->cfg.section2_entry_size, (uint32_t)sb->extra_offset, sb->resource_name, sb->subblock_id, sb->stream_type); - ;VGM_LOG("UBI SB: stream offset=%x, size=%x, name=%s\n", (uint32_t)sb->stream_offset, sb->stream_size, sb->is_streamed ? sb->resource_name : "internal" ); + ;VGM_LOG("UBI SB: stream offset=%x, size=%x, name=%s\n", (uint32_t)sb->stream_offset, sb->stream_size, sb->is_external ? sb->resource_name : "internal" ); switch(sb->type) { case UBI_AUDIO: @@ -1682,7 +1684,7 @@ static void build_readable_name(char * buf, size_t buf_size, ubi_sb_header* sb) } } else { - if (sb->is_streamed || sb->cfg.audio_has_internal_names || sb->is_blk || sb->is_ps2_bnm) + if (sb->is_external || sb->cfg.audio_has_internal_names) res_name = sb->resource_name; else res_name = NULL; @@ -1741,6 +1743,8 @@ static int parse_type_audio_ps2_bnm(ubi_sb_header *sb, off_t offset, STREAMFILE sprintf(sb->resource_name, "BNK_%d.VB", sb->bank_number); } + sb->is_external = 1; + return 1; fail: return 0; @@ -1784,8 +1788,10 @@ static int parse_type_audio_ps2_old(ubi_sb_header* sb, off_t offset, STREAMFILE* /* filenames are hardcoded */ if (sb->is_blk) { blk_get_resource_name(sb); + sb->is_external = 1; } else if (sb->is_streamed) { strcpy(sb->resource_name, sb->is_localized ? "STRM.LM1" : "STRM.SM1"); + sb->is_external = 1; } return 1; @@ -1821,8 +1827,10 @@ static int parse_type_layer_ps2_old(ubi_sb_header* sb, off_t offset, STREAMFILE* /* filenames are hardcoded */ if (sb->is_blk) { blk_get_resource_name(sb); + sb->is_external = 1; } else if (sb->is_streamed) { strcpy(sb->resource_name, sb->is_localized ? "STRM.LM1" : "STRM.SM1"); + sb->is_external = 1; } return 1; @@ -1858,12 +1866,11 @@ static int parse_type_audio(ubi_sb_header* sb, off_t offset, STREAMFILE* sf) { } sb->is_streamed = read_32bit(offset + sb->cfg.audio_streamed_flag, sf) & sb->cfg.audio_streamed_and; + sb->is_external = sb->is_streamed; - /* hack for Donald Duck Demo, there are some streamed APM sounds that don't have the flag set */ - if (sb->is_bnm && sb->version == 0x00000000 && sb->stream_type == 0x04 && !sb->is_streamed) { - /* check the header for whether there are actually any RAM APM sounds */ - if (read_32bit(0x24, sf) - read_32bit(0x20, sf) == 0x00) - sb->is_streamed = 1; + if (sb->cfg.audio_internal_flag && !sb->is_streamed) { + /* RAM sounds are not always internal in early versions [Donald Duck Demo (PC)] */ + sb->is_external = (int)!(read_32bit(offset + sb->cfg.audio_internal_flag, sf)); } /* apparently, there may also be other subblocks based on various flags but they were not seen so far */ @@ -1897,7 +1904,7 @@ static int parse_type_audio(ubi_sb_header* sb, off_t offset, STREAMFILE* sf) { /* external stream name can be found in the header (first versions) or the sectionX table (later versions) */ if (sb->cfg.audio_stream_name) { - if (sb->is_dat && !sb->is_streamed) { + if (sb->is_dat && !sb->is_external) { sb->subbank_index = read_8bit(offset + sb->cfg.audio_stream_name + 0x01, sf); } else { read_string(sb->resource_name, sb->cfg.resource_name_size, offset + sb->cfg.audio_stream_name, sf); @@ -2014,6 +2021,8 @@ static int parse_type_layer(ubi_sb_header* sb, off_t offset, STREAMFILE* sf) { goto fail; } + sb->is_external = sb->is_streamed; + /* get 1st layer header in extra table and validate all headers match */ table_offset = sb->extra_offset; //sb->channels = (sb->cfg.layer_channels % 4) ? /* non-aligned offset is always 16b */ @@ -2359,10 +2368,10 @@ static int parse_offsets(ubi_sb_header* sb, STREAMFILE* sf) { VGM_ASSERT(!sb->is_map && sb->section3_num > 2, "UBI SB: section3 > 2 found\n"); - if (sb->is_streamed) + if (sb->is_external) return 1; - /* Internal sounds are split into subblock, with their offsets being relative to subblock start. + /* Internal sounds are split into subblocks, with their offsets being relative to subblock start. * A table contains sizes of each subblock, so we adjust offsets based on the subblock ID of our sound. * Headers normally only use 0 or 1, and section3 may only define id1 (which the internal sound would use). * May exist even for external streams only, and they often use id 1 too. */ @@ -2863,6 +2872,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { } if (sb->is_bnm || sb->is_blk || sb->is_dat) { + sb->cfg.audio_internal_flag = 0x08; sb->cfg.audio_stream_size = 0x0c; sb->cfg.audio_stream_offset = 0x10; //sb->cfg.audio_extra_offset = 0x10; @@ -2886,6 +2896,7 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { sb->cfg.random_extra_offset = 0x10; //sb->cfg.random_extra_size = 0x0c; } else if (sb->version <= 0x00000007) { + sb->cfg.audio_internal_flag = 0x08; sb->cfg.audio_stream_size = 0x0c; sb->cfg.audio_extra_offset = 0x10; sb->cfg.audio_stream_offset = 0x14;