vgmstream/src/meta/bsf.c

98 lines
2.9 KiB
C

#include "meta.h"
#include "../coding/coding.h"
/* .bsf - from Kuju games [Reign of Fire ((PS2/GC/Xbox)] */
VGMSTREAM* init_vgmstream_bsf(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
STREAMFILE* temp_sf = NULL;
uint32_t subfile_type;
off_t subfile_name;
off_t subfile_offset;
size_t subfile_size;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!check_extensions(sf,"bsf"))
goto fail;
if (read_u32le(0x00,sf) != 0x42534648) /* "BSFH" (notice chunks are LE even on GC) */
goto fail;
total_subsongs = read_u32le(0x08,sf);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* dumb container of other formats */
{
int i;
off_t offset = 0x08 + read_u32le(0x04,sf); /* 0x04: chunk size */
subfile_type = 0;
for (i = 0; i < total_subsongs; i++) {
/* subsong header "xxxH" */
//uint32_t head_type = read_u32le(offset + 0x00,sf);
uint32_t head_size = read_u32le(offset + 0x04,sf);
/* 0x08: name
* 0x28: audio config? */
/* subsong data "xxxD" */
uint32_t data_type = read_u32le(offset + 0x08 + head_size + 0x00,sf);
uint32_t data_size = read_u32le(offset + 0x08 + head_size + 0x04,sf);
if (i + 1 == target_subsong) {
subfile_name = offset + 0x08;
subfile_type = data_type;
subfile_size = data_size;
subfile_offset = offset + 0x08 + head_size + 0x08;
break;
}
offset += 0x08 + head_size + 0x08 + data_size;
}
if (subfile_type == 0)
goto fail;
}
switch(subfile_type) {
case 0x44535044: /* "DSPD" */
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "dsp");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_ngc_dsp_std(temp_sf);
if (!vgmstream) goto fail;
break;
case 0x56414744: /* "VAGD" */
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "vag");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_vag(temp_sf);
if (!vgmstream) goto fail;
break;
case 0x57415644: /* "WAVD" */
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "wav");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_riff(temp_sf);
if (!vgmstream) goto fail;
break;
default:
goto fail;
}
vgmstream->num_streams = total_subsongs;
read_string(vgmstream->stream_name, 0x20, subfile_name, sf);
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
return NULL;
}