diff --git a/src/layout/blocked_str_snds.c b/src/layout/blocked_str_snds.c index 7a7fca9a..d47473ed 100644 --- a/src/layout/blocked_str_snds.c +++ b/src/layout/blocked_str_snds.c @@ -1,54 +1,39 @@ #include "layout.h" #include "../vgmstream.h" -/* set up for the block at the given offset */ -void block_update_str_snds(off_t block_offset, VGMSTREAM * vgmstream) { - off_t current_chunk; - size_t file_size; + +void block_update_str_snds(off_t block_offset, VGMSTREAM* vgmstream) { + STREAMFILE* sf = vgmstream->ch[0].streamfile; + uint32_t block_type, block_subtype, block_size, block_current; int i; - STREAMFILE *streamfile; - int FoundSSMP = 0; - off_t SSMP_offset = -1; - current_chunk = block_offset; - streamfile = vgmstream->ch[0].streamfile; - file_size = get_streamfile_size(streamfile); + /* EOF reads: signal we have nothing and let the layout fail */ + if (block_offset >= get_streamfile_size(sf)) { + vgmstream->current_block_samples = -1; + return; + } - /* we may have to skip some chunks */ - while (!FoundSSMP && current_chunk < file_size) { - if (current_chunk+read_32bitBE(current_chunk+4,streamfile)>=file_size) - break; - switch (read_32bitBE(current_chunk,streamfile)) { - case 0x534e4453: /* SNDS */ - /* SSMP */ - if (read_32bitBE(current_chunk+0x10,streamfile)==0x53534d50) { - FoundSSMP = 1; - SSMP_offset = current_chunk; - } - break; - case 0x46494c4c: /* FILL, the main culprit */ - default: - break; + + block_type = read_u32be(block_offset + 0x00,sf); + block_size = read_u32be(block_offset + 0x04,sf); + + block_current = 0; /* ignore block by default (other chunks include MPVD + VHDR/FRAM and FILL) */ + if (block_type == 0x534e4453) { /* SNDS */ + block_subtype = read_u32be(block_offset + 0x10,sf); /* SNDS */ + if (block_subtype == 0x53534d50) { + block_current = read_u32be(block_offset + 0x14, sf) / vgmstream->channels; } - - current_chunk += read_32bitBE(current_chunk+4,streamfile); } - if (!FoundSSMP) { - /* if we couldn't find it all we can do is try playing the current - * block, which is going to suck */ - vgmstream->current_block_offset = block_offset; - } + /* seen in Battle Tryst video frames */ + if (block_size % 0x04) + block_size += 0x04 - (block_size % 0x04); - vgmstream->current_block_offset = SSMP_offset; - vgmstream->current_block_size = (read_32bitBE( - vgmstream->current_block_offset+4, - vgmstream->ch[0].streamfile) - 0x18) / vgmstream->channels; - vgmstream->next_block_offset = vgmstream->current_block_offset + - read_32bitBE(vgmstream->current_block_offset+4, - vgmstream->ch[0].streamfile); + vgmstream->current_block_offset = block_offset; + vgmstream->next_block_offset = block_offset + block_size; + vgmstream->current_block_size = block_current; for (i = 0; i < vgmstream->channels; i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18 + i * vgmstream->interleave_block_size; + vgmstream->ch[i].offset = block_offset + 0x18 + i * vgmstream->interleave_block_size; } } diff --git a/src/meta/str_snds.c b/src/meta/str_snds.c index d4edcb7e..d3f2f935 100644 --- a/src/meta/str_snds.c +++ b/src/meta/str_snds.c @@ -13,10 +13,10 @@ VGMSTREAM* init_vgmstream_str_snds(STREAMFILE* sf) { /* checks */ /* .str: standard + * .stream: Battle Tryst (Arcade) movies * .3do: Aqua World - Umimi Monogatari (3DO) movies */ - if (!check_extensions(sf, "str,3do")) + if (!check_extensions(sf, "str,stream,3do")) goto fail; - if (read_u32be(0x00,sf) != 0x4354524c && /* "CTRL" */ read_u32be(0x00,sf) != 0x534e4453 && /* "SNDS" */ read_u32be(0x00,sf) != 0x53484452) /* "SHDR" */ @@ -96,14 +96,24 @@ VGMSTREAM* init_vgmstream_str_snds(STREAMFILE* sf) { vgmstream->num_samples /= vgmstream->channels; switch (read_u32be(shdr_offset + 0x24,sf)) { - case 0x53445832: /* "SDX2" */ + case 0x53445832: /* "SDX2" (common) */ if (channels > 1) { vgmstream->coding_type = coding_SDX2_int; - vgmstream->interleave_block_size = 1; + vgmstream->interleave_block_size = 0x01; } else { vgmstream->coding_type = coding_SDX2; } break; + + case 0x43424432: /* "CBD2" (rare, Battle Tryst) */ + if (channels > 1) { + vgmstream->coding_type = coding_CBD2_int; + vgmstream->interleave_block_size = 0x01; + } else { + vgmstream->coding_type = coding_CBD2; /* assumed */ + } + break; + default: goto fail; }