Add WiiU .XWS [Ninja Gaiden 3 Razor's Edge (WiiU)]

This commit is contained in:
bnnm 2021-11-28 14:01:22 +01:00
parent 1fda26f9a3
commit 30a4dd0e09
6 changed files with 67 additions and 12 deletions

View File

@ -1383,6 +1383,7 @@ static const meta_info meta_info_list[] = {
{meta_LOPU_FB, "French-Bread LOPU header"},
{meta_LPCM_FB, "French-Bread LPCM header"},
{meta_WBK, "Treyarch WBK header"},
{meta_DSP_APEX, "Koei Tecmo APEX header"},
};
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {

View File

@ -1,7 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF, XMA2 } kwb_codec;
typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF_APEX, XMA2 } kwb_codec;
typedef struct {
int big_endian;
@ -18,8 +18,8 @@ typedef struct {
int loop_flag;
int block_size;
off_t stream_offset;
size_t stream_size;
uint32_t stream_offset;
uint32_t stream_size;
off_t dsp_offset;
//off_t name_offset;
@ -121,20 +121,38 @@ static VGMSTREAM* init_vgmstream_koei_wavebank(kwb_header* kwb, STREAMFILE* sf_h
read_s32 = kwb->big_endian ? read_s32be : read_s32le;
/* container */
if (kwb->codec == MSF) {
if (kwb->codec == MSF_APEX) {
if (kwb->stream_offset == 0) {
vgmstream = init_vgmstream_silence(0,0,0); /* dummy, whatevs */
if (!vgmstream) goto fail;
}
else {
STREAMFILE* temp_sf = NULL;
init_vgmstream_t init_vgmstream = NULL;
const char* fake_ext;
uint32_t id;
id = read_u32be(kwb->stream_offset, sf_h);
if ((id & 0xFFFFFF00) == get_id32be("MSF\0")) { /* PS3 */
kwb->stream_size = read_u32(kwb->stream_offset + 0x0c, sf_h) + 0x40;
fake_ext = "msf";
init_vgmstream = init_vgmstream_msf;
}
else if (id == get_id32be("APEX")) { /* WiiU */
kwb->stream_size = read_u32(kwb->stream_offset + 0x04, sf_h); /* not padded */
fake_ext = "dsp";
init_vgmstream = init_vgmstream_dsp_apex;
}
else {
vgm_logi("KWB: unknown type %x at %x\n", id, kwb->stream_offset);
goto fail;
}
kwb->stream_size = read_u32(kwb->stream_offset + 0x0c, sf_h) + 0x40;
temp_sf = setup_subfile_streamfile(sf_h, kwb->stream_offset, kwb->stream_size, "msf");
temp_sf = setup_subfile_streamfile(sf_h, kwb->stream_offset, kwb->stream_size, fake_ext);
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_msf(temp_sf);
vgmstream = init_vgmstream(temp_sf);
close_streamfile(temp_sf);
if (!vgmstream) goto fail;
}
@ -641,9 +659,9 @@ static int parse_type_msfbank(kwb_header* kwb, off_t offset, STREAMFILE* sf) {
relative_subsong = kwb->target_subsong - current_subsongs;
header_offset = offset + 0x30 + (relative_subsong-1) * 0x04;
/* just a dumb table pointing to MSF, entries can be dummy */
/* just a dumb table pointing to MSF/APEX, entries can be dummy */
kwb->stream_offset = read_u32be(header_offset, sf);
kwb->codec = MSF;
kwb->codec = MSF_APEX;
kwb->stream_offset += offset;
@ -728,7 +746,7 @@ static int parse_type_xwsfile(kwb_header* kwb, off_t offset, STREAMFILE* sf) {
goto fail;
}
else {
VGM_LOG("XWS: unknown type %x at head=%x, body=%x\n", entry_type, head_offset, body_offset);
vgm_logi("XWS: unknown type %x at head=%x, body=%x\n", entry_type, head_offset, body_offset);
goto fail;
}
}

View File

@ -64,6 +64,7 @@ VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_idsp_tose(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_apex(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);

View File

@ -1461,7 +1461,6 @@ VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf) {
if (read_u32be(0x00,sf) != 3)
goto fail;
/* .dsp: assumed */
if (!check_extensions(sf, "kwa"))
goto fail;
@ -1484,3 +1483,37 @@ VGMSTREAM* init_vgmstream_dsp_kwa(STREAMFILE* sf) {
fail:
return NULL;
}
/* APEX - interleaved dsp [Ninja Gaiden 3 Razor's Edge (WiiU)] */
VGMSTREAM* init_vgmstream_dsp_apex(STREAMFILE* sf) {
dsp_meta dspm = {0};
uint32_t stream_size;
/* checks */
if (!is_id32be(0x00,sf, "APEX"))
goto fail;
/* .dsp: assumed */
if (!check_extensions(sf, "dsp"))
goto fail;
dspm.max_channels = 2;
stream_size = read_u32be(0x04,sf);
/* 0x08: 1? */
dspm.channels = read_u16be(0x0a,sf);
/* 0x0c: channel size? */
dspm.interleave = 0x08;
dspm.header_offset = 0x20;
dspm.header_spacing = 0x60;
dspm.start_offset = dspm.header_offset + dspm.header_spacing * 2;
/* second DSP header exists even for mono files, but has no coefs */
dspm.interleave_last = (stream_size / dspm.channels) % dspm.interleave;
dspm.meta_type = meta_DSP_APEX;
return init_vgmstream_dsp_common(sf, &dspm);
fail:
return NULL;
}

View File

@ -526,6 +526,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_lopu_fb,
init_vgmstream_lpcm_fb,
init_vgmstream_wbk,
init_vgmstream_dsp_apex,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */

View File

@ -753,6 +753,7 @@ typedef enum {
meta_LOPU_FB,
meta_LPCM_FB,
meta_WBK,
meta_DSP_APEX,
} meta_t;