Improve XNB [Dragon's Blade (Android)]; add .DA wav; extra exts

This commit is contained in:
bnnm 2017-09-24 22:27:33 +02:00
parent e51bafec97
commit 9f90ca9181
4 changed files with 64 additions and 87 deletions

View File

@ -40,6 +40,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("AIFCL", aifcl);
VGMSTREAM_DECLARE_FILE_TYPE("AIX", aix); VGMSTREAM_DECLARE_FILE_TYPE("AIX", aix);
VGMSTREAM_DECLARE_FILE_TYPE("AKB", akb); VGMSTREAM_DECLARE_FILE_TYPE("AKB", akb);
VGMSTREAM_DECLARE_FILE_TYPE("AMTS", amts); VGMSTREAM_DECLARE_FILE_TYPE("AMTS", amts);
VGMSTREAM_DECLARE_FILE_TYPE("AO", ao);
VGMSTREAM_DECLARE_FILE_TYPE("AS4", as4); VGMSTREAM_DECLARE_FILE_TYPE("AS4", as4);
VGMSTREAM_DECLARE_FILE_TYPE("ASD", asd); VGMSTREAM_DECLARE_FILE_TYPE("ASD", asd);
VGMSTREAM_DECLARE_FILE_TYPE("ASF", asf); VGMSTREAM_DECLARE_FILE_TYPE("ASF", asf);
@ -92,6 +93,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("CNK", cnk);
VGMSTREAM_DECLARE_FILE_TYPE("CPS", cps); VGMSTREAM_DECLARE_FILE_TYPE("CPS", cps);
VGMSTREAM_DECLARE_FILE_TYPE("CXS", cxs); VGMSTREAM_DECLARE_FILE_TYPE("CXS", cxs);
VGMSTREAM_DECLARE_FILE_TYPE("DA", da);
VGMSTREAM_DECLARE_FILE_TYPE("DBM", dbm); VGMSTREAM_DECLARE_FILE_TYPE("DBM", dbm);
VGMSTREAM_DECLARE_FILE_TYPE("DCS", dcs); VGMSTREAM_DECLARE_FILE_TYPE("DCS", dcs);
VGMSTREAM_DECLARE_FILE_TYPE("DDSP", ddsp); VGMSTREAM_DECLARE_FILE_TYPE("DDSP", ddsp);
@ -142,6 +144,7 @@ VGMSTREAM_DECLARE_FILE_TYPE("ILD", ild);
VGMSTREAM_DECLARE_FILE_TYPE("INT", int); VGMSTREAM_DECLARE_FILE_TYPE("INT", int);
VGMSTREAM_DECLARE_FILE_TYPE("ISD", isd); VGMSTREAM_DECLARE_FILE_TYPE("ISD", isd);
VGMSTREAM_DECLARE_FILE_TYPE("ISWS", isws); VGMSTREAM_DECLARE_FILE_TYPE("ISWS", isws);
VGMSTREAM_DECLARE_FILE_TYPE("ITL", itl);
VGMSTREAM_DECLARE_FILE_TYPE("IVAUD", ivaud); VGMSTREAM_DECLARE_FILE_TYPE("IVAUD", ivaud);
VGMSTREAM_DECLARE_FILE_TYPE("IVAG", ivag); VGMSTREAM_DECLARE_FILE_TYPE("IVAG", ivag);
VGMSTREAM_DECLARE_FILE_TYPE("IVB", ivb); VGMSTREAM_DECLARE_FILE_TYPE("IVB", ivb);

View File

@ -33,6 +33,7 @@ static const char* extension_list[] = {
"aix", "aix",
"akb", "akb",
"amts", //fake extension (to be removed) "amts", //fake extension (to be removed)
"ao", //txth/reserved [Cloudphobia (PC)]
"as4", "as4",
"asd", "asd",
"asf", "asf",
@ -85,6 +86,7 @@ static const char* extension_list[] = {
"cps", "cps",
"cxs", "cxs",
"da",
"dbm", "dbm",
"dcs", "dcs",
"ddsp", "ddsp",
@ -135,6 +137,7 @@ static const char* extension_list[] = {
"int", "int",
"isd", "isd",
"isws", "isws",
"itl", //txth/reserved [Charinko Hero (GC)]
"ivaud", "ivaud",
"ivag", "ivag",
"ivb", "ivb",
@ -660,7 +663,7 @@ static const meta_info meta_info_list[] = {
{meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"}, {meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"},
{meta_RIFX_WAVE, "RIFX WAVE header"}, {meta_RIFX_WAVE, "RIFX WAVE header"},
{meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"}, {meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"},
{meta_XNBm, "XNBm header"}, {meta_XNB, "Microsoft XNA Game Studio 4.0 header"},
{meta_PCM_SCD, "PCM file with custom header (SCD)"}, {meta_PCM_SCD, "PCM file with custom header (SCD)"},
{meta_PCM_PS2, "PCM file with custom header (PS2)"}, {meta_PCM_PS2, "PCM file with custom header (PS2)"},
{meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV Header"},

View File

@ -2,6 +2,7 @@
#include "../coding/coding.h" #include "../coding/coding.h"
#include "../layout/layout.h" #include "../layout/layout.h"
#include "../util.h" #include "../util.h"
#include <string.h>
/* Resource Interchange File Format */ /* Resource Interchange File Format */
@ -262,7 +263,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("wav",filename_extension(filename)) && if (strcasecmp("wav",filename_extension(filename)) &&
strcasecmp("lwav",filename_extension(filename)) strcasecmp("lwav",filename_extension(filename)) &&
strcasecmp("da",filename_extension(filename)) /* SD Gundam - Over Galaxian, The Great Battle VI (PS) */
#ifndef VGM_USE_FFMPEG #ifndef VGM_USE_FFMPEG
&& strcasecmp("sgb",filename_extension(filename)) /* SGB has proper support with FFmpeg in sgxd */ && strcasecmp("sgb",filename_extension(filename)) /* SGB has proper support with FFmpeg in sgxd */
#endif #endif
@ -835,79 +837,66 @@ fail:
return NULL; return NULL;
} }
/* XNBm (Windows 7 Phone) */ //todo move
/* XNB - Microsoft XNA Game Studio 4.0 format */
VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT]; off_t start_offset;
int loop_flag = 0, version, flags, num_samples = 0;
size_t xnb_size, data_size;
struct riff_fmt_chunk fmt; struct riff_fmt_chunk fmt;
off_t file_size = -1;
int sample_count = 0;
off_t start_offset = -1;
int loop_flag = 0;
#if 0
long loop_start_ms = -1;
long loop_end_ms = -1;
off_t loop_start_offset = -1;
off_t loop_end_offset = -1;
#endif
uint32_t xnbm_size;
uint32_t data_size = 0;
/* check extension, case insensitive */ /* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename)); if ( !check_extensions(streamFile,"xnb"))
if (strcasecmp("xnb",filename_extension(filename)))
{
goto fail; goto fail;
}
/* check header */ /* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x584E426d) /* "XNBm" */ if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
goto fail;
/* check version? */
if ((uint32_t)read_16bitLE(4,streamFile)!=5)
goto fail; goto fail;
/* 0x04: platform: w = Microsoft Windows, m = Windows Phone 7, x = Xbox 360, 'a' = Android */
xnbm_size = read_32bitLE(6,streamFile); version = read_8bit(0x04,streamFile);
file_size = get_streamfile_size(streamFile); if (version != 5) goto fail; /* XNA 4.0 only */
/* check for tructated XNBm */ flags = read_8bit(0x05,streamFile);
if (file_size < xnbm_size) goto fail; if (flags & 0x80) goto fail; /* compressed with XMemCompress, not public */
//if (flags & 0x01) goto fail; /* XMA flag? */
/* read through chunks to verify format and find metadata */ /* "check for truncated XNB" (???) */
xnb_size = read_32bitLE(0x06,streamFile);
if (get_streamfile_size(streamFile) < xnb_size) goto fail;
/* XNB contains "type reader" class references to parse "shared resource" data (can be any implemented filetype) */
{ {
off_t current_chunk = 0xa; /* start with first chunk */ char reader_name[255+1];
int id_string_len; off_t current_chunk = 0xa;
int reader_string_len;
uint32_t fmt_chunk_size; uint32_t fmt_chunk_size;
const char * type_sound = "Microsoft.Xna.Framework.Content.SoundEffectReader"; /* partial "fmt" chunk or XMA */
//const char * type_song = "Microsoft.Xna.Framework.Content.SongReader"; /* just references a companion .wma */
/* flag? count of strings? */ /* type reader count, accept only one for now */
if (read_8bit(current_chunk ++, streamFile) != 1)
goto fail;
/* string length */
id_string_len = read_8bit(current_chunk ++, streamFile);
/* skip string */
/* may want to check this ID "Microsoft.Xna.Framework.Content.SoundEffectReader" */
current_chunk += id_string_len;
/* ???? */
if (read_32bitLE(current_chunk, streamFile) != 0)
goto fail;
current_chunk += 4;
/* ???? */
if (read_8bit(current_chunk ++, streamFile) != 0)
goto fail;
/* flag? count of chunks? */
if (read_8bit(current_chunk++, streamFile) != 1) if (read_8bit(current_chunk++, streamFile) != 1)
goto fail; goto fail;
/* fmt size */ reader_string_len = read_8bit(current_chunk++, streamFile); /* doesn't count null */
if (reader_string_len > 255) goto fail;
/* check SoundEffect type string */
if (read_string(reader_name,reader_string_len+1,current_chunk,streamFile) != reader_string_len)
goto fail;
if ( strcmp(reader_name, type_sound) != 0 )
goto fail;
current_chunk += reader_string_len + 1;
current_chunk += 4; /* reader version */
/* shared resource count */
if (read_8bit(current_chunk++, streamFile) != 1)
goto fail;
/* shared resource: partial "fmt" chunk */
fmt_chunk_size = read_32bitLE(current_chunk, streamFile); fmt_chunk_size = read_32bitLE(current_chunk, streamFile);
current_chunk += 4; current_chunk += 4;
@ -918,10 +907,8 @@ VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) {
0, /* sns == false */ 0, /* sns == false */
0)) /* mwv == false */ 0)) /* mwv == false */
goto fail; goto fail;
current_chunk += fmt_chunk_size; current_chunk += fmt_chunk_size;
/* data size! */
data_size = read_32bitLE(current_chunk, streamFile); data_size = read_32bitLE(current_chunk, streamFile);
current_chunk += 4; current_chunk += 4;
@ -930,40 +917,40 @@ VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) {
switch (fmt.coding_type) { switch (fmt.coding_type) {
case coding_PCM16LE: case coding_PCM16LE:
sample_count = data_size/2/fmt.channel_count; num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 16);
break; break;
case coding_PCM8_U_int: case coding_PCM8_U_int:
sample_count = data_size/fmt.channel_count; num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 8);
break; break;
case coding_MSADPCM: case coding_MSADPCM:
sample_count = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count); num_samples = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
break; break;
case coding_MS_IMA: case coding_MS_IMA:
sample_count = (data_size / fmt.block_size) * (fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count + num_samples = (data_size / fmt.block_size) * (fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count +
((data_size % fmt.block_size) ? (data_size % fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count : 0); ((data_size % fmt.block_size) ? (data_size % fmt.block_size - 4 * fmt.channel_count) * 2 / fmt.channel_count : 0);
break; break;
default: default:
VGM_LOG("XNB: unknown codec 0x%x\n", fmt.coding_type);
goto fail; goto fail;
} }
/* build the VGMSTREAM */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag); vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ vgmstream->num_samples = num_samples;
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = fmt.sample_rate; vgmstream->sample_rate = fmt.sample_rate;
vgmstream->meta_type = meta_XNB;
vgmstream->coding_type = fmt.coding_type; vgmstream->coding_type = fmt.coding_type;
vgmstream->layout_type = layout_none;
if (fmt.channel_count > 1) { if (fmt.channel_count > 1) {
switch (fmt.coding_type) { switch (fmt.coding_type) {
case coding_PCM8_U_int: case coding_PCM8_U_int:
case coding_MS_IMA: case coding_MS_IMA:
case coding_MSADPCM: case coding_MSADPCM:
// use layout_none from above vgmstream->layout_type = layout_none;
break; break;
default: default:
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
@ -971,40 +958,24 @@ VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) {
} }
} }
vgmstream->interleave_block_size = fmt.interleave;
switch (fmt.coding_type) { switch (fmt.coding_type) {
case coding_MSADPCM: case coding_MSADPCM:
case coding_MS_IMA: case coding_MS_IMA:
// override interleave_block_size with frame size
vgmstream->interleave_block_size = fmt.block_size; vgmstream->interleave_block_size = fmt.block_size;
break; break;
default: default:
// use interleave from above vgmstream->interleave_block_size = fmt.interleave;
break; break;
} }
vgmstream->meta_type = meta_XNBm;
/* open the file, set up each channel */ if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
{ goto fail;
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<fmt.channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
start_offset+i*fmt.interleave;
}
}
return vgmstream; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

@ -479,7 +479,7 @@ typedef enum {
meta_RIFF_WAVE_SNS, /* .sns RIFF */ meta_RIFF_WAVE_SNS, /* .sns RIFF */
meta_RIFX_WAVE, /* RIFX, for big-endian WAVs */ meta_RIFX_WAVE, /* RIFX, for big-endian WAVs */
meta_RIFX_WAVE_smpl, /* RIFX w/ loop data in smpl chunk */ meta_RIFX_WAVE_smpl, /* RIFX w/ loop data in smpl chunk */
meta_XNBm, /* XNBm, which has a RIFF fmt chunk */ meta_XNB, /* XNA Game Studio 4.0 */
meta_PC_MXST, /* Lego Island MxSt */ meta_PC_MXST, /* Lego Island MxSt */
meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */ meta_PC_SOB_SAB, /* Worms 4 Mayhem SOB+SAB file */
meta_NWA, /* Visual Art's NWA */ meta_NWA, /* Visual Art's NWA */