mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +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
|
||||
RelativePath=".\meta\xma.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\xnb.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\xss.c"
|
||||
|
@ -436,6 +436,7 @@
|
||||
<ClCompile Include="meta\xbox_xwav.c" />
|
||||
<ClCompile Include="meta\x360_pasx.c" />
|
||||
<ClCompile Include="meta\xma.c" />
|
||||
<ClCompile Include="meta\xnb.c" />
|
||||
<ClCompile Include="meta\xss.c" />
|
||||
<ClCompile Include="meta\xvag.c" />
|
||||
<ClCompile Include="meta\xwb.c" />
|
||||
|
@ -1216,6 +1216,9 @@
|
||||
<ClCompile Include="meta\xma.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\xnb.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\x360_cxs.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -152,7 +152,7 @@ VGMSTREAM * init_vgmstream_riff(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);
|
||||
|
||||
|
143
src/meta/riff.c
143
src/meta/riff.c
@ -840,146 +840,3 @@ fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
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_ps3_ivag,
|
||||
init_vgmstream_ps2_2pfs,
|
||||
init_vgmstream_xnbm,
|
||||
init_vgmstream_xnb,
|
||||
init_vgmstream_rsd6oogv,
|
||||
init_vgmstream_ubi_ckd,
|
||||
init_vgmstream_ps2_vbk,
|
||||
|
Loading…
x
Reference in New Issue
Block a user