mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Fix compact XWB [NFL Fever 2004 demo from Amped 2 (Xbox)]
This commit is contained in:
parent
6fccb2a529
commit
51aa1660f2
@ -44,7 +44,7 @@ typedef struct {
|
|||||||
uint32_t base_flags;
|
uint32_t base_flags;
|
||||||
size_t entry_elem_size;
|
size_t entry_elem_size;
|
||||||
size_t entry_alignment;
|
size_t entry_alignment;
|
||||||
int streams;
|
int total_subsongs;
|
||||||
|
|
||||||
uint32_t entry_flags;
|
uint32_t entry_flags;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
@ -63,27 +63,25 @@ typedef struct {
|
|||||||
uint32_t loop_end_sample;
|
uint32_t loop_end_sample;
|
||||||
} xwb_header;
|
} xwb_header;
|
||||||
|
|
||||||
static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_header * xwb, STREAMFILE *streamFile);
|
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
|
||||||
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
|
||||||
VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
||||||
VGMSTREAM * vgmstream = NULL;
|
VGMSTREAM * vgmstream = NULL;
|
||||||
off_t start_offset, off, suboff;
|
off_t start_offset, off, suboff;
|
||||||
xwb_header xwb;
|
xwb_header xwb = {0};
|
||||||
int target_stream = streamFile->stream_index;
|
int target_subsong = streamFile->stream_index;
|
||||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* basic checks */
|
/* checks */
|
||||||
if (!check_extensions(streamFile,"xwb")) goto fail;
|
if (!check_extensions(streamFile,"xwb"))
|
||||||
|
goto fail;
|
||||||
if ((read_32bitBE(0x00,streamFile) != 0x57424E44) && /* "WBND" (LE) */
|
if ((read_32bitBE(0x00,streamFile) != 0x57424E44) && /* "WBND" (LE) */
|
||||||
(read_32bitBE(0x00,streamFile) != 0x444E4257)) /* "DNBW" (BE) */
|
(read_32bitBE(0x00,streamFile) != 0x444E4257)) /* "DNBW" (BE) */
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
memset(&xwb,0,sizeof(xwb_header));
|
|
||||||
|
|
||||||
xwb.little_endian = read_32bitBE(0x00,streamFile) == 0x57424E44;/* WBND */
|
xwb.little_endian = read_32bitBE(0x00,streamFile) == 0x57424E44;/* WBND */
|
||||||
if (xwb.little_endian) {
|
if (xwb.little_endian) {
|
||||||
read_32bit = read_32bitLE;
|
read_32bit = read_32bitLE;
|
||||||
@ -101,11 +99,11 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
|
|
||||||
/* read segment offsets (SEGIDX) */
|
/* read segment offsets (SEGIDX) */
|
||||||
if (xwb.version <= XACT1_0_MAX) {
|
if (xwb.version <= XACT1_0_MAX) {
|
||||||
xwb.streams = read_32bit(0x0c, streamFile);
|
xwb.total_subsongs = read_32bit(0x0c, streamFile);
|
||||||
/* 0x10: bank name */
|
/* 0x10: bank name */
|
||||||
xwb.entry_elem_size = 0x14;
|
xwb.entry_elem_size = 0x14;
|
||||||
xwb.entry_offset= 0x50;
|
xwb.entry_offset= 0x50;
|
||||||
xwb.entry_size = xwb.entry_elem_size * xwb.streams;
|
xwb.entry_size = xwb.entry_elem_size * xwb.total_subsongs;
|
||||||
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
|
xwb.data_offset = xwb.entry_offset + xwb.entry_size;
|
||||||
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
|
xwb.data_size = get_streamfile_size(streamFile) - xwb.data_offset;
|
||||||
}
|
}
|
||||||
@ -128,7 +126,7 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
/* read base entry (WAVEBANKDATA) */
|
/* read base entry (WAVEBANKDATA) */
|
||||||
off = xwb.base_offset;
|
off = xwb.base_offset;
|
||||||
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
|
xwb.base_flags = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
xwb.streams = read_32bit(off+0x04, streamFile);
|
xwb.total_subsongs = read_32bit(off+0x04, streamFile);
|
||||||
/* 0x08 bank_name */
|
/* 0x08 bank_name */
|
||||||
suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40);
|
suboff = 0x08 + (xwb.version <= XACT1_1_MAX ? 0x10 : 0x40);
|
||||||
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
|
xwb.entry_elem_size = read_32bit(off+suboff+0x00, streamFile);
|
||||||
@ -138,26 +136,32 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
/* suboff+0x10: build time 64b (XACT2/3) */
|
/* suboff+0x10: build time 64b (XACT2/3) */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
|
if (target_subsong == 0) target_subsong = 1; /* auto: default to 1 */
|
||||||
if (target_stream < 0 || target_stream > xwb.streams || xwb.streams < 1) goto fail;
|
if (target_subsong < 0 || target_subsong > xwb.total_subsongs || xwb.total_subsongs < 1) goto fail;
|
||||||
|
|
||||||
|
|
||||||
/* read stream entry (WAVEBANKENTRY) */
|
/* read stream entry (WAVEBANKENTRY) */
|
||||||
off = xwb.entry_offset + (target_stream-1) * xwb.entry_elem_size;
|
off = xwb.entry_offset + (target_subsong-1) * xwb.entry_elem_size;
|
||||||
|
|
||||||
if (xwb.base_flags & WAVEBANK_FLAGS_COMPACT) { /* compact entry */
|
if (xwb.base_flags & WAVEBANK_FLAGS_COMPACT) { /* compact entry [NFL Fever 2004 demo from Amped 2 (Xbox)] */
|
||||||
/* offset_in_sectors:21 and sector_alignment_in_bytes:11 */
|
uint32_t entry, size_deviation, sector_offset;
|
||||||
uint32_t entry = (uint32_t)read_32bit(off+0x00, streamFile);
|
off_t next_stream_offset;
|
||||||
xwb.stream_offset = xwb.data_offset + (entry >> 11) * xwb.entry_alignment + (entry & 0x7FF);
|
|
||||||
|
|
||||||
/* find size (up to next entry or data end) */
|
entry = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
if (xwb.streams > 1) {
|
size_deviation = ((entry >> 21) & 0x7FF); /* 11b, padding data for sector alignment in bytes*/
|
||||||
entry = (uint32_t)read_32bit(off+xwb.entry_size, streamFile);
|
sector_offset = (entry & 0x1FFFFF); /* 21b, offset within data in sectors */
|
||||||
xwb.stream_size = xwb.stream_offset -
|
|
||||||
(xwb.data_offset + (entry >> 11) * xwb.entry_alignment + (entry & 0x7FF));
|
xwb.stream_offset = xwb.data_offset + sector_offset*xwb.entry_alignment;
|
||||||
} else {
|
|
||||||
xwb.stream_size = xwb.data_size;
|
/* find size using next offset */
|
||||||
|
if (target_subsong < xwb.total_subsongs) {
|
||||||
|
uint32_t next_entry = (uint32_t)read_32bit(off+0x04, streamFile);
|
||||||
|
next_stream_offset = xwb.data_offset + (next_entry & 0x1FFFFF)*xwb.entry_alignment;
|
||||||
}
|
}
|
||||||
|
else { /* for last entry (or first, when subsongs = 1) */
|
||||||
|
next_stream_offset = xwb.data_offset + xwb.data_size;
|
||||||
|
}
|
||||||
|
xwb.stream_size = next_stream_offset - xwb.stream_offset - size_deviation;
|
||||||
}
|
}
|
||||||
else if (xwb.version <= XACT1_0_MAX) {
|
else if (xwb.version <= XACT1_0_MAX) {
|
||||||
xwb.format = (uint32_t)read_32bit(off+0x00, streamFile);
|
xwb.format = (uint32_t)read_32bit(off+0x00, streamFile);
|
||||||
@ -353,10 +357,10 @@ VGMSTREAM * init_vgmstream_xwb(STREAMFILE *streamFile) {
|
|||||||
vgmstream->num_samples = xwb.num_samples;
|
vgmstream->num_samples = xwb.num_samples;
|
||||||
vgmstream->loop_start_sample = xwb.loop_start_sample;
|
vgmstream->loop_start_sample = xwb.loop_start_sample;
|
||||||
vgmstream->loop_end_sample = xwb.loop_end_sample;
|
vgmstream->loop_end_sample = xwb.loop_end_sample;
|
||||||
vgmstream->num_streams = xwb.streams;
|
vgmstream->num_streams = xwb.total_subsongs;
|
||||||
vgmstream->stream_size = xwb.stream_size;
|
vgmstream->stream_size = xwb.stream_size;
|
||||||
vgmstream->meta_type = meta_XWB;
|
vgmstream->meta_type = meta_XWB;
|
||||||
get_xsb_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_stream, &xwb, streamFile);
|
get_xsb_name(vgmstream->stream_name,STREAM_NAME_SIZE, target_subsong, &xwb, streamFile);
|
||||||
|
|
||||||
switch(xwb.codec) {
|
switch(xwb.codec) {
|
||||||
case PCM: /* Unreal Championship (Xbox)[PCM8], KOF2003 (Xbox)[PCM16LE], Otomedius (X360)[PCM16BE] */
|
case PCM: /* Unreal Championship (Xbox)[PCM8], KOF2003 (Xbox)[PCM16LE], Otomedius (X360)[PCM16BE] */
|
||||||
@ -535,7 +539,7 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
/* try to find the stream name in a companion XSB file, a comically complex cue format. */
|
/* try to find the stream name in a companion XSB file, a comically complex cue format. */
|
||||||
static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_header * xwb, STREAMFILE *streamXwb) {
|
static void get_xsb_name(char * buf, size_t maxsize, int target_subsong, xwb_header * xwb, STREAMFILE *streamXwb) {
|
||||||
STREAMFILE *streamFile = NULL;
|
STREAMFILE *streamFile = NULL;
|
||||||
int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0;
|
int i,j, start_sound, cfg__start_sound = 0, cfg__selected_wavebank = 0;
|
||||||
int xsb_version;
|
int xsb_version;
|
||||||
@ -609,8 +613,8 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head
|
|||||||
xsb.xsb_sounds_offset = read_32bit(0x46, streamFile);
|
xsb.xsb_sounds_offset = read_32bit(0x46, streamFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
VGM_ASSERT(xsb.xsb_sounds_count < xwb->streams,
|
VGM_ASSERT(xsb.xsb_sounds_count < xwb->total_subsongs,
|
||||||
"XSB: number of streams in xsb lower than xwb (xsb %i vs xwb %i)\n", xsb.xsb_sounds_count, xwb->streams);
|
"XSB: number of streams in xsb lower than xwb (xsb %i vs xwb %i)\n", xsb.xsb_sounds_count, xwb->total_subsongs);
|
||||||
|
|
||||||
VGM_ASSERT(xsb.xsb_simple_sounds_count + xsb.xsb_complex_sounds_count != xsb.xsb_sounds_count,
|
VGM_ASSERT(xsb.xsb_simple_sounds_count + xsb.xsb_complex_sounds_count != xsb.xsb_sounds_count,
|
||||||
"XSB: number of xsb sounds doesn't match simple + complex sounds (simple %i, complex %i, total %i)\n", xsb.xsb_simple_sounds_count, xsb.xsb_complex_sounds_count, xsb.xsb_sounds_count);
|
"XSB: number of xsb sounds doesn't match simple + complex sounds (simple %i, complex %i, total %i)\n", xsb.xsb_simple_sounds_count, xsb.xsb_complex_sounds_count, xsb.xsb_sounds_count);
|
||||||
@ -747,7 +751,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head
|
|||||||
|
|
||||||
//CHECK_EXIT(w->sound_count == 0, "ERROR: xsb wavebank %i has no sounds", i); //Ikaruga PC
|
//CHECK_EXIT(w->sound_count == 0, "ERROR: xsb wavebank %i has no sounds", i); //Ikaruga PC
|
||||||
|
|
||||||
if (w->sound_count == xwb->streams) {
|
if (w->sound_count == xwb->total_subsongs) {
|
||||||
if (!cfg__selected_wavebank) {
|
if (!cfg__selected_wavebank) {
|
||||||
VGM_LOG("XSB: multiple xsb wavebanks with the same number of sounds, use -w to specify one of the wavebanks\n");
|
VGM_LOG("XSB: multiple xsb wavebanks with the same number of sounds, use -w to specify one of the wavebanks\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -773,22 +777,22 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cfg__start_sound) {
|
if (cfg__start_sound) {
|
||||||
if (xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - (cfg__start_sound-1) < xwb->streams) {
|
if (xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - (cfg__start_sound-1) < xwb->total_subsongs) {
|
||||||
VGM_LOG("XSB: starting sound too high (max in selected wavebank is %i)\n", xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - xwb->streams + 1);
|
VGM_LOG("XSB: starting sound too high (max in selected wavebank is %i)\n", xsb.xsb_wavebanks[cfg__selected_wavebank-1].sound_count - xwb->total_subsongs + 1);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
if (!cfg->ignore_names_not_found)
|
if (!cfg->ignore_names_not_found)
|
||||||
CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count > xwb->streams_count, "ERROR: number of streams in xsb wavebank bigger than xwb (xsb %i vs xwb %i), use -s to specify (1=first)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->streams_count);
|
CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count > xwb->streams_count, "ERROR: number of streams in xsb wavebank bigger than xwb (xsb %i vs xwb %i), use -s to specify (1=first)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->total_subsongs);
|
||||||
if (!cfg->ignore_names_not_found)
|
if (!cfg->ignore_names_not_found)
|
||||||
CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count < xwb->streams_count, "ERROR: number of streams in xsb wavebank lower than xwb (xsb %i vs xwb %i), use -n to ignore (some names won't be extracted)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->streams_count);
|
CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count < xwb->streams_count, "ERROR: number of streams in xsb wavebank lower than xwb (xsb %i vs xwb %i), use -n to ignore (some names won't be extracted)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->total_subsongs);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
//if (!cfg->ignore_names_not_found)
|
//if (!cfg->ignore_names_not_found)
|
||||||
// CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count != xwb->streams_count, "ERROR: number of streams in xsb wavebank different than xwb (xsb %i vs xwb %i), use -s to specify (1=first)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->streams_count);
|
// CHECK_EXIT(xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count != xwb->streams_count, "ERROR: number of streams in xsb wavebank different than xwb (xsb %i vs xwb %i), use -s to specify (1=first)", xwb->xsb_wavebanks[cfg->selected_wavebank-1].sound_count, xwb->total_subsongs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* *************************** */
|
/* *************************** */
|
||||||
@ -799,7 +803,7 @@ static void get_xsb_name(char * buf, size_t maxsize, int target_stream, xwb_head
|
|||||||
for (i = start_sound; i < xsb.xsb_sounds_count; i++) {
|
for (i = start_sound; i < xsb.xsb_sounds_count; i++) {
|
||||||
xsb_sound *s = &(xsb.xsb_sounds[i]);
|
xsb_sound *s = &(xsb.xsb_sounds[i]);
|
||||||
if (s->wavebank == cfg__selected_wavebank-1
|
if (s->wavebank == cfg__selected_wavebank-1
|
||||||
&& s->stream_index == target_stream-1){
|
&& s->stream_index == target_subsong-1){
|
||||||
name_offset = s->name_offset;
|
name_offset = s->name_offset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user