mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-06 14:44:25 +01:00
Move XNB from riff.c to xnb.c (cleanup)
This commit is contained in:
parent
a818f7adfe
commit
331bc187fa
@ -1341,6 +1341,10 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\meta\xma.c"
|
RelativePath=".\meta\xma.c"
|
||||||
>
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\xnb.c"
|
||||||
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\xss.c"
|
RelativePath=".\meta\xss.c"
|
||||||
|
@ -436,6 +436,7 @@
|
|||||||
<ClCompile Include="meta\xbox_xwav.c" />
|
<ClCompile Include="meta\xbox_xwav.c" />
|
||||||
<ClCompile Include="meta\x360_pasx.c" />
|
<ClCompile Include="meta\x360_pasx.c" />
|
||||||
<ClCompile Include="meta\xma.c" />
|
<ClCompile Include="meta\xma.c" />
|
||||||
|
<ClCompile Include="meta\xnb.c" />
|
||||||
<ClCompile Include="meta\xss.c" />
|
<ClCompile Include="meta\xss.c" />
|
||||||
<ClCompile Include="meta\xvag.c" />
|
<ClCompile Include="meta\xvag.c" />
|
||||||
<ClCompile Include="meta\xwb.c" />
|
<ClCompile Include="meta\xwb.c" />
|
||||||
|
@ -1216,6 +1216,9 @@
|
|||||||
<ClCompile Include="meta\xma.c">
|
<ClCompile Include="meta\xma.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\xnb.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\x360_cxs.c">
|
<ClCompile Include="meta\x360_cxs.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -152,7 +152,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE * streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_rifx(STREAMFILE * streamFile);
|
VGMSTREAM * init_vgmstream_rifx(STREAMFILE * streamFile);
|
||||||
|
|
||||||
VGMSTREAM * init_vgmstream_xnbm(STREAMFILE * streamFile);
|
VGMSTREAM * init_vgmstream_xnb(STREAMFILE * streamFile);
|
||||||
|
|
||||||
VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile);
|
VGMSTREAM * init_vgmstream_pos(STREAMFILE * streamFile);
|
||||||
|
|
||||||
|
143
src/meta/riff.c
143
src/meta/riff.c
@ -840,146 +840,3 @@ fail:
|
|||||||
if (vgmstream) close_vgmstream(vgmstream);
|
if (vgmstream) close_vgmstream(vgmstream);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo move
|
|
||||||
/* XNB - Microsoft XNA Game Studio 4.0 format */
|
|
||||||
VGMSTREAM * init_vgmstream_xnbm(STREAMFILE *streamFile) {
|
|
||||||
VGMSTREAM * vgmstream = NULL;
|
|
||||||
off_t start_offset;
|
|
||||||
int loop_flag = 0, version, flags, num_samples = 0;
|
|
||||||
size_t xnb_size, data_size;
|
|
||||||
|
|
||||||
struct riff_fmt_chunk fmt;
|
|
||||||
|
|
||||||
|
|
||||||
/* check extension, case insensitive */
|
|
||||||
if ( !check_extensions(streamFile,"xnb"))
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
/* check header */
|
|
||||||
if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
|
|
||||||
goto fail;
|
|
||||||
/* 0x04: platform: ‘w’ = Microsoft Windows, ‘m’ = Windows Phone 7, ‘x’ = Xbox 360, 'a' = Android */
|
|
||||||
|
|
||||||
version = read_8bit(0x04,streamFile);
|
|
||||||
if (version != 5) goto fail; /* XNA 4.0 only */
|
|
||||||
|
|
||||||
flags = read_8bit(0x05,streamFile);
|
|
||||||
if (flags & 0x80) goto fail; /* compressed with XMemCompress, not public */
|
|
||||||
//if (flags & 0x01) goto fail; /* XMA flag? */
|
|
||||||
|
|
||||||
/* "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) */
|
|
||||||
{
|
|
||||||
char reader_name[255+1];
|
|
||||||
off_t current_chunk = 0xa;
|
|
||||||
int reader_string_len;
|
|
||||||
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 */
|
|
||||||
|
|
||||||
/* type reader count, accept only one for now */
|
|
||||||
if (read_8bit(current_chunk++, streamFile) != 1)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
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);
|
|
||||||
current_chunk += 4;
|
|
||||||
|
|
||||||
if (-1 == read_fmt(0, /* big endian == false */
|
|
||||||
streamFile,
|
|
||||||
current_chunk-8, /* read_fmt() expects to skip "fmt "+size */
|
|
||||||
&fmt,
|
|
||||||
0, /* sns == false */
|
|
||||||
0)) /* mwv == false */
|
|
||||||
goto fail;
|
|
||||||
current_chunk += fmt_chunk_size;
|
|
||||||
|
|
||||||
data_size = read_32bitLE(current_chunk, streamFile);
|
|
||||||
current_chunk += 4;
|
|
||||||
|
|
||||||
start_offset = current_chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fmt.coding_type) {
|
|
||||||
case coding_PCM16LE:
|
|
||||||
num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 16);
|
|
||||||
break;
|
|
||||||
case coding_PCM8_U_int:
|
|
||||||
num_samples = pcm_bytes_to_samples(data_size, fmt.channel_count, 8);
|
|
||||||
break;
|
|
||||||
case coding_MSADPCM:
|
|
||||||
num_samples = msadpcm_bytes_to_samples(data_size, fmt.block_size, fmt.channel_count);
|
|
||||||
break;
|
|
||||||
case coding_MS_IMA:
|
|
||||||
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);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
VGM_LOG("XNB: unknown codec 0x%x\n", fmt.coding_type);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
|
||||||
vgmstream = allocate_vgmstream(fmt.channel_count,loop_flag);
|
|
||||||
if (!vgmstream) goto fail;
|
|
||||||
|
|
||||||
vgmstream->num_samples = num_samples;
|
|
||||||
vgmstream->sample_rate = fmt.sample_rate;
|
|
||||||
|
|
||||||
vgmstream->meta_type = meta_XNB;
|
|
||||||
vgmstream->coding_type = fmt.coding_type;
|
|
||||||
|
|
||||||
if (fmt.channel_count > 1) {
|
|
||||||
switch (fmt.coding_type) {
|
|
||||||
case coding_PCM8_U_int:
|
|
||||||
case coding_MS_IMA:
|
|
||||||
case coding_MSADPCM:
|
|
||||||
vgmstream->layout_type = layout_none;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vgmstream->layout_type = layout_interleave;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fmt.coding_type) {
|
|
||||||
case coding_MSADPCM:
|
|
||||||
case coding_MS_IMA:
|
|
||||||
vgmstream->interleave_block_size = fmt.block_size;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
vgmstream->interleave_block_size = fmt.interleave;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
return vgmstream;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
close_vgmstream(vgmstream);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
123
src/meta/xnb.c
Normal file
123
src/meta/xnb.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
/* XNB - Microsoft XNA Game Studio 4.0 format */
|
||||||
|
VGMSTREAM * init_vgmstream_xnb(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
off_t start_offset;
|
||||||
|
int loop_flag = 0, channel_count;
|
||||||
|
int flags, codec, sample_rate, block_size, bps;
|
||||||
|
size_t xnb_size, data_size;
|
||||||
|
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
if ( !check_extensions(streamFile,"xnb"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* check header */
|
||||||
|
if ((read_32bitBE(0,streamFile) & 0xFFFFFF00) != 0x584E4200) /* "XNB" */
|
||||||
|
goto fail;
|
||||||
|
/* 0x04: platform: ‘w’ = Microsoft Windows, ‘m’ = Windows Phone 7, ‘x’ = Xbox 360, 'a' = Android */
|
||||||
|
|
||||||
|
if (read_8bit(0x04,streamFile) != 0x05) /* XNA 4.0 version only */
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
flags = read_8bit(0x05,streamFile);
|
||||||
|
if (flags & 0x80) goto fail; /* compressed with XMemCompress */
|
||||||
|
//if (flags & 0x01) goto fail; /* XMA/big endian flag? */
|
||||||
|
|
||||||
|
/* "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) */
|
||||||
|
{
|
||||||
|
char reader_name[255+1];
|
||||||
|
off_t current_chunk = 0xa;
|
||||||
|
int reader_string_len;
|
||||||
|
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 */
|
||||||
|
|
||||||
|
/* type reader count, accept only one for now */
|
||||||
|
if (read_8bit(current_chunk++, streamFile) != 1)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
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);
|
||||||
|
current_chunk += 4;
|
||||||
|
|
||||||
|
{
|
||||||
|
codec = read_16bitLE(current_chunk+0x00, streamFile);
|
||||||
|
channel_count = read_16bitLE(current_chunk+0x02, streamFile);
|
||||||
|
sample_rate = read_32bitLE(current_chunk+0x04, streamFile);
|
||||||
|
block_size = read_16bitLE(current_chunk+0x0c, streamFile);
|
||||||
|
bps = read_16bitLE(current_chunk+0x0e, streamFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
current_chunk += fmt_chunk_size;
|
||||||
|
|
||||||
|
data_size = read_32bitLE(current_chunk, streamFile);
|
||||||
|
current_chunk += 4;
|
||||||
|
|
||||||
|
start_offset = current_chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
vgmstream->meta_type = meta_XNB;
|
||||||
|
|
||||||
|
switch (codec) {
|
||||||
|
case 0x01:
|
||||||
|
vgmstream->coding_type = bps == 8 ? coding_PCM8_U_int : coding_PCM16LE;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = block_size / channel_count;
|
||||||
|
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, bps);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02:
|
||||||
|
vgmstream->coding_type = coding_MSADPCM;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->interleave_block_size = block_size;
|
||||||
|
vgmstream->num_samples = msadpcm_bytes_to_samples(data_size, block_size, channel_count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x11:
|
||||||
|
vgmstream->coding_type = coding_MS_IMA;
|
||||||
|
vgmstream->layout_type = layout_none;
|
||||||
|
vgmstream->interleave_block_size = block_size;
|
||||||
|
vgmstream->num_samples = ms_ima_bytes_to_samples(data_size, block_size, channel_count);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
VGM_LOG("XNB: unknown codec 0x%x\n", codec);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) )
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -316,7 +316,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
|||||||
init_vgmstream_ps2_hsf,
|
init_vgmstream_ps2_hsf,
|
||||||
init_vgmstream_ps3_ivag,
|
init_vgmstream_ps3_ivag,
|
||||||
init_vgmstream_ps2_2pfs,
|
init_vgmstream_ps2_2pfs,
|
||||||
init_vgmstream_xnbm,
|
init_vgmstream_xnb,
|
||||||
init_vgmstream_rsd6oogv,
|
init_vgmstream_rsd6oogv,
|
||||||
init_vgmstream_ubi_ckd,
|
init_vgmstream_ubi_ckd,
|
||||||
init_vgmstream_ps2_vbk,
|
init_vgmstream_ps2_vbk,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user