diff --git a/src/meta/bcstm.c b/src/meta/bcstm.c index e210682b..38a25582 100644 --- a/src/meta/bcstm.c +++ b/src/meta/bcstm.c @@ -7,12 +7,13 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { coding_t coding_type; - off_t head_offset; - off_t seek_offset; + off_t info_offset, seek_offset, data_offset, regn_offset, pdat_offset; + size_t info_size, seek_size, data_size, regn_size, pdat_size; + uint16_t temp_id; int codec_number; int channel_count; int loop_flag; - int ima = 0; + int i, ima = 0; off_t start_offset; /* check extension, case insensitive */ @@ -24,24 +25,45 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { /* check header */ if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */ goto fail; - if ((uint32_t)read_32bitBE(4, streamFile) != 0xFFFE4000) + if ((uint16_t)read_16bitLE(4, streamFile) != 0xFEFF) goto fail; + int section_count = read_16bitLE(0x10, streamFile); + for (i = 0; i < section_count; i++) { + temp_id = read_16bitLE(0x14 + i * 0xc, streamFile); + switch(temp_id) { + case 0x4000: + info_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + info_size = read_32bitLE(0x1c + i * 0xc, streamFile); + break; + case 0x4001: + seek_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + seek_size = read_32bitLE(0x1c + i * 0xc, streamFile); + break; + case 0x4002: + data_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + data_size = read_32bitLE(0x1c + i * 0xc, streamFile); + break; + case 0x4003: + regn_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + regn_size = read_32bitLE(0x1c + i * 0xc, streamFile); + break; + case 0x4004: + pdat_offset = read_32bitLE(0x18 + i * 0xc, streamFile); + pdat_size = read_32bitLE(0x1c + i * 0xc, streamFile); + break; + default: + break; + } + } - - /* get head offset, check */ - head_offset = read_32bitLE(0x18, streamFile); - if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */ - goto fail; - - seek_offset = read_32bitLE(0x24, streamFile); /* check type details */ - codec_number = read_8bit(head_offset + 0x20, streamFile); - loop_flag = read_8bit(head_offset + 0x21, streamFile); - channel_count = read_8bit(head_offset + 0x22, streamFile); + codec_number = read_8bit(info_offset + 0x20, streamFile); + loop_flag = read_8bit(info_offset + 0x21, streamFile); + channel_count = read_8bit(info_offset + 0x22, streamFile); switch (codec_number) { case 0: @@ -70,12 +92,12 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { if (!vgmstream) goto fail; /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitLE(head_offset + 0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitLE(head_offset + 0x24, streamFile); + vgmstream->num_samples = read_32bitLE(info_offset + 0x2c, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitLE(info_offset + 0x24, streamFile); /* channels and loop flag are set by allocate_vgmstream */ if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting { - vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); if (vgmstream->loop_start_sample > 10000) { vgmstream->loop_start_sample -= 5000; @@ -86,7 +108,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { } else { - vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitLE(info_offset + 0x28, streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; } @@ -105,13 +127,13 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { if (ima) vgmstream->interleave_block_size = 0x200; else { - vgmstream->interleave_block_size = read_32bitLE(head_offset + 0x34, streamFile); - vgmstream->interleave_smallblock_size = read_32bitLE(head_offset + 0x44, streamFile); + vgmstream->interleave_block_size = read_32bitLE(info_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitLE(info_offset + 0x44, streamFile); } if (vgmstream->coding_type == coding_NGC_DSP) { off_t coef_offset; - off_t tempoffset = head_offset; + off_t tempoffset = info_offset; int foundcoef = 0; int i, j; int coef_spacing = 0x2E; @@ -120,7 +142,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { { if ((uint32_t)read_32bitLE(tempoffset, streamFile) == 0x00004102) { - coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - head_offset; + coef_offset = read_32bitLE(tempoffset + 4, streamFile) + tempoffset + (channel_count * 8) - 4 - info_offset; foundcoef++; break; } @@ -129,17 +151,15 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) { for (j = 0; jchannels; j++) { for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(info_offset + coef_offset + j*coef_spacing + i * 2, streamFile); } } } if (ima) // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. start_offset = seek_offset; - else if (vgmstream->coding_type == coding_NGC_DSP) - start_offset = read_32bitLE(0x30, streamFile) + 0x20; - else // No SEEK header and not IMA, so just start after the DATA header - start_offset = 0x120; + else + start_offset = data_offset + 0x20; diff --git a/src/meta/bfstm.c b/src/meta/bfstm.c index d3094d4d..620fbbe1 100644 --- a/src/meta/bfstm.c +++ b/src/meta/bfstm.c @@ -7,12 +7,13 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { coding_t coding_type; - off_t head_offset; - off_t seek_offset; - off_t data_offset; + off_t info_offset, seek_offset, data_offset, regn_offset, pdat_offset; + size_t info_size, seek_size, data_size, regn_size, pdat_size; + uint16_t temp_id; int codec_number; int channel_count; int loop_flag; + int i, j; int ima = 0; off_t start_offset; int founddata; @@ -30,33 +31,44 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if ((uint16_t)read_16bitBE(4, streamFile) != 0xFEFF) goto fail; - founddata = 0; - tempoffset1 = 0x8; - - while (!(founddata)) - { - if ((uint32_t)read_32bitBE(tempoffset1, streamFile) == 0x40020000) - { - data_offset = read_32bitBE(tempoffset1 + 4, streamFile); - founddata++; - break; + int section_count = read_16bitBE(0x10, streamFile); + for (i = 0; i < section_count; i++) { + temp_id = read_16bitBE(0x14 + i * 0xc, streamFile); + switch(temp_id) { + case 0x4000: + info_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + info_size = read_32bitBE(0x1c + i * 0xc, streamFile); + break; + case 0x4001: + seek_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + seek_size = read_32bitBE(0x1c + i * 0xc, streamFile); + break; + case 0x4002: + data_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + data_size = read_32bitBE(0x1c + i * 0xc, streamFile); + break; + case 0x4003: + regn_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + regn_size = read_32bitBE(0x1c + i * 0xc, streamFile); + break; + case 0x4004: + pdat_offset = read_32bitBE(0x18 + i * 0xc, streamFile); + pdat_size = read_32bitBE(0x1c + i * 0xc, streamFile); + break; + default: + break; } - tempoffset1++; } - /* get head offset, check */ - head_offset = read_32bitBE(0x18, streamFile); - if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */ + if ((uint32_t)read_32bitBE(info_offset, streamFile) != 0x494E464F) /* "INFO" */ goto fail; - seek_offset = read_32bitBE(0x24, streamFile); - /* check type details */ - codec_number = read_8bit(head_offset + 0x20, streamFile); - loop_flag = read_8bit(head_offset + 0x21, streamFile); - channel_count = read_8bit(head_offset + 0x22, streamFile); + codec_number = read_8bit(info_offset + 0x20, streamFile); + loop_flag = read_8bit(info_offset + 0x21, streamFile); + channel_count = read_8bit(info_offset + 0x22, streamFile); switch (codec_number) { case 0: @@ -80,12 +92,12 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if (!vgmstream) goto fail; /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(head_offset + 0x2c, streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset + 0x26, streamFile); + vgmstream->num_samples = read_32bitBE(info_offset + 0x2c, streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitBE(info_offset + 0x26, streamFile); /* channels and loop flag are set by allocate_vgmstream */ if (ima) //Shift the loop points back slightly to avoid stupid pops in some IMA streams due to DC offsetting { - vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitBE(info_offset + 0x28, streamFile); if (vgmstream->loop_start_sample > 10000) { vgmstream->loop_start_sample -= 5000; @@ -96,7 +108,7 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { } else { - vgmstream->loop_start_sample = read_32bitBE(head_offset + 0x28, streamFile); + vgmstream->loop_start_sample = read_32bitBE(info_offset + 0x28, streamFile); vgmstream->loop_end_sample = vgmstream->num_samples; } @@ -115,41 +127,31 @@ VGMSTREAM * init_vgmstream_bfstm(STREAMFILE *streamFile) { if (ima) vgmstream->interleave_block_size = 0x200; else { - vgmstream->interleave_block_size = read_32bitBE(head_offset + 0x34, streamFile); - vgmstream->interleave_smallblock_size = read_32bitBE(head_offset + 0x44, streamFile); + vgmstream->interleave_block_size = read_32bitBE(info_offset + 0x34, streamFile); + vgmstream->interleave_smallblock_size = read_32bitBE(info_offset + 0x44, streamFile); } if (vgmstream->coding_type == coding_NGC_DSP) { - off_t coef_offset; - off_t tempoffset2 = head_offset; - int foundcoef = 0; - int i, j; - int coef_spacing = 0x2E; - - while (!(foundcoef)) - { - if ((uint32_t)read_32bitBE(tempoffset2, streamFile) == 0x41020000) - { - coef_offset = read_32bitBE(tempoffset2 + 4, streamFile) + tempoffset2 + (channel_count * 8) - 4 - head_offset; - foundcoef++; - break; - } - tempoffset2++; - } - + off_t coef_offset[channel_count]; + off_t coeff_ptr_table = read_32bitBE(info_offset + 0x1c, streamFile) + info_offset + 8; // Getting pointer for coefficient pointer table + + for (i = 0; i < channel_count; i++) { + tempoffset1 = read_32bitBE(coeff_ptr_table + 8 + i * 8, streamFile); + coef_offset[i] = tempoffset1 + coeff_ptr_table; + coef_offset[i] += read_32bitBE(coef_offset[i] + 4, streamFile); + } + for (j = 0; jchannels; j++) { for (i = 0; i<16; i++) { - vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile); + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_offset[j] + i * 2, streamFile); } } } if (ima) // No SEEK (ADPC) header, so just start where the SEEK header is supposed to be. start_offset = seek_offset; - else if (vgmstream->coding_type == coding_NGC_DSP) + else start_offset = data_offset + 0x20; - else // No SEEK header and not IMA, so just start after the DATA header - start_offset = 0x120;