mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 15:54:05 +01:00
Redo .rwav/rwar and add .brwav
This commit is contained in:
parent
f6a48926b7
commit
e76ccb6ab7
269
src/meta/bfwav.c
269
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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
249
src/meta/rwsd.c
249
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;i<channels;i++) {
|
||||
char filename[PATH_LIMIT];
|
||||
|
||||
sf->get_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;
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user