Merge bcwav with bfwav and cleanup

This commit is contained in:
bnnm 2022-01-14 17:12:41 +01:00
parent 13c8649026
commit 55307d393f
7 changed files with 270 additions and 260 deletions

View File

@ -105,7 +105,7 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
subfile_size = read_u32le(subfile_offset + 0x04,sf) + 0x08; /* padded size, use RIFF's */
}
else if (is_id32be(subfile_offset,sf, "CWAV")) { /* (type 9=CWAV) */
init_vgmstream = init_vgmstream_rwsd; /* Sonic: Lost World (3DS) */
init_vgmstream = init_vgmstream_bcwav; /* Sonic: Lost World (3DS) */
extension = "bcwav";
}
else if (read_u32be(subfile_offset + 0x08,sf) >= 8000 && read_u32be(subfile_offset + 0x08,sf) <= 48000 &&

View File

@ -1,109 +1,149 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* FWAV - Nintendo streams */
/* FWAV and CWAV are basically identical except always LE */
typedef enum { FWAV, CWAV } bxwav_type_t;
static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type);
/* FWAV - NintendoWare binary caFe wave (WiiU and Switch games) */
VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
off_t info_offset, data_offset;
int channels, loop_flag, codec, sample_rate;
int big_endian;
size_t interleave = 0;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* checks */
if (!is_id32be(0x00, sf, "FWAV"))
goto fail;
/* .bfwav: used?
* .fwav: header id */
/* .bfwavnsmbu: fake extension to detect New Super Mario Bros U files with weird sample rate */
if (!check_extensions(sf, "bfwav,fwav,bfwavnsmbu"))
goto fail;
return init_vgmstream_bxwav(sf, FWAV);
fail:
return NULL;
}
/* CWAV - NintendoWare binary CTR wave (3DS games) */
VGMSTREAM* init_vgmstream_bcwav(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00, sf, "CWAV"))
goto fail;
/* .bcwav: standard 3DS (though rare as usually found in .bcsar) [Adventure Bar Story (3DS), LBX (3DS)]
* .adpcm: 80's Overdrive (3DS)
* .bms: 3D Classics Kirby's Adventure (3DS)
* .sfx: Wizdom (3DS)
* .str: Pac-Man and the Ghostly Adventures 2 (3DS)
* .zic: Wizdom (3DS) */
if (!check_extensions(sf, "bcwav,adpcm,bms,sfx,str,zic"))
goto fail;
return init_vgmstream_bxwav(sf, CWAV);
fail:
return NULL;
}
static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) {
VGMSTREAM* vgmstream = NULL;
uint32_t info_offset, data_offset, chtb_offset;
int channels, loop_flag, codec, sample_rate;
int big_endian;
int32_t num_samples, loop_start;
read_u32_t read_u32;
read_s32_t read_s32;
read_u16_t read_u16;
read_s16_t read_s16;
/* BOM check */
if (read_u16be(0x04, sf) == 0xFEFF) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
if (read_u16be(0x04, sf) == 0xFEFF) { /* WiiU */
big_endian = 1;
} else if (read_u16be(0x04, sf) == 0xFFFE) {
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
read_u32 = read_u32be;
read_s32 = read_s32be;
read_u16 = read_u16be;
read_s16 = read_s16be;
}
else if (read_u16le(0x04, sf) == 0xFEFF) { /* 3DS, Switch */
big_endian = 0;
} else {
read_u32 = read_u32le;
read_s32 = read_s32le;
read_u16 = read_u16le;
read_s16 = read_s16le;
}
else {
goto fail;
}
/* FWAV header */
/* header */
/* 0x06(2): header size (0x40) */
/* 0x08: version (0x00010200) */
/* 0x08: version */
/* - FWAV: 0x00010200 */
/* - CWAV: 0x00000002 (Kirby's Adventure), 0x00000102 (common), 0x00010102 (FE Fates, Hyrule Warriors Legends) */
/* 0x0c: file size */
/* 0x10(2): sections (2) */
/* 0x14(2): info mark (0x7000) */
info_offset = read_32bit(0x18, sf);
info_offset = read_u32(0x18, sf);
/* 0x1c: info size */
/* 0x20(2): data mark (0x7001) */
data_offset = read_32bit(0x24, sf);
data_offset = read_u32(0x24, sf);
/* 0x28: data size */
/* rest: padding */
/* INFO section */
if (!is_id32be(info_offset, sf, "INFO"))
if (!is_id32be(info_offset + 0x00, sf, "INFO"))
goto fail;
/* 0x04: size */
codec = read_u8(info_offset + 0x08, sf);
loop_flag = read_u8(info_offset + 0x09, sf);
sample_rate = read_32bit(info_offset + 0x0C, sf);
channels = read_32bit(info_offset + 0x1C, sf);
/* 0x0a: padding */
sample_rate = read_u32(info_offset + 0x0C, sf);
loop_start = read_s32(info_offset + 0x10, sf);
num_samples = read_s32(info_offset + 0x14, sf);
/* 0x18: original loop start? (slightly lower) */
chtb_offset = info_offset + 0x1C;
channels = read_u32(chtb_offset + 0x00, sf);
/* channel table is parsed at the end */
/* DATA section */
if (!is_id32be(data_offset + 0x00, sf, "DATA"))
goto fail;
//TODO remove
if (check_extensions(sf, "bfwavnsmbu"))
sample_rate = 16000;
/* parse channel table */
{
off_t channel1_info, data_start;
int i;
channel1_info = info_offset + 0x1c + read_32bit(info_offset+0x20+0x08*0+0x04, sf);
data_start = read_32bit(channel1_info+0x04, sf); /* within "DATA" after 0x08 */
/* channels use absolute offsets but should be ok as interleave */
interleave = 0;
if (channels > 1) {
off_t channel2_info = info_offset + 0x1c + read_32bit(info_offset+0x20+0x08*1+0x04, sf);
interleave = read_32bit(channel2_info+0x04, sf) - data_start;
}
start_offset = data_offset + 0x08 + data_start;
/* validate all channels just in case of multichannel with non-constant interleave */
for (i = 0; i < channels; i++) {
/* channel table, 0x00: flag (0x7100), 0x04: channel info offset */
off_t channel_info = info_offset + 0x1c + read_32bit(info_offset+0x20+0x08*i+0x04, sf);
/* channel info, 0x00(2): flag (0x1f00), 0x04: offset, 0x08(2): ADPCM flag (0x0300), 0x0c: ADPCM offset */
if ((uint16_t)read_16bit(channel_info+0x00, sf) != 0x1F00)
goto fail;
if (read_32bit(channel_info+0x04, sf) != data_start + interleave*i)
goto fail;
}
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
switch(type) {
case FWAV: vgmstream->meta_type = meta_FWAV; break;
case CWAV: vgmstream->meta_type = meta_CWAV; break;
default: goto fail;
}
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = read_32bit(info_offset + 0x14, sf);
vgmstream->loop_start_sample = read_32bit(info_offset + 0x10, sf);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_FWAV;
vgmstream->layout_type = (channels == 1) ? layout_none : layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = num_samples;
if (type == CWAV)
vgmstream->allow_dual_stereo = 1; /* LEGO 3DS games */
vgmstream->layout_type = layout_none;
/* only 0x02 is known, other codecs are probably from bxstm that do use them */
switch (codec) {
case 0x00:
vgmstream->coding_type = coding_PCM8;
@ -113,29 +153,80 @@ VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf) {
vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE;
break;
case 0x02:
case 0x02: /* common */
vgmstream->coding_type = coding_NGC_DSP;
{
int i, c;
off_t coef_header, coef_offset;
for (i = 0; i < vgmstream->channels; i++) {
for (c = 0; c < 16; c++) {
coef_header = info_offset + 0x1C + read_32bit(info_offset + 0x24 + (i*0x08), sf);
coef_offset = read_32bit(coef_header + 0x0c, sf) + coef_header;
vgmstream->ch[i].adpcm_coef[c] = read_16bit(coef_offset + c*2, sf);
}
}
}
/* coefs are read below */
break;
default: /* 0x03: IMA? */
case 0x03:
vgmstream->coding_type = coding_3DS_IMA;
/* hist is read below */
break;
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
if (!vgmstream_open_stream_bf(vgmstream, sf, data_offset, 1))
goto fail;
/* parse channel table and offsets
* (usually the interleave/distance is fixed, but in theory could be non-standard, so assign manually) */
{
int ch, i;
for (ch = 0; ch < channels; ch++) {
uint32_t chnf_offset, chdt_offset;
/* channel entry: */
/* - 0x00: mark (0x7100) */
/* - 0x02: padding */
/* - 0x04: channel info offset (from channel table offset) */
chnf_offset = read_u32(chtb_offset + 0x04 + ch * 0x08 + 0x04, sf) + chtb_offset;
/* channel info: */
/* 0x00: mark (0x1F00) */
/* 0x02: padding */
/* 0x04: offset to channel data (from DATA offset after size ) */
/* 0x08: ADPCM mark (0x0300=DSP, 0x0301=IMA, 0x0000=none) */
/* 0x0a: padding */
/* 0x0c: ADPCM offset (from channel info offset), 0xFFFFFFFF otherwise */
/* 0x10: null? */
if (read_u16(chnf_offset + 0x00, sf) != 0x1F00)
goto fail;
chdt_offset = read_u32(chnf_offset + 0x04, sf) + data_offset + 0x08;
vgmstream->ch[ch].channel_start_offset = chdt_offset;
vgmstream->ch[ch].offset = chdt_offset;
switch(codec) {
case 0x02: {
/* standard DSP coef + predictor + hists + loop predictor + loop hists */
uint32_t coef_offset = read_u32(chnf_offset + 0x0c, sf) + chnf_offset;
for (i = 0; i < 16; i++) {
vgmstream->ch[ch].adpcm_coef[i] = read_s16(coef_offset + 0x00 + i*0x02, sf);
}
vgmstream->ch[ch].adpcm_history1_16 = read_s16(coef_offset + 0x22, sf);
vgmstream->ch[ch].adpcm_history2_16 = read_s16(coef_offset + 0x24, sf);
break;
}
case 0x03: {
/* hist + step */
uint32_t coef_offset = read_u32(chnf_offset + 0x0c, sf) + chnf_offset;
vgmstream->ch[ch].adpcm_history1_16 = read_s16(coef_offset + 0x00, sf);
vgmstream->ch[ch].adpcm_step_index = read_s16(coef_offset + 0x02, sf);
break;
}
default:
break;
}
}
}
return vgmstream;
fail:

View File

@ -201,7 +201,7 @@ VGMSTREAM* init_vgmstream_cpk_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
if (!vgmstream) goto fail;
break;
case CWAV: /* Metal Gear Solid: Snake Eater 3D (3DS) */
vgmstream = init_vgmstream_rwsd(temp_sf);
vgmstream = init_vgmstream_bcwav(temp_sf);
if (!vgmstream) goto fail;
break;
case ADX: /* Sonic Generations (3DS) */

View File

@ -564,7 +564,8 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_bfstm(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_bfwav(STREAMFILE* streamFile);
VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_bcwav(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE* streamFile);

View File

@ -2,13 +2,12 @@
#include "../coding/coding.h"
#include "../util.h"
/* Wii RWAV, 3DS CWAV */
/* Wii RWAV */
struct rwav_data {
typedef struct {
// in
off_t offset;
STREAMFILE *streamFile;
int big_endian;
STREAMFILE *sf;
int32_t (*read_32bit)(off_t,STREAMFILE*);
// out
@ -16,71 +15,45 @@ struct rwav_data {
off_t start_offset;
off_t info_chunk;
off_t wave_offset;
};
} rwav_data_t;
static void read_rwav(struct rwav_data * rd)
{
static void read_rwav(rwav_data_t* rd) {
off_t chunk_table_offset;
off_t chunk_table_step;
off_t info_chunk;
off_t data_chunk;
if (rd->big_endian)
{
/* "RWAV" */
if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574156)
return;
/* big endian, version 2 */
if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0102)
return;
chunk_table_offset = rd->offset+0x10;
chunk_table_step = 8;
}
else
{
/* "CWAV" */
if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x43574156)
return;
/* little endian, version 2 */
if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFFFE4000 ||
(
(uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00000002 && /* Kirby's Adventure */
(uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00000102 && /* common */
(uint32_t)read_32bitBE(rd->offset+8,rd->streamFile)!=0x00010102
)
)
return;
chunk_table_offset = rd->offset+0x18;
chunk_table_step = 0xc;
}
info_chunk = rd->offset+rd->read_32bit(chunk_table_offset,rd->streamFile);
/* "INFO" */
if ((uint32_t)read_32bitBE(info_chunk,rd->streamFile)!=0x494e464f)
if (!is_id32be(rd->offset, rd->sf, "RWAV"))
return;
data_chunk = rd->offset+rd->read_32bit(chunk_table_offset+chunk_table_step,rd->streamFile);
/* "DATA" */
if ((uint32_t)read_32bitBE(data_chunk,rd->streamFile)!=0x44415441)
/* big endian, version 2 */
if (read_u32be(rd->offset+4,rd->sf) != 0xFEFF0102)
return;
rd->start_offset = data_chunk + 8;
rd->info_chunk = info_chunk + 8;
chunk_table_offset = rd->offset + 0x10;
chunk_table_step = 0x08;
info_chunk = rd->offset + rd->read_32bit(chunk_table_offset, rd->sf);
if (!is_id32be(info_chunk, rd->sf, "INFO"))
return;
data_chunk = rd->offset + rd->read_32bit(chunk_table_offset + chunk_table_step, rd->sf);
if (!is_id32be(data_chunk, rd->sf, "DATA"))
return;
rd->start_offset = data_chunk + 0x08;
rd->info_chunk = info_chunk + 0x08;
rd->version = 2;
rd->wave_offset = info_chunk - 8; // pretend to have a WAVE
rd->wave_offset = info_chunk - 0x08; /* pretend to have a WAVE */
return;
}
static void read_rwar(struct rwav_data * rd)
{
if ((uint32_t)read_32bitBE(rd->offset,rd->streamFile)!=0x52574152) /* "RWAR" */
static void read_rwar(rwav_data_t* rd) {
if (!is_id32be(rd->offset, rd->sf, "RWAR"))
return;
if ((uint32_t)read_32bitBE(rd->offset+4,rd->streamFile)!=0xFEFF0100) /* version 0 */
if (read_u32be(rd->offset + 0x04, rd->sf) != 0xFEFF0100) /* version 0 */
return;
rd->offset += 0x60;
@ -92,23 +65,20 @@ static void read_rwar(struct rwav_data * rd)
/* RWSD is quite similar to BRSTM, but can contain several streams.
* Still, some games use it for single streams. We only support the
* single stream form here */
VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
size_t wave_length;
int codec;
int channel_count;
int channels;
int loop_flag;
int rwar = 0;
int rwav = 0;
struct rwav_data rwav_data;
rwav_data_t rwav_data;
size_t stream_size;
int big_endian = 1;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
@ -118,44 +88,29 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
rwav_data.wave_offset = -1;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
sf->get_name(sf,filename,sizeof(filename));
if (check_extensions(streamFile, "rwsd")) {
if (check_extensions(sf, "rwsd")) {
;
}
else if (check_extensions(streamFile, "rwar")) {
else if (check_extensions(sf, "rwar")) {
rwar = 1;
}
else if (check_extensions(streamFile, "rwav")) {
else if (check_extensions(sf, "rwav")) {
rwav = 1;
}
/* .bcwav: standard 3DS
* .bms: 3D Classics Kirby's Adventure (3DS)
* .sfx: Wizdom (3DS)
* .str: Pac-Man and the Ghostly Adventures 2 (3DS)
* .zic: Wizdom (3DS) */
else if (check_extensions(streamFile, "bcwav,bms,sfx,str,zic")) {
rwav = 1; // cwav, similar to little endian rwav
big_endian = 0;
}
else {
goto fail;
}
if (big_endian) {
read_16bit = read_16bitBE;
read_32bit = read_32bitBE;
}
else {
read_16bit = read_16bitLE;
read_32bit = read_32bitLE;
}
read_16bit = read_16bitBE;
read_32bit = read_32bitBE;
/* check header */
if (rwar || rwav) {
rwav_data.offset = 0;
rwav_data.streamFile = streamFile;
rwav_data.big_endian = big_endian;
rwav_data.sf = sf;
rwav_data.read_32bit = read_32bit;
if (rwar) read_rwar(&rwav_data);
@ -163,33 +118,34 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
if (rwav_data.wave_offset < 0) goto fail;
}
else {
if ((uint32_t)read_32bitBE(0,streamFile)!=0x52575344) /* "RWSD" */
if (!is_id32be(0x00, sf, "RWSD"))
goto fail;
switch (read_32bitBE(4,streamFile)) {
switch (read_u32be(0x04, sf)) {
case 0xFEFF0102:
/* ideally we would look through the chunk list for a WAVE chunk,
* but it's always in the same order */
/* get WAVE offset, check */
rwav_data.wave_offset = read_32bit(0x18,streamFile);
if ((uint32_t)read_32bitBE(rwav_data.wave_offset,streamFile)!=0x57415645) /* "WAVE" */
rwav_data.wave_offset = read_32bit(0x18,sf);
if (!is_id32be(0x00, sf, "WAVE"))
goto fail;
/* get WAVE size, check */
wave_length = read_32bit(0x1c,streamFile);
if (read_32bit(rwav_data.wave_offset+4,streamFile)!=wave_length)
wave_length = read_32bit(0x1c,sf);
if (read_32bit(rwav_data.wave_offset + 0x04,sf) != wave_length)
goto fail;
/* check wave count */
if (read_32bit(rwav_data.wave_offset+8,streamFile) != 1)
if (read_32bit(rwav_data.wave_offset + 0x08,sf) != 1)
goto fail; /* only support 1 */
rwav_data.version = 2;
break;
case 0xFEFF0103:
rwav_data.offset = 0xe0;
rwav_data.streamFile = streamFile;
rwav_data.big_endian = big_endian;
rwav_data.sf = sf;
rwav_data.read_32bit = read_32bit;
read_rwar(&rwav_data);
@ -204,126 +160,87 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
}
/* get type details */
codec = read_8bit(rwav_data.wave_offset+0x10,streamFile);
loop_flag = read_8bit(rwav_data.wave_offset+0x11,streamFile);
if (big_endian)
channel_count = read_8bit(rwav_data.wave_offset+0x12,streamFile);
else
channel_count = read_32bit(rwav_data.wave_offset+0x24,streamFile);
codec = read_u8(rwav_data.wave_offset+0x10,sf);
loop_flag = read_u8(rwav_data.wave_offset+0x11,sf);
channels = read_u8(rwav_data.wave_offset+0x12,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->num_samples = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x1c,sf));
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x18,sf));
vgmstream->sample_rate = (uint16_t)read_16bit(rwav_data.wave_offset + 0x14,sf);
vgmstream->loop_end_sample = vgmstream->num_samples;
switch (codec) {
case 0:
coding_type = coding_PCM8;
vgmstream->coding_type = coding_PCM8;
break;
case 1:
if (big_endian)
coding_type = coding_PCM16BE;
else
coding_type = coding_PCM16LE;
vgmstream->coding_type = coding_PCM16BE;
break;
case 2:
coding_type = coding_NGC_DSP;
break;
case 3:
coding_type = coding_3DS_IMA;
vgmstream->coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
if (channel_count < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
if (big_endian) {
vgmstream->num_samples = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x1c,streamFile));
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(rwav_data.wave_offset+0x18,streamFile));
}
else {
vgmstream->num_samples = read_32bit(rwav_data.wave_offset+0x1c,streamFile);
vgmstream->loop_start_sample = read_32bit(rwav_data.wave_offset+0x18,streamFile);
}
vgmstream->sample_rate = (uint16_t)read_16bit(rwav_data.wave_offset+0x14,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type;
vgmstream->layout_type = layout_none;
if (rwar)
if (rwar) {
vgmstream->meta_type = meta_RWAR;
else if (rwav) {
if (big_endian) {
vgmstream->meta_type = meta_RWAV;
}
else {
vgmstream->meta_type = meta_CWAV;
vgmstream->allow_dual_stereo = 1; /* LEGO 3DS games */
}
}
else
else if (rwav) {
vgmstream->meta_type = meta_RWAV;
}
else {
vgmstream->meta_type = meta_RWSD;
}
{
off_t data_start_offset;
off_t codec_info_offset;
int i,j;
int i, j;
for (j=0;j<vgmstream->channels;j++) {
if (rwar || rwav)
{
if (big_endian)
{
for (j = 0 ; j < vgmstream->channels; j++) {
if (rwar || rwav) {
/* This is pretty nasty, so an explaination is in order.
* At 0x10 in the info_chunk is the offset of a table with
* one entry per channel. Each entry in this table is itself
* an offset to a set of information for the channel. The
* first element in the set is the offset into DATA of the
* channel.
* The second element is the
* offset of the codec-specific setup for the channel. */
* At 0x10 in the info_chunk is the offset of a table with
* one entry per channel. Each entry in this table is itself
* an offset to a set of information for the channel. The
* first element in the set is the offset into DATA of the channel.
* The second element is the offset of the codec-specific setup for the channel. */
off_t channel_info_offset;
channel_info_offset = rwav_data.info_chunk +
read_32bit(rwav_data.info_chunk+
read_32bit(rwav_data.info_chunk+0x10,streamFile)+j*4,
streamFile);
off_t channel_info_offset = rwav_data.info_chunk +
read_32bit(rwav_data.info_chunk +
read_32bit(rwav_data.info_chunk + 0x10,sf) + j*0x04, sf);
data_start_offset = rwav_data.start_offset +
read_32bit(channel_info_offset+0, streamFile);
read_32bit(channel_info_offset + 0x00, sf);
codec_info_offset = rwav_data.info_chunk +
read_32bit(channel_info_offset+4, streamFile);
}
read_32bit(channel_info_offset + 0x04, sf);
else
{
// CWAV uses some relative offsets
off_t cur_pos = rwav_data.info_chunk + 0x14; // channel count
cur_pos = cur_pos + read_32bit(cur_pos + 4 + j*8 + 4,streamFile);
vgmstream->ch[j].channel_start_offset =
vgmstream->ch[j].offset = data_start_offset;
// size is at cur_pos + 4
data_start_offset = rwav_data.start_offset + read_32bit(cur_pos + 4, streamFile);
// codec-specific info is at cur_pos + 0xC
codec_info_offset = cur_pos + read_32bit(cur_pos + 0xC,streamFile);
}
vgmstream->ch[j].channel_start_offset=
vgmstream->ch[j].offset=data_start_offset;
} else {
// dummy for RWSD, must be a proper way to work this out
codec_info_offset=rwav_data.wave_offset+0x6c+j*0x30;
codec_info_offset = rwav_data.wave_offset + 0x6c + j*0x30;
}
if (vgmstream->coding_type == coding_NGC_DSP) {
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i]=read_16bit(codec_info_offset+i*2,streamFile);
for (i = 0; i < 16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bit(codec_info_offset + i*0x2, sf);
}
}
if (vgmstream->coding_type == coding_3DS_IMA) {
vgmstream->ch[j].adpcm_history1_16 = read_16bit(codec_info_offset,streamFile);
vgmstream->ch[j].adpcm_step_index = read_16bit(codec_info_offset+2,streamFile);
vgmstream->ch[j].adpcm_history1_16 = read_16bit(codec_info_offset + 0x00,sf);
vgmstream->ch[j].adpcm_step_index = read_16bit(codec_info_offset + 0x02,sf);
}
}
}
@ -333,15 +250,16 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
}
else {
if (rwav_data.version == 2)
rwav_data.start_offset = read_32bit(8,streamFile);
rwav_data.start_offset = read_32bit(0x08, sf);
}
stream_size = read_32bit(rwav_data.wave_offset+0x50,streamFile);
stream_size = read_32bit(rwav_data.wave_offset + 0x50,sf);
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
for (i=0;i<channels;i++) {
vgmstream->ch[i].streamfile = sf->open(sf,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
@ -356,8 +274,7 @@ VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile) {
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -26,7 +26,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd_cwav(STREAMFILE* sf) {
temp_sf = setup_ubi_ckd_cwav_streamfile(sf);
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_rwsd(temp_sf);
vgmstream = init_vgmstream_bcwav(temp_sf);
if (!vgmstream) goto fail;
return vgmstream;

View File

@ -21,6 +21,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_adx,
init_vgmstream_brstm,
init_vgmstream_bfwav,
init_vgmstream_bcwav,
init_vgmstream_nds_strm,
init_vgmstream_afc,
init_vgmstream_ast,