mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-14 10:37:38 +01:00
Merge pull request #1379 from EdnessP/master
RWS: 0x809 File ID revision [Burnout 2 (multi)]
This commit is contained in:
commit
19c4f6b62e
@ -606,6 +606,7 @@
|
||||
<ClCompile Include="meta\rsd.c" />
|
||||
<ClCompile Include="meta\rsf.c" />
|
||||
<ClCompile Include="meta\rws.c" />
|
||||
<ClCompile Include="meta\rws_mono.c" />
|
||||
<ClCompile Include="meta\rwsd.c" />
|
||||
<ClCompile Include="meta\rwx.c" />
|
||||
<ClCompile Include="meta\rxws.c" />
|
||||
|
@ -1639,6 +1639,9 @@
|
||||
<ClCompile Include="meta\rws.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\rws_mono.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\rwsd.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -21,8 +21,6 @@ VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM* init_vgmstream_awd(STREAMFILE *sf);
|
||||
|
||||
VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile);
|
||||
@ -990,4 +988,8 @@ VGMSTREAM* init_vgmstream_sscf_encrypted(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
133
src/meta/rws_mono.c
Normal file
133
src/meta/rws_mono.c
Normal file
@ -0,0 +1,133 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
|
||||
|
||||
/* RWS - RenderWare Stream (with the tag 0x809) */
|
||||
VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
bool big_endian;
|
||||
char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE];
|
||||
int bit_depth = 0, channels = 0, idx, interleave, loop_flag, sample_rate = 0, total_subsongs, target_subsong = sf->stream_index;
|
||||
read_u32_t read_u32;
|
||||
off_t chunk_offset, header_offset, stream_offset = 0;
|
||||
size_t chunk_size, header_size, stream_size = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (read_u32le(0x00, sf) != 0x809) /* File ID */
|
||||
goto fail;
|
||||
|
||||
/* Burnout 2: Point of Impact (PS2, GCN, Xbox):
|
||||
* Predecessor to the common 0x80D-0x80F tag rws.c (which is also used in B2)
|
||||
* with some parts of it later reworked into awd.c seemingly */
|
||||
if (!check_extensions(sf, "rws"))
|
||||
goto fail;
|
||||
|
||||
/* Uses various chunk IDs across the file:
|
||||
* 0x00000809: File ID
|
||||
* 0x0000080A: File header ID
|
||||
* 0x0000080C: File data ID
|
||||
*
|
||||
* 0x00000802: Stream ID
|
||||
* 0x00000803: Stream header ID
|
||||
* 0x00000804: Stream data ID
|
||||
*/
|
||||
|
||||
chunk_offset = 0x0C;
|
||||
if (read_u32le(chunk_offset, sf) != 0x80A) /* File header ID */
|
||||
goto fail;
|
||||
chunk_size = read_u32le(chunk_offset + 0x04, sf); /* usually 0x44 */
|
||||
|
||||
read_string(header_name, STREAM_NAME_SIZE, chunk_offset + 0x40, sf);
|
||||
|
||||
chunk_offset += chunk_size + 0x0C;
|
||||
if (read_u32le(chunk_offset, sf) != 0x80C) /* File data ID */
|
||||
goto fail;
|
||||
|
||||
big_endian = guess_endian32(chunk_offset + 0x0C, sf);
|
||||
read_u32 = big_endian ? read_u32be : read_u32le;
|
||||
|
||||
total_subsongs = read_u32(chunk_offset + 0x0C, sf);
|
||||
|
||||
if (!target_subsong)
|
||||
target_subsong = 1;
|
||||
|
||||
chunk_offset += 0x10;
|
||||
for (idx = 1; idx <= total_subsongs; idx++) {
|
||||
if (read_u32le(chunk_offset, sf) != 0x802) /* Stream ID */
|
||||
goto fail;
|
||||
chunk_size = read_u32le(chunk_offset + 0x04, sf);
|
||||
|
||||
if (idx == target_subsong) {
|
||||
header_offset = chunk_offset + 0x0C;
|
||||
if (read_u32le(header_offset, sf) != 0x803) /* Stream header ID */
|
||||
goto fail;
|
||||
header_size = read_u32le(header_offset + 0x04, sf); /* usually 0xA0 */
|
||||
|
||||
sample_rate = read_u32(header_offset + 0x10, sf);
|
||||
stream_size = read_u32(header_offset + 0x18, sf);
|
||||
bit_depth = read_u8(header_offset + 0x1C, sf);
|
||||
channels = read_u8(header_offset + 0x1D, sf); /* always 1? */
|
||||
if (channels != 1)
|
||||
goto fail;
|
||||
|
||||
/* Assumed misc data offs/size at header_offset + 0x20 to +0x24
|
||||
* which is always empty since GCN uses PCM S16BE encoding here */
|
||||
|
||||
read_string(stream_name, STREAM_NAME_SIZE, header_offset + 0x7C, sf);
|
||||
|
||||
stream_offset = header_offset + header_size + 0x0C;
|
||||
if (read_u32le(stream_offset, sf) != 0x804) /* Stream data ID */
|
||||
goto fail;
|
||||
if (read_u32le(stream_offset + 0x04, sf) != stream_size)
|
||||
goto fail;
|
||||
}
|
||||
chunk_offset += chunk_size + 0x0C;
|
||||
}
|
||||
|
||||
if (total_subsongs < 1 || target_subsong > total_subsongs)
|
||||
goto fail;
|
||||
|
||||
interleave = 0;
|
||||
loop_flag = 0;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream)
|
||||
goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_RWS;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->stream_size = stream_size;
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
/* Likely unreliable, but currently only can be tested with Burnout 2 */
|
||||
switch (bit_depth) {
|
||||
case 4: /* PS-ADPCM, normally DSP-ADPCM would be 4 too (as is in awd.c) but GCN uses PCM */
|
||||
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
break;
|
||||
|
||||
case 16: /* PCM Signed 16-bit */
|
||||
vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels);
|
||||
vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", header_name, stream_name);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, stream_offset + 0x0C))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -529,6 +529,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
|
||||
init_vgmstream_s_p_sth,
|
||||
init_vgmstream_utf_ahx,
|
||||
init_vgmstream_ego_dic,
|
||||
init_vgmstream_rws_mono,
|
||||
|
||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||
init_vgmstream_scd_pcm,
|
||||
|
Loading…
Reference in New Issue
Block a user