Merge pull request #1021 from bnnm/xws-atsl

- Fix some ATSL [Dynasty Warriors 9 DLC (PC)]
- Add WiiU .XWS [Ninja Gaiden 3 Razor's Edge (WiiU)]
This commit is contained in:
bnnm 2021-11-28 14:32:47 +01:00 committed by GitHub
commit f45715daf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 83 additions and 21 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

@ -36,16 +36,18 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
* 00000301 00020101 (same)
* - 01040301 00060301 .atsl4 from Nobunaga's Ambition: Sphere of Influence (PS4)[ATRAC9]
* - 00060301 00040301 atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9]
* - 00060301 00010301 atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS]
* - 000A0301 00010501 atsl in G1L from Warriors All-Stars (PC)[KOVS]
* - 000B0301 00080601 atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS]
* - 00060301 00040301 .atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9]
* - 00060301 00010301 .atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS]
* - 000A0301 00010501 .atsl in G1L from Warriors All-Stars (PC)[KOVS] 2017-09
* - 01000000 01010501 .atsl from Nioh (PC)[KOVS] 2017-11
* - 01000000 00010501 .atsl from Nioh (PC)[KOVS] 2017-11
* - 000B0301 00080601 .atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS] 2017-09
* - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC]
* - 01000000 01010501 .atsl from Nioh (PC)[KOVS]
* - 01000000 00010501 .atsl from Nioh (PC)[KOVS]
* - 010D0301 01010601 .atsl from Dynasty Warriors 9 DLC (PC)[KOVS]
*/
type = read_u16le(0x0c, sf);
//version = read_u16le(0x0e, sf);
switch(type) {
case 0x0100: /* KOVS */
init_vgmstream = init_vgmstream_ogg_vorbis;
@ -95,11 +97,16 @@ VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
/* parse entry header (in machine endianness) */
for (i = 0; i < entries; i++) {
int is_unique = 1;
uint32_t entry_subfile_offset, entry_subfile_size;
/* 0x00: id */
uint32_t entry_subfile_offset = read_u32(header_size + i*entry_size + 0x04,sf);
uint32_t entry_subfile_size = read_u32(header_size + i*entry_size + 0x08,sf);
/* 0x08+: channels/sample rate/num_samples/loop_start/etc (match subfile header) */
entry_subfile_offset = read_u32(header_size + i*entry_size + 0x04,sf);
entry_subfile_size = read_u32(header_size + i*entry_size + 0x08,sf);
/* 0x10+: config, channels/sample rate/num_samples/loop_start/channel layout/etc (matches subfile header) */
/* dummy entry, seen in DW9 DLC (has unique config though) */
if (!entry_subfile_offset && !entry_subfile_size)
continue;
/* check if current entry was repeated in a prev entry */
for (j = 0; j < i; j++) {

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;