From e76ccb6ab7c61ce6cb35fda1e0cc7567f798c113 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 30 Jan 2022 13:33:21 +0100 Subject: [PATCH] Redo .rwav/rwar and add .brwav --- src/meta/bfwav.c | 269 ++++++++++++++++++++++++++++++++++++++--------- src/meta/meta.h | 2 + src/meta/rwsd.c | 249 +++++++++---------------------------------- src/vgmstream.c | 2 + 4 files changed, 271 insertions(+), 251 deletions(-) diff --git a/src/meta/bfwav.c b/src/meta/bfwav.c index 74d6724e..a7298dc0 100644 --- a/src/meta/bfwav.c +++ b/src/meta/bfwav.c @@ -3,11 +3,31 @@ #include "../util/endianness.h" -/* FWAV and CWAV are basically identical except always LE */ -typedef enum { FWAV, CWAV } bxwav_type_t; +/* RWAV is a bit simpler, while FWAV and CWAV are basically identical except for endianness. + * From SDK info, typically .xxxx is the original NintendoWare format (usually a .xml) and .bxxxx is a + * binary/external form (like .rseq=xml then .brseq=binary, or .wav > brwav). */ +typedef enum { RWAV, FWAV, CWAV } bxwav_type_t; static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type); + +/* RWAV - NintendoWare binary Revolution wave (Wii games) */ +VGMSTREAM* init_vgmstream_brwav(STREAMFILE* sf) { + + /* checks */ + if (!is_id32be(0x00, sf, "RWAV")) + goto fail; + + /* .brwav: from tools (no games known) + * .rwav: header id */ + if (!check_extensions(sf, "brwav,rwav")) + goto fail; + + return init_vgmstream_bxwav(sf, RWAV); +fail: + return NULL; +} + /* FWAV - NintendoWare binary caFe wave (WiiU and Switch games) */ VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf) { @@ -21,7 +41,6 @@ VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf) { goto fail; return init_vgmstream_bxwav(sf, FWAV); - fail: return NULL; } @@ -43,7 +62,6 @@ VGMSTREAM* init_vgmstream_bcwav(STREAMFILE* sf) { goto fail; return init_vgmstream_bxwav(sf, CWAV); - fail: return NULL; } @@ -52,7 +70,7 @@ fail: static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { VGMSTREAM* vgmstream = NULL; - uint32_t info_offset, data_offset, chtb_offset; + uint32_t info_offset, data_offset, chtb_offset, file_size; int channels, loop_flag, codec, sample_rate; int big_endian; int32_t num_samples, loop_start; @@ -63,7 +81,7 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { read_s16_t read_s16; /* BOM check */ - if (read_u16be(0x04, sf) == 0xFEFF) { /* WiiU */ + if (read_u16be(0x04, sf) == 0xFEFF) { /* Wii, WiiU */ big_endian = 1; read_u32 = read_u32be; read_s32 = read_s32be; @@ -82,41 +100,95 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { } /* header */ - /* 0x06(2): header size (0x40) */ - /* 0x08: version */ - /* - FWAV: 0x00010200 */ - /* - CWAV: 0x00000002 (Kirby's Adventure), 0x00000102 (common), 0x00010102 (FE Fates, Hyrule Warriors Legends) */ - /* 0x0c: file size */ - /* 0x10(2): sections (2) */ + switch(type) { + case RWAV: + /* 0x06(2): version (usually 0102, 0103=Let's Tap, no diffs) */ + file_size = read_u32(0x08, sf); + /* 0x0c(2): header size (0x20) */ + /* 0x0e(2): sections (2) */ - /* 0x14(2): info mark (0x7000) */ - info_offset = read_u32(0x18, sf); - /* 0x1c: info size */ + info_offset = read_u32(0x10, sf); + /* 0x14: info size */ - /* 0x20(2): data mark (0x7001) */ - data_offset = read_u32(0x24, sf); - /* 0x28: data size */ - /* rest: padding */ + data_offset = read_u32(0x18, sf); + /* 0x1c: data size */ + break; + + case FWAV: + case CWAV: + /* 0x06(2): header size (0x40) */ + /* 0x08: version */ + /* - FWAV: 0x00010200 */ + /* - CWAV: 0x00000002 (Kirby's Adventure), 0x00000102 (common), 0x00010102 (FE Fates, Hyrule Warriors Legends) */ + file_size = read_u32(0x0c, sf); + /* 0x10(2): sections (2) */ + + /* 0x14(2): info mark (0x7000) */ + info_offset = read_u32(0x18, sf); + /* 0x1c: info size */ + + /* 0x20(2): data mark (0x7001) */ + data_offset = read_u32(0x24, sf); + /* 0x28: data size */ + /* rest: padding */ + break; + + default: + goto fail; + } + + if (file_size != get_streamfile_size(sf)) { + vgm_logi("BXWAV: wrong size %x vs %x\n", file_size, (uint32_t)get_streamfile_size(sf)); + goto fail; + } /* INFO section */ 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); - /* 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); + + switch(type) { + case RWAV: + codec = read_u8(info_offset + 0x08, sf); + loop_flag = read_u8(info_offset + 0x09, sf); + channels = read_u8(info_offset + 0x0a, sf); + /* 0x0b: part of rate? */ + sample_rate = read_u16(info_offset + 0x0c, sf); + /* 0x0e(2): padding */ + loop_start = read_s32(info_offset + 0x10, sf); + num_samples = read_s32(info_offset + 0x14, sf); + chtb_offset = read_u32(info_offset + 0x18, sf) + info_offset + 0x08; + /* 0x1c: channel table size */ + + loop_start = dsp_nibbles_to_samples(loop_start); + num_samples = dsp_nibbles_to_samples(num_samples); + + break; + + case FWAV: + case CWAV: + codec = read_u8(info_offset + 0x08, sf); + loop_flag = read_u8(info_offset + 0x09, 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); + break; + + default: + goto fail; + } + /* channel table is parsed at the end */ /* DATA section */ if (!is_id32be(data_offset + 0x00, sf, "DATA")) goto fail; + /* 0x04: size */ /* build the VGMSTREAM */ @@ -124,6 +196,7 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { if (!vgmstream) goto fail; switch(type) { + case RWAV: vgmstream->meta_type = meta_RWAV; break; case FWAV: vgmstream->meta_type = meta_FWAV; break; case CWAV: vgmstream->meta_type = meta_CWAV; break; default: goto fail; @@ -138,7 +211,7 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { vgmstream->layout_type = layout_none; - /* only 0x02 is known, other codecs are probably from bxstm that do use them */ + /* only 0x02 is known, others can be made with SDK tools */ switch (codec) { case 0x00: vgmstream->coding_type = coding_PCM8; @@ -171,25 +244,51 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { { 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; + uint32_t chnf_offset, chdt_offset, coef_offset; + switch(type) { + case RWAV: + /* channel entry: */ + /* - 0x04: channel info offset (from INFO offset after size) */ - /* 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? */ + chnf_offset = read_u32(chtb_offset + ch * 0x04 + 0x00, sf) + info_offset + 0x08; - if (read_u16(chnf_offset + 0x00, sf) != 0x1F00) - goto fail; - chdt_offset = read_u32(chnf_offset + 0x04, sf) + data_offset + 0x08; + /* channel info: */ + /* 0x00: offset to channel data (from DATA offset after size) */ + /* 0x04: ADPCM offset (from INFO offset after size), 0xFFFFFFFF otherwise? */ + /* 0x08: volumes x4? */ + /* 0x18: padding */ + + chdt_offset = read_u32(chnf_offset + 0x00, sf) + data_offset + 0x08; + coef_offset = read_u32(chnf_offset + 0x04, sf) + info_offset + 0x08; + break; + + case FWAV: + case CWAV: + /* 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: padding */ + + if (read_u16(chnf_offset + 0x00, sf) != 0x1F00) + goto fail; + chdt_offset = read_u32(chnf_offset + 0x04, sf) + data_offset + 0x08; + coef_offset = read_u32(chnf_offset + 0x0c, sf) + chnf_offset; + break; + + default: + goto fail; + } vgmstream->ch[ch].channel_start_offset = chdt_offset; vgmstream->ch[ch].offset = chdt_offset; @@ -197,20 +296,16 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) { 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); + //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; @@ -228,3 +323,73 @@ fail: close_vgmstream(vgmstream); return NULL; } + +/* ************************************************************************* */ + +/* RWAR - NintendoWare container [BIT.TRIP BEAT (Wii), Dance Dance Revolution Hottest Party 2 (Wii)] */ +VGMSTREAM* init_vgmstream_brwar(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + uint32_t tabl_offset, data_offset; + uint32_t subfile_offset, subfile_size; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00, sf, "RWAR")) + goto fail; + + if (!check_extensions(sf,"rwar")) + goto fail; + + /* simple container of .rwavs (inside .brsar), rarely used with single siles (DDR) */ + + /* abridged, see RWAV (same header) */ + /* 0x04(2): BOM */ + /* 0x06(2): version (usually 0100) */ + /* 0x08: file size */ + /* 0x0c(2): header size (0x20) */ + /* 0x0e(2): sections (2) */ + + tabl_offset = read_u32be(0x10, sf); + /* 0x14: tabl size */ + + data_offset = read_u32be(0x18, sf); + /* 0x1c: data size */ + + /* TABL section */ + if (!is_id32be(tabl_offset + 0x00, sf, "TABL")) + goto fail; + /* 0x04: size */ + + total_subsongs = read_u32be(tabl_offset + 0x08,sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + /* 0x00: always 0x01000000? */ + subfile_offset = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x04,sf) + data_offset; + subfile_size = read_u32be(tabl_offset + 0x0c + (target_subsong-1) * 0x0c + 0x08,sf); + + + /* DATA section */ + if (!is_id32be(data_offset + 0x00, sf, "DATA")) + goto fail; + /* 0x04: size */ + + //VGM_LOG("BRWAR: of=%x, sz=%x\n", subfile_offset, subfile_size); + + temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "rwav"); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream_brwav(temp_sf); + if (!vgmstream) goto fail; + + vgmstream->num_streams = total_subsongs; + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index 6538d48f..8e88016e 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -564,8 +564,10 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_bfstm(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_brwav(STREAMFILE* sf); VGMSTREAM* init_vgmstream_bfwav(STREAMFILE* sf); VGMSTREAM* init_vgmstream_bcwav(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_brwar(STREAMFILE* sf); VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE* streamFile); diff --git a/src/meta/rwsd.c b/src/meta/rwsd.c index 42dc3599..77e49d49 100644 --- a/src/meta/rwsd.c +++ b/src/meta/rwsd.c @@ -2,177 +2,64 @@ #include "../coding/coding.h" #include "../util.h" -/* Wii RWAV */ - -typedef struct { - // in - off_t offset; - STREAMFILE *sf; - int32_t (*read_32bit)(off_t,STREAMFILE*); - - // out - int version; - off_t start_offset; - off_t info_chunk; - off_t wave_offset; -} rwav_data_t; - -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 (!is_id32be(rd->offset, rd->sf, "RWAV")) - return; - - /* big endian, version 2 */ - if (read_u32be(rd->offset+4,rd->sf) != 0xFEFF0102) - return; - - 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 - 0x08; /* pretend to have a WAVE */ - - return; -} - -static void read_rwar(rwav_data_t* rd) { - if (!is_id32be(rd->offset, rd->sf, "RWAR")) - return; - - if (read_u32be(rd->offset + 0x04, rd->sf) != 0xFEFF0100) /* version 0 */ - return; - - rd->offset += 0x60; - read_rwav(rd); - rd->version = 0; - return; -} - /* 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 */ + * Still, some games use it for single streams. We only support the single stream form here */ +//TODO this meta is a hack as WSD is just note info, and data offsets are elsewhere, +// while this assumes whatever data follows RWSD must belong to it; rework for Wii Sports VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - char filename[PATH_LIMIT]; - size_t wave_length; - int codec; - int channels; - int loop_flag; - int rwar = 0; - int rwav = 0; - rwav_data_t rwav_data; - + int codec, channels, loop_flag; size_t stream_size; + off_t start_offset, wave_offset = 0; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - rwav_data.version = -1; - rwav_data.start_offset = 0; - rwav_data.info_chunk = -1; - rwav_data.wave_offset = -1; - - /* check extension, case insensitive */ - sf->get_name(sf,filename,sizeof(filename)); - - if (check_extensions(sf, "rwsd")) { - ; - } - else if (check_extensions(sf, "rwar")) { - rwar = 1; - } - else if (check_extensions(sf, "rwav")) { - rwav = 1; - } - else { + if (!is_id32be(0x00, sf, "RWSD")) goto fail; - } - - read_16bit = read_16bitBE; - read_32bit = read_32bitBE; + if (!check_extensions(sf, "rwsd")) + goto fail; /* check header */ - if (rwar || rwav) { - rwav_data.offset = 0; - rwav_data.sf = sf; - rwav_data.read_32bit = read_32bit; + 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 */ - if (rwar) read_rwar(&rwav_data); - if (rwav) read_rwav(&rwav_data); - if (rwav_data.wave_offset < 0) goto fail; - } - else { - if (!is_id32be(0x00, sf, "RWSD")) - goto fail; - - 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,sf); - if (!is_id32be(rwav_data.wave_offset + 0x00, sf, "WAVE")) - goto fail; - - /* get WAVE size, check */ - 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 + 0x08,sf) != 1) - goto fail; /* only support 1 */ - - rwav_data.version = 2; - break; - - case 0xFEFF0103: - rwav_data.offset = 0xe0; - rwav_data.sf = sf; - rwav_data.read_32bit = read_32bit; - - read_rwar(&rwav_data); - if (rwav_data.wave_offset < 0) goto fail; - - rwar = 1; - break; - default: + /* get WAVE offset, check */ + wave_offset = read_32bitBE(0x18,sf); + if (!is_id32be(wave_offset + 0x00, sf, "WAVE")) goto fail; - } + /* get WAVE size, check */ + wave_length = read_32bitBE(0x1c,sf); + if (read_32bitBE(wave_offset + 0x04,sf) != wave_length) + goto fail; + + /* check wave count */ + if (read_32bitBE(wave_offset + 0x08,sf) != 1) + goto fail; /* only support 1 */ + + break; + + case 0xFEFF0103: /* followed by RWAR, extract that or use .txth subfile */ + goto fail; } /* get type details */ - 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); + codec = read_u8(wave_offset+0x10,sf); + loop_flag = read_u8(wave_offset+0x11,sf); + channels = read_u8(wave_offset+0x12,sf); /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels,loop_flag); + 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->num_samples = dsp_nibbles_to_samples(read_32bitBE(wave_offset+0x1c,sf)); + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bitBE(wave_offset+0x18,sf)); - vgmstream->sample_rate = (uint16_t)read_16bit(rwav_data.wave_offset + 0x14,sf); + vgmstream->sample_rate = (uint16_t)read_16bitBE(wave_offset + 0x14,sf); vgmstream->loop_end_sample = vgmstream->num_samples; switch (codec) { @@ -190,84 +77,48 @@ VGMSTREAM* init_vgmstream_rwsd(STREAMFILE* sf) { } vgmstream->layout_type = layout_none; - - if (rwar) { - vgmstream->meta_type = meta_RWAR; - } - else if (rwav) { - vgmstream->meta_type = meta_RWAV; - } - else { - vgmstream->meta_type = meta_RWSD; - } + vgmstream->meta_type = meta_RWSD; { - off_t data_start_offset; off_t codec_info_offset; int i, j; 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. */ - - 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 + 0x00, sf); - codec_info_offset = rwav_data.info_chunk + - read_32bit(channel_info_offset + 0x04, sf); - - 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; - } + // dummy for RWSD, must be a proper way to work this out + codec_info_offset = 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*0x2, sf); + vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(codec_info_offset + i*0x2, sf); } } } } - if (rwar || rwav) { - /* */ - } - else { - if (rwav_data.version == 2) - rwav_data.start_offset = read_32bit(0x08, sf); - } + + /* this is just data size and following data may or may not be from this RWSD */ + start_offset = read_32bitBE(0x08, sf); - stream_size = read_32bit(rwav_data.wave_offset + 0x50,sf); + stream_size = read_32bitBE(wave_offset + 0x50,sf); /* open the file for reading by each channel */ { int i; - for (i=0;iget_name(sf,filename,sizeof(filename)); + + 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; - if (!(rwar || rwav)) { - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset= - rwav_data.start_offset + i*stream_size; - } + vgmstream->ch[i].channel_start_offset = vgmstream->ch[i].offset = + start_offset + i*stream_size; } } return vgmstream; - fail: close_vgmstream(vgmstream); return NULL; diff --git a/src/vgmstream.c b/src/vgmstream.c index f54d7ab9..f1b59ae8 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -20,8 +20,10 @@ static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VG VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { init_vgmstream_adx, init_vgmstream_brstm, + init_vgmstream_brwav, init_vgmstream_bfwav, init_vgmstream_bcwav, + init_vgmstream_brwar, init_vgmstream_nds_strm, init_vgmstream_afc, init_vgmstream_ast,