mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 15:54:05 +01:00
Fix SQEX .scd XMA total samples + cleanup
This commit is contained in:
parent
68b9164d72
commit
9a5c116f1c
@ -384,10 +384,6 @@
|
||||
RelativePath=".\meta\sfh_streamfile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\sqex_scd_streamfile.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\sqex_sead_streamfile.h"
|
||||
>
|
||||
|
@ -138,7 +138,6 @@
|
||||
<ClInclude Include="meta\sab_streamfile.h" />
|
||||
<ClInclude Include="meta\riff_ogg_streamfile.h" />
|
||||
<ClInclude Include="meta\sfh_streamfile.h" />
|
||||
<ClInclude Include="meta\sqex_scd_streamfile.h" />
|
||||
<ClInclude Include="meta\sqex_sead_streamfile.h" />
|
||||
<ClInclude Include="meta\txth_streamfile.h" />
|
||||
<ClInclude Include="meta\ubi_bao_streamfile.h" />
|
||||
|
@ -179,9 +179,6 @@
|
||||
<ClInclude Include="meta\sfh_streamfile.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="meta\sqex_scd_streamfile.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="meta\sqex_sead_streamfile.h">
|
||||
<Filter>meta\Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -1,38 +1,39 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "sqex_scd_streamfile.h"
|
||||
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource);
|
||||
static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource);
|
||||
static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource);
|
||||
static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource);
|
||||
#endif
|
||||
|
||||
/* SCD - Square-Enix games (FF XIII, XIV) */
|
||||
VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset, tables_offset, meta_offset, extradata_offset, name_offset = 0;
|
||||
int32_t stream_size, extradata_size, loop_start, loop_end;
|
||||
|
||||
int loop_flag = 0, channel_count, codec, sample_rate;
|
||||
int loop_flag = 0, channels, codec, sample_rate;
|
||||
int version, target_entry, aux_chunk_count;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
int big_endian;
|
||||
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
/* check extension, case insensitive */
|
||||
if ( !check_extensions(streamFile, "scd") )
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "scd"))
|
||||
goto fail;
|
||||
|
||||
/** main header **/
|
||||
if (read_32bitBE(0x00,streamFile) != 0x53454442 && /* "SEDB" */
|
||||
read_32bitBE(0x04,streamFile) != 0x53534346) /* "SSCF" */
|
||||
if (!is_id32be(0x00,sf, "SEDB") &&
|
||||
!is_id32be(0x04,sf, "SSCF"))
|
||||
goto fail;
|
||||
|
||||
if (read_8bit(0x0c,streamFile) == 0x01) { /* big endian flag */
|
||||
big_endian = read_u8(0x0c,sf) == 0x01;
|
||||
if (big_endian) { /* big endian flag */
|
||||
//size_offset = 0x14;
|
||||
read_32bit = read_32bitBE;
|
||||
read_16bit = read_16bitBE;
|
||||
@ -42,21 +43,20 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
read_16bit = read_16bitLE;
|
||||
}
|
||||
|
||||
/* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
|
||||
if (read_8bit(0x0d,streamFile) != 0x04)
|
||||
goto fail;
|
||||
|
||||
/* v2: FFXIII demo (PS3), FFT0 test files (PC); v3: common; v4: Kingdom Hearts 2.8 (PS4) */
|
||||
version = read_32bit(0x08,streamFile);
|
||||
version = read_32bit(0x08,sf);
|
||||
if (version != 2 && version != 3 && version != 4)
|
||||
goto fail;
|
||||
|
||||
tables_offset = read_16bit(0x0e,streamFile); /* usually 0x30 or 0x20 */
|
||||
/* SSCF version? (older SSCFs from Crisis Core/FFXI X360 seem to be V3/2) */
|
||||
if (read_u8(0x0d,sf) != 0x04)
|
||||
goto fail;
|
||||
|
||||
tables_offset = read_16bit(0x0e,sf); /* usually 0x30 or 0x20 */
|
||||
|
||||
#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))
|
||||
/* FFXIII music_68tak.ps3.scd is 0x80 shorter? */
|
||||
if (read_32bit(size_offset,sf) != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
@ -80,8 +80,8 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
/* find meta_offset in table3 (headers) and total subsongs */
|
||||
{
|
||||
int i;
|
||||
int headers_entries = read_16bit(tables_offset+0x04,streamFile);
|
||||
off_t headers_offset = read_32bit(tables_offset+0x0c,streamFile);
|
||||
int headers_entries = read_16bit(tables_offset+0x04,sf);
|
||||
off_t headers_offset = read_32bit(tables_offset+0x0c,sf);
|
||||
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
total_subsongs = 0;
|
||||
@ -89,9 +89,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
/* manually find subsongs as entries can be dummy (ex. sfx banks in FF XIV or FF Type-0) */
|
||||
for (i = 0; i < headers_entries; i++) {
|
||||
off_t entry_offset = read_32bit(headers_offset + i*0x04,streamFile);
|
||||
off_t entry_offset = read_32bit(headers_offset + i*0x04,sf);
|
||||
|
||||
if (read_32bit(entry_offset+0x0c,streamFile) == -1)
|
||||
if (read_32bit(entry_offset+0x0c,sf) == -1)
|
||||
continue; /* codec -1 when dummy */
|
||||
|
||||
total_subsongs++;
|
||||
@ -105,15 +105,15 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
/** stream header **/
|
||||
stream_size = read_32bit(meta_offset+0x00,streamFile);
|
||||
channel_count = read_32bit(meta_offset+0x04,streamFile);
|
||||
sample_rate = read_32bit(meta_offset+0x08,streamFile);
|
||||
codec = read_32bit(meta_offset+0x0c,streamFile);
|
||||
stream_size = read_32bit(meta_offset+0x00,sf);
|
||||
channels = read_32bit(meta_offset+0x04,sf);
|
||||
sample_rate = read_32bit(meta_offset+0x08,sf);
|
||||
codec = read_32bit(meta_offset+0x0c,sf);
|
||||
|
||||
loop_start = read_32bit(meta_offset+0x10,streamFile);
|
||||
loop_end = read_32bit(meta_offset+0x14,streamFile);
|
||||
extradata_size = read_32bit(meta_offset+0x18,streamFile);
|
||||
aux_chunk_count = read_32bit(meta_offset+0x1c,streamFile);
|
||||
loop_start = read_32bit(meta_offset+0x10,sf);
|
||||
loop_end = read_32bit(meta_offset+0x14,sf);
|
||||
extradata_size = read_32bit(meta_offset+0x18,sf);
|
||||
aux_chunk_count = read_32bit(meta_offset+0x1c,sf);
|
||||
/* 0x01e(2): unknown, seen in some FF XIV sfx (MSADPCM) */
|
||||
|
||||
loop_flag = (loop_end > 0);
|
||||
@ -127,19 +127,19 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
/* skips aux chunks, sometimes needed (Lightning Returns X360, FF XIV PC) */
|
||||
if (aux_chunk_count && read_32bitBE(extradata_offset, streamFile) == 0x4D41524B) { /* "MARK" */
|
||||
extradata_offset += read_32bit(extradata_offset+0x04, streamFile);
|
||||
if (aux_chunk_count && is_id32be(extradata_offset, sf, "MARK")) {
|
||||
extradata_offset += read_32bit(extradata_offset+0x04, sf);
|
||||
}
|
||||
|
||||
/* find name if possible */
|
||||
if (version == 4) {
|
||||
int info_entries = read_16bit(tables_offset+0x00,streamFile);
|
||||
int headers_entries = read_16bit(tables_offset+0x04,streamFile);
|
||||
int info_entries = read_16bit(tables_offset+0x00,sf);
|
||||
int headers_entries = read_16bit(tables_offset+0x04,sf);
|
||||
off_t info_offset = tables_offset+0x20;
|
||||
|
||||
/* not very exact as table1 and table3 entries may differ in V3, not sure about V4 */
|
||||
if (info_entries == headers_entries) {
|
||||
off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,streamFile);
|
||||
off_t entry_offset = read_16bit(info_offset + 0x04*target_entry,sf);
|
||||
name_offset = entry_offset+0x30;
|
||||
}
|
||||
}
|
||||
@ -157,17 +157,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
ovmi.disable_reordering = 1; /* already ordered */
|
||||
/* loop values are in bytes, let init_vgmstream_ogg_vorbis find loop comments instead */
|
||||
|
||||
ogg_version = read_8bit(extradata_offset + 0x00, streamFile);
|
||||
ogg_version = read_u8(extradata_offset + 0x00, sf);
|
||||
/* 0x01(1): 0x20 in v2/3, this ogg miniheader size? */
|
||||
ogg_byte = read_8bit(extradata_offset + 0x02, streamFile);
|
||||
ogg_byte = read_u8(extradata_offset + 0x02, sf);
|
||||
/* 0x03(1): ? in v3 */
|
||||
|
||||
if (ogg_version == 0) { /* 0x10? header, then custom Vorbis header before regular Ogg (FF XIV PC v1) */
|
||||
ovmi.stream_size = stream_size;
|
||||
}
|
||||
else { /* 0x20 header, then seek table */
|
||||
size_t seek_table_size = read_32bit(extradata_offset+0x10, streamFile);
|
||||
size_t vorb_header_size = read_32bit(extradata_offset+0x14, streamFile);
|
||||
size_t seek_table_size = read_32bit(extradata_offset+0x10, sf);
|
||||
size_t vorb_header_size = read_32bit(extradata_offset+0x14, sf);
|
||||
/* 0x18(4): ? (can be 0) */
|
||||
|
||||
if ((extradata_offset-meta_offset) + seek_table_size + vorb_header_size != extradata_size)
|
||||
@ -192,16 +192,16 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
/* actual Ogg init */
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(streamFile, NULL, start_offset, &ovmi);
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis_callbacks(sf, NULL, start_offset, &ovmi);
|
||||
if (ogg_vgmstream && name_offset)
|
||||
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
|
||||
read_string(ogg_vgmstream->stream_name, PATH_LIMIT, name_offset, sf);
|
||||
return ogg_vgmstream;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
@ -209,7 +209,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->stream_size = stream_size;
|
||||
vgmstream->meta_type = meta_SQEX_SCD;
|
||||
if (name_offset)
|
||||
read_string(vgmstream->stream_name, PATH_LIMIT, name_offset, streamFile);
|
||||
read_string(vgmstream->stream_name, STREAM_NAME_SIZE, name_offset, sf);
|
||||
|
||||
switch (codec) {
|
||||
case 0x01: /* PCM */
|
||||
@ -217,10 +217,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
|
||||
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16);
|
||||
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channels, 16);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channel_count, 16);
|
||||
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channel_count, 16);
|
||||
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start, channels, 16);
|
||||
vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end, channels, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -229,10 +229,10 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x10;
|
||||
|
||||
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channel_count);
|
||||
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channel_count);
|
||||
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels);
|
||||
vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channels);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -246,7 +246,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
cfg.interleave = 0x800; /* for multistream [Final Fantasy XIII-2 (PS3)], otherwise ignored */
|
||||
cfg.data_size = stream_size;
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
|
||||
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_SCD, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
@ -268,9 +268,9 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
case 0x0C: /* MS ADPCM [Final Fantasy XIV (PC) sfx] */
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, streamFile);
|
||||
vgmstream->frame_size = read_16bit(extradata_offset + 0x0c, sf);
|
||||
/* WAVEFORMATEX in extradata_offset */
|
||||
if (!msadpcm_check_coefs(streamFile, extradata_offset + 0x14))
|
||||
if (!msadpcm_check_coefs(sf, extradata_offset + 0x14))
|
||||
goto fail;
|
||||
|
||||
vgmstream->num_samples = msadpcm_bytes_to_samples(stream_size, vgmstream->frame_size, vgmstream->channels);
|
||||
@ -282,83 +282,53 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */
|
||||
case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */
|
||||
const off_t interleave_size = 0x800;
|
||||
const off_t stride_size = interleave_size * channel_count;
|
||||
int i;
|
||||
size_t total_size;
|
||||
layered_layout_data * data = NULL;
|
||||
|
||||
/* interleaved DSPs including the header (so the first 0x800 is 0x60 header + 0x740 data)
|
||||
* so interleave layout can't used; we'll setup de-interleaving streamfiles as layers/channels instead */
|
||||
//todo this could be simplified using a block layout or adding interleave_first_block
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x800;
|
||||
vgmstream->interleave_first_skip = 0x60;
|
||||
vgmstream->interleave_first_block_size = vgmstream->interleave_block_size - vgmstream->interleave_first_skip;
|
||||
|
||||
/* read from the first DSP header and verify other channel headers */
|
||||
{
|
||||
total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; /* rounded nibbles / 2 */
|
||||
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end + 1;
|
||||
}
|
||||
/* standard dsp header at start_offset */
|
||||
dsp_read_coefs_be(vgmstream, sf, start_offset+0x1c, vgmstream->interleave_block_size);
|
||||
dsp_read_hist_be(vgmstream, sf, start_offset+0x40, vgmstream->interleave_block_size);
|
||||
|
||||
for (i = 1; i < channel_count; i++) {
|
||||
if ((read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size ||
|
||||
read_32bitBE(start_offset+interleave_size*i+0x00,streamFile) != vgmstream->num_samples) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
vgmstream->num_samples = read_32bit(start_offset+0x00,sf);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end + 1;
|
||||
}
|
||||
|
||||
/* init layout */
|
||||
data = init_layout_layered(channel_count);
|
||||
if (!data) goto fail;
|
||||
vgmstream->layout_data = data;
|
||||
|
||||
/* open each layer subfile */
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
STREAMFILE* temp_streamFile = setup_scd_dsp_streamfile(streamFile, start_offset+interleave_size*i, interleave_size, stride_size, total_size);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
data->layers[i] = init_vgmstream_ngc_dsp_std(temp_streamFile);
|
||||
close_streamfile(temp_streamFile);
|
||||
if (!data->layers[i]) goto fail;
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
if (!setup_layout_layered(data))
|
||||
goto fail;
|
||||
|
||||
|
||||
start_offset += vgmstream->interleave_first_skip;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x0B: { /* XMA2 [Final Fantasy (X360), Lightning Returns (X360) sfx, Kingdom Hearts 2.8 (X1)] */
|
||||
ffmpeg_codec_data *ffmpeg_data = NULL;
|
||||
uint8_t buf[200];
|
||||
uint8_t buf[0x100];
|
||||
int32_t bytes;
|
||||
|
||||
/* extradata_offset+0x00: fmt0x166 header (BE), extradata_offset+0x34: seek table */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,200, extradata_offset,0x34, stream_size, streamFile, 1);
|
||||
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
|
||||
if (!ffmpeg_data) goto fail;
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
/* extradata:
|
||||
* 0x00: fmt0x166 header (BE X360, LE XBone)
|
||||
* 0x34: seek table */
|
||||
bytes = ffmpeg_make_riff_xma_from_fmt_chunk(buf,0x100, extradata_offset,0x34, stream_size, sf, big_endian);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, start_offset, stream_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = ffmpeg_data->totalSamples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end; //todo +1?
|
||||
xma2_parse_fmt_chunk_extra(sf, extradata_offset, NULL, &vgmstream->num_samples, NULL, NULL, big_endian);
|
||||
vgmstream->loop_start_sample = loop_start; /* same loops in chunk */
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
xma_fix_raw_samples(vgmstream, streamFile, start_offset,stream_size, 0, 0,0); /* samples are ok, loops? */
|
||||
xma_fix_raw_samples(vgmstream, sf, start_offset, stream_size, extradata_offset, 1,1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x0E: { /* ATRAC3/ATRAC3plus [Lord of Arcana (PSP), Final Fantasy Type-0] */
|
||||
int fact_samples = 0;
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_atrac3_riff(streamFile, start_offset, &fact_samples);
|
||||
vgmstream->codec_data = init_ffmpeg_atrac3_riff(sf, start_offset, &fact_samples);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
@ -377,17 +347,17 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
/* post header has various typical ATRAC9 values */
|
||||
cfg.channels = vgmstream->channels;
|
||||
cfg.config_data = read_32bit(extradata_offset+0x0c,streamFile);
|
||||
cfg.encoder_delay = read_32bit(extradata_offset+0x18,streamFile);
|
||||
cfg.config_data = read_32bit(extradata_offset+0x0c,sf);
|
||||
cfg.encoder_delay = read_32bit(extradata_offset+0x18,sf);
|
||||
|
||||
vgmstream->codec_data = init_atrac9(&cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_ATRAC9;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
vgmstream->num_samples = read_32bit(extradata_offset+0x10,streamFile); /* loop values above are also weird and ignored */
|
||||
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, streamFile) + 1;
|
||||
vgmstream->num_samples = read_32bit(extradata_offset+0x10,sf); /* loop values above are also weird and ignored */
|
||||
vgmstream->loop_start_sample = read_32bit(extradata_offset+0x20, sf);
|
||||
vgmstream->loop_end_sample = read_32bit(extradata_offset+0x24, sf) + 1;
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample -= cfg.encoder_delay;
|
||||
vgmstream->loop_end_sample -= cfg.encoder_delay;
|
||||
@ -403,7 +373,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
@ -415,7 +385,7 @@ fail:
|
||||
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||
static void scd_ogg_v2_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) {
|
||||
uint8_t *ptr8 = ptr;
|
||||
size_t bytes_read = size * nmemb;
|
||||
ogg_vorbis_io *io = datasource;
|
||||
@ -438,7 +408,7 @@ static void scd_ogg_v2_decryption_callback(void *ptr, size_t size, size_t nmemb,
|
||||
}
|
||||
}
|
||||
|
||||
static void scd_ogg_v3_decryption_callback(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||
static void scd_ogg_v3_decryption_callback(void* ptr, size_t size, size_t nmemb, void* datasource) {
|
||||
/* V3 decryption table found in the .exe of FF XIV Heavensward */
|
||||
static const uint8_t scd_ogg_v3_lookuptable[256] = {
|
||||
0x3A, 0x32, 0x32, 0x32, 0x03, 0x7E, 0x12, 0xF7, 0xB2, 0xE2, 0xA2, 0x67, 0x32, 0x32, 0x22, 0x32, // 00-0F
|
||||
|
@ -1,92 +0,0 @@
|
||||
#ifndef _SQEX_SCD_STREAMFILE_H_
|
||||
#define _SQEX_SCD_STREAMFILE_H_
|
||||
#include "../streamfile.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
off_t start_physical_offset; /* interleaved data start, for this substream */
|
||||
size_t interleave_block_size; /* max size that can be read before encountering other substreams */
|
||||
size_t stride_size; /* step size between interleave blocks (interleave*channels) */
|
||||
size_t total_size; /* final size of the deinterleaved substream */
|
||||
} scd_dsp_io_data;
|
||||
|
||||
|
||||
/* Handles deinterleaving of complete files, skipping portions or other substreams. */
|
||||
static size_t scd_dsp_io_read(STREAMFILE *streamfile, uint8_t *dest, off_t offset, size_t length, scd_dsp_io_data* data) {
|
||||
size_t total_read = 0;
|
||||
|
||||
while (length > 0) {
|
||||
size_t to_read;
|
||||
size_t length_available;
|
||||
off_t block_num;
|
||||
off_t intrablock_offset;
|
||||
off_t physical_offset;
|
||||
|
||||
block_num = offset / data->interleave_block_size;
|
||||
intrablock_offset = offset % data->interleave_block_size;
|
||||
physical_offset = data->start_physical_offset + block_num*data->stride_size + intrablock_offset;
|
||||
length_available = data->interleave_block_size - intrablock_offset;
|
||||
|
||||
if (length < length_available) {
|
||||
to_read = length;
|
||||
}
|
||||
else {
|
||||
to_read = length_available;
|
||||
}
|
||||
|
||||
if (to_read > 0) {
|
||||
size_t bytes_read;
|
||||
|
||||
bytes_read = read_streamfile(dest, physical_offset, to_read, streamfile);
|
||||
total_read += bytes_read;
|
||||
|
||||
if (bytes_read != to_read) {
|
||||
return total_read;
|
||||
}
|
||||
|
||||
dest += bytes_read;
|
||||
offset += bytes_read;
|
||||
length -= bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
return total_read;
|
||||
}
|
||||
|
||||
static size_t scd_dsp_io_size(STREAMFILE *streamfile, scd_dsp_io_data* data) {
|
||||
return data->total_size;
|
||||
}
|
||||
|
||||
|
||||
static STREAMFILE* setup_scd_dsp_streamfile(STREAMFILE *streamFile, off_t start_offset, size_t interleave_block_size, size_t stride_size, size_t total_size) {
|
||||
STREAMFILE *temp_streamFile = NULL, *new_streamFile = NULL;
|
||||
scd_dsp_io_data io_data = {0};
|
||||
size_t io_data_size = sizeof(scd_dsp_io_data);
|
||||
|
||||
io_data.start_physical_offset = start_offset;
|
||||
io_data.interleave_block_size = interleave_block_size;
|
||||
io_data.stride_size = stride_size;
|
||||
io_data.total_size = total_size;
|
||||
|
||||
|
||||
/* setup subfile */
|
||||
new_streamFile = open_wrap_streamfile(streamFile);
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
new_streamFile = open_io_streamfile(temp_streamFile, &io_data,io_data_size, scd_dsp_io_read,scd_dsp_io_size);
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
new_streamFile = open_fakename_streamfile(temp_streamFile, NULL,"dsp");
|
||||
if (!new_streamFile) goto fail;
|
||||
temp_streamFile = new_streamFile;
|
||||
|
||||
return temp_streamFile;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* _SCD_STREAMFILE_H_ */
|
Loading…
x
Reference in New Issue
Block a user