Add CWAC .dsp [Mario & Sonic at the Rio 2016 Olympic Games (WiiU)]

This commit is contained in:
bnnm 2020-12-19 16:53:15 +01:00
parent 2aa5173ed6
commit 0958519274
6 changed files with 64 additions and 13 deletions

View File

@ -341,7 +341,8 @@ static const char* extension_list[] = {
"n64",
"naac",
"ndp",
"nds",
"ndp", //fake extension/header id for .nds
"ngca",
"nlsd",
"nop",
@ -1322,6 +1323,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_WIIVOICE, "Koei Tecmo WiiVoice header"},
{meta_SBK, "Team17 SBK header"},
{meta_DSP_WIIADPCM, "Exient WIIADPCM header"},
{meta_DSP_CWAC, "CRI CWAC 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 { ADX, HCA, VAG, RIFF, CWAV, DSP } awb_type;
typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC } awb_type;
static void load_awb_name(STREAMFILE* sf, STREAMFILE* sf_acb, VGMSTREAM* vgmstream, int waveid);
@ -116,6 +116,10 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
type = DSP;
extension = "dsp";
}
else if (is_id32be(subfile_offset,sf, "CWAC")) { /* type 13 again */
type = CWAC;
extension = "dsp";
}
else {
VGM_LOG("AWB: unknown codec\n");
goto fail;
@ -150,6 +154,10 @@ VGMSTREAM* init_vgmstream_awb_memory(STREAMFILE* sf, STREAMFILE* sf_acb) {
vgmstream = init_vgmstream_ngc_dsp_std(temp_sf);
if (!vgmstream) goto fail;
break;
case CWAC: /* Mario & Sonic at the Rio 2016 Olympic Games (WiiU) */
vgmstream = init_vgmstream_dsp_cwac(temp_sf);
if (!vgmstream) goto fail;
break;
default:
goto fail;
}

View File

@ -42,7 +42,7 @@ VGMSTREAM* init_vgmstream_wii_was(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_str_ig(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_xiii(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_cabelas(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_wii_ndp(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_ndp(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ngc_dsp_aaap(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_dspw(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_ngc_dsp_iadp(STREAMFILE* sf);
@ -57,6 +57,7 @@ VGMSTREAM* init_vgmstream_dsp_itl(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_sqex(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_wiivoice(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf);
VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf);
VGMSTREAM * init_vgmstream_csmp(STREAMFILE *streamFile);

View File

@ -92,6 +92,7 @@ typedef struct {
int fix_loop_start; /* weird files with bad loop start */
int single_header; /* all channels share header, thus totals are off */
int ignore_header_agreement; /* sometimes there are minor differences between headers */
int ignore_loop_ps; /* sometimes has bad loop start ps */
} dsp_meta;
#define COMMON_DSP_MAX_CHANNELS 6
@ -114,8 +115,10 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) {
/* load standard DSP header per channel */
{
for (i = 0; i < dspm->channel_count; i++) {
if (read_dsp_header_endian(&ch_header[i], dspm->header_offset + i*dspm->header_spacing, sf, !dspm->little_endian))
if (read_dsp_header_endian(&ch_header[i], dspm->header_offset + i*dspm->header_spacing, sf, !dspm->little_endian)) {
//;VGM_LOG("DSP: bad header\n");
goto fail;
}
}
}
@ -130,8 +133,10 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) {
/* check type==0 and gain==0 */
{
for (i = 0; i < dspm->channel_count; i++) {
if (ch_header[i].format || ch_header[i].gain)
if (ch_header[i].format || ch_header[i].gain) {
//;VGM_LOG("DSP: bad type/gain\n");
goto fail;
}
}
}
@ -157,13 +162,15 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) {
for (i = 0; i < channels; i++) {
off_t channel_offset = dspm->start_offset + i*dspm->interleave;
if (ch_header[i].initial_ps != read_u8(channel_offset, sf))
if (ch_header[i].initial_ps != read_u8(channel_offset, sf)) {
//;VGM_LOG("DSP: bad initial ps\n");
goto fail;
}
}
}
/* check expected loop predictor/scale */
if (ch_header[0].loop_flag) {
if (ch_header[0].loop_flag && !dspm->ignore_loop_ps) {
int channels = dspm->channel_count;
if (dspm->single_header)
channels = 1;
@ -177,6 +184,7 @@ static VGMSTREAM* init_vgmstream_dsp_common(STREAMFILE* sf, dsp_meta *dspm) {
}
if (ch_header[i].loop_ps != read_u8(dspm->start_offset + i*dspm->interleave + loop_offset,sf)) {
//;VGM_LOG("DSP: bad loop ps: %x vs at %lx\n", ch_header[i].loop_ps, dspm->start_offset + i*dspm->interleave + loop_offset);
goto fail;
}
}
@ -870,25 +878,28 @@ fail:
}
/* NPD - Icon Games header + subinterleaved DSPs [Vertigo (Wii), Build n' Race (Wii)] */
VGMSTREAM* init_vgmstream_wii_ndp(STREAMFILE* sf) {
VGMSTREAM* init_vgmstream_dsp_ndp(STREAMFILE* sf) {
dsp_meta dspm = {0};
/* checks */
if (!check_extensions(sf, "ndp"))
/* .nds: standard
* .ndp: header id */
if (!check_extensions(sf, "nds,ndp"))
goto fail;
if (read_32bitBE(0x00,sf) != 0x4E445000) /* "NDP\0" */
if (!is_id32be(0x00,sf, "NDP\0"))
goto fail;
if (read_32bitLE(0x08,sf) + 0x18 != get_streamfile_size(sf))
if (read_u32le(0x08,sf) + 0x18 != get_streamfile_size(sf))
goto fail;
/* 0x0c: sample rate */
dspm.channel_count = read_32bitLE(0x10,sf);
dspm.channel_count = read_u32le(0x10,sf);
dspm.max_channels = 2;
dspm.header_offset = 0x18;
dspm.header_spacing = 0x60;
dspm.start_offset = dspm.header_offset + dspm.channel_count*dspm.header_spacing;
dspm.interleave = 0x04;
dspm.ignore_loop_ps = 1; /* some files loops from 0 but loop ps is null */
dspm.meta_type = meta_WII_NDP;
return init_vgmstream_dsp_common(sf, &dspm);
@ -1337,3 +1348,30 @@ VGMSTREAM* init_vgmstream_dsp_wiiadpcm(STREAMFILE* sf) {
fail:
return NULL;
}
/* CWAC - CRI wrapper [Mario & Sonic at the Rio 2016 Olympic Games (WiiU)] */
VGMSTREAM* init_vgmstream_dsp_cwac(STREAMFILE* sf) {
dsp_meta dspm = {0};
/* checks */
/* .dsp: assumed */
if (!check_extensions(sf, "dsp"))
goto fail;
if (!is_id32be(0x00,sf, "CWAC"))
goto fail;
dspm.channel_count = read_u16be(0x04,sf);
dspm.header_offset = read_u32be(0x08,sf);
dspm.interleave = read_u32be(0x0c,sf) - dspm.header_offset;
dspm.max_channels = 2;
dspm.header_spacing = dspm.interleave;
dspm.start_offset = dspm.header_offset + 0x60;
dspm.ignore_loop_ps = 1; /* loop offset seems relative to CWAC? also interleave affects it */
dspm.meta_type = meta_DSP_CWAC;
return init_vgmstream_dsp_common(sf, &dspm);
fail:
return NULL;
}

View File

@ -200,7 +200,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_redspark,
init_vgmstream_ivaud,
init_vgmstream_wii_wsd,
init_vgmstream_wii_ndp,
init_vgmstream_dsp_ndp,
init_vgmstream_ps2_sps,
init_vgmstream_ps2_xa2_rrp,
init_vgmstream_nds_hwas,
@ -514,6 +514,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_opus_nsopus,
init_vgmstream_sbk,
init_vgmstream_dsp_wiiadpcm,
init_vgmstream_dsp_cwac,
/* 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

@ -743,6 +743,7 @@ typedef enum {
meta_DSP_WIIVOICE,
meta_SBK,
meta_DSP_WIIADPCM,
meta_DSP_CWAC,
} meta_t;
/* standard WAVEFORMATEXTENSIBLE speaker positions */