mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Basic support for multi-stream SCD (FF XIV sfx)
This commit is contained in:
parent
8913ccdd47
commit
8b8a9ecd4e
@ -49,9 +49,11 @@ static void scd_ogg_decrypt_v3_callback(void *ptr, size_t size, size_t nmemb, vo
|
||||
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
off_t start_offset, meta_offset_offset, meta_offset, post_meta_offset, data_size;
|
||||
off_t start_offset, tables_offset, headers_offset, meta_offset, post_meta_offset, stream_size;
|
||||
int headers_entries;
|
||||
int32_t loop_start, loop_end;
|
||||
|
||||
int target_stream = 1; /* N=Nth stream, 0=auto (first) */
|
||||
int loop_flag = 0;
|
||||
int channel_count;
|
||||
int codec_id;
|
||||
@ -68,56 +70,75 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
if (read_32bitBE(0,streamFile) != 0x53454442) goto fail;
|
||||
/* SSCF */
|
||||
if (read_32bitBE(4,streamFile) != 0x53534346) goto fail;
|
||||
if (read_32bitBE(8,streamFile) == 2 ||
|
||||
read_32bitBE(8,streamFile) == 3) {
|
||||
/* version 2 BE, as seen in FFXIII demo for PS3 */
|
||||
/* version 3 BE, as seen in FFXIII for PS3 */
|
||||
|
||||
/** main header section **/
|
||||
if (read_32bitBE(8,streamFile) == 2 || /* version 2 BE, as seen in FFXIII demo for PS3 */
|
||||
read_32bitBE(8,streamFile) == 3) { /* version 3 BE, as seen in FFXIII for PS3 */
|
||||
|
||||
read_32bit = read_32bitBE;
|
||||
read_16bit = read_16bitBE;
|
||||
//size_offset = 0x14;
|
||||
meta_offset_offset = 0x40 + read_16bit(0xe,streamFile);
|
||||
} else if (read_32bitLE(8,streamFile) == 3 ||
|
||||
} else if (read_32bitLE(8,streamFile) == 3 || /* version 2/3 LE, as seen in FFXIV for PC (and others?) */
|
||||
read_32bitLE(8,streamFile) == 2) {
|
||||
/* version 2/3 LE, as seen in FFXIV for PC (and others?) */
|
||||
|
||||
read_32bit = read_32bitLE;
|
||||
read_16bit = read_16bitLE;
|
||||
//size_offset = 0x10;
|
||||
meta_offset_offset = 0x40 + read_16bit(0xe,streamFile);
|
||||
} else goto fail;
|
||||
|
||||
/* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */
|
||||
/* 0xc: probably 00=LE, 01=BE */
|
||||
/* 0xd: unk (always 0x04) */
|
||||
tables_offset = read_16bit(0xe,streamFile);
|
||||
|
||||
#if 0
|
||||
/* never mind, FFXIII music_68tak.ps3.scd is 0x80 shorter */
|
||||
/* check file size with header value */
|
||||
if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
meta_offset = read_32bit(meta_offset_offset,streamFile);
|
||||
data_size = read_32bit(meta_offset + 0x0, streamFile); /* music size */
|
||||
/** offset tables **/
|
||||
/* 0x00: table1_unknown entries */
|
||||
/* 0x02: table2_headers entries */
|
||||
/* 0x04: table3_unknown entries */
|
||||
/* 0x06: unknown (varies) */
|
||||
/* 0x08: table1_unknown start offset */
|
||||
/* 0x0c: table2_headers start offset */
|
||||
/* 0x10: table3_unknown start offset */
|
||||
/* 0x14: unknown (0x0) */
|
||||
/* 0x18: unknown offset */
|
||||
/* 0x1c: unknown (0x0) */
|
||||
headers_entries = read_16bit(tables_offset+0x02,streamFile);
|
||||
VGM_ASSERT(headers_entries > 1, "SCD: multiple streams found (%i entries)\n", headers_entries);
|
||||
if (target_stream == 0) target_stream = 1; /* auto: default to 1 */
|
||||
if (target_stream > headers_entries) goto fail;
|
||||
headers_offset = read_32bit(tables_offset+0x0c,streamFile);
|
||||
|
||||
/** header table entries (each is an uint32_t offset to stream header) **/
|
||||
meta_offset = read_32bit(headers_offset + (target_stream-1)*4,streamFile);
|
||||
|
||||
/** stream header **/
|
||||
stream_size = read_32bit(meta_offset + 0x0, streamFile);
|
||||
channel_count = read_32bit(meta_offset+4,streamFile);
|
||||
/* 0x8 sample rate */
|
||||
codec_id = read_32bit(meta_offset+0xc,streamFile);
|
||||
|
||||
/* check that chunk size equals stream size (?) */
|
||||
loop_start = read_32bit(meta_offset+0x10,streamFile);
|
||||
loop_end = read_32bit(meta_offset+0x14,streamFile);
|
||||
loop_flag = (loop_end > 0);
|
||||
|
||||
channel_count = read_32bit(meta_offset+4,streamFile);
|
||||
codec_id = read_32bit(meta_offset+0xc,streamFile);
|
||||
|
||||
post_meta_offset = meta_offset + 0x20;
|
||||
|
||||
/* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks
|
||||
before anything else */
|
||||
|
||||
/* data at meta_offset is only 0x20 bytes, but there may be auxiliary chunks before anything else */
|
||||
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
|
||||
for (; aux_chunk_count > 0; aux_chunk_count --)
|
||||
{
|
||||
for (; aux_chunk_count > 0; aux_chunk_count--) {
|
||||
/* skip aux chunks */
|
||||
/*printf("skipping %08x\n", read_32bitBE(post_meta_offset, streamFile));*/
|
||||
post_meta_offset += read_32bit(post_meta_offset+4,streamFile);
|
||||
}
|
||||
|
||||
start_offset = post_meta_offset + read_32bit(meta_offset+0x18,streamFile);
|
||||
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
if (codec_id == 0x6)
|
||||
{
|
||||
@ -174,8 +195,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
} else if (xor_version == 3) {
|
||||
inf.decryption_enabled = 1;
|
||||
inf.decryption_callback = scd_ogg_decrypt_v3_callback;
|
||||
inf.scd_xor = data_size & 0xFF; /* xor_byte is not used? */
|
||||
inf.scd_xor_length = data_size; /* full file is XOR'ed */
|
||||
inf.scd_xor = stream_size & 0xFF; /* xor_byte is not used? */
|
||||
inf.scd_xor_length = stream_size; /* full file is XOR'ed */
|
||||
}
|
||||
result = init_vgmstream_ogg_vorbis_callbacks(streamFile, filename, NULL, start_offset, &inf);
|
||||
/* always? */
|
||||
@ -197,7 +218,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
/* PCM */
|
||||
vgmstream->coding_type = coding_PCM16LE_int;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->num_samples = read_32bit(meta_offset+0,streamFile) / 2 / channel_count;
|
||||
vgmstream->num_samples = stream_size / 2 / channel_count;
|
||||
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start / 2 / channel_count;
|
||||
@ -212,6 +233,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
struct mpg123_frameinfo mi;
|
||||
coding_t ct;
|
||||
|
||||
/* Drakengard 3, some Kingdom Hearts */
|
||||
if (vgmstream->sample_rate == 47999)
|
||||
vgmstream->sample_rate = 48000;
|
||||
if (vgmstream->sample_rate == 44099)
|
||||
@ -226,7 +248,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = ct;
|
||||
vgmstream->layout_type = layout_mpeg;
|
||||
if (mi.vbr != MPG123_CBR) goto fail;
|
||||
vgmstream->num_samples = mpeg_bytes_to_samples(read_32bit(meta_offset+0,streamFile), &mi);
|
||||
vgmstream->num_samples = mpeg_bytes_to_samples(stream_size, &mi);
|
||||
vgmstream->num_samples -= vgmstream->num_samples%576;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi);
|
||||
@ -243,7 +265,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bit(post_meta_offset+0xc,streamFile);
|
||||
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bit(meta_offset+0,streamFile), vgmstream->interleave_block_size, vgmstream->channels);
|
||||
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->interleave_block_size, vgmstream->channels);
|
||||
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels);
|
||||
@ -344,7 +366,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
VGM_LOG("SCD unknown codec_id: %x\n", codec_id);
|
||||
VGM_LOG("SCD: unknown codec_id %x\n", codec_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user