EA SCHl: Implemented looping for streamed sounds in ABK

This commit is contained in:
NicknineTheEagle 2019-01-16 23:05:09 +03:00
parent c6280d85b3
commit 3f0ba31a43

View File

@ -187,15 +187,16 @@ fail:
/* streamed assets are stored externally in AST file (mostly seen in earlier 6th-gen games) */ /* streamed assets are stored externally in AST file (mostly seen in earlier 6th-gen games) */
VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
int bnk_target_stream, is_dupe, total_sounds = 0, target_stream = streamFile->stream_index; int bnk_target_stream, is_dupe, total_sounds = 0, target_stream = streamFile->stream_index;
off_t bnk_offset, header_table_offset, base_offset, value_offset, table_offset, entry_offset, target_entry_offset, schl_offset; off_t bnk_offset, header_table_offset, base_offset, value_offset, table_offset, entry_offset, target_entry_offset, schl_offset, schl_loop_offset;
uint32_t i, j, k, num_sounds, total_sound_tables; uint32_t i, j, k, num_sounds, total_sound_tables;
uint16_t num_tables; uint16_t num_tables;
uint8_t sound_type, num_entries; uint8_t sound_type, num_entries;
off_t sound_table_offsets[0x2000]; off_t sound_table_offsets[0x2000];
STREAMFILE * astData = NULL; STREAMFILE * astData = NULL;
VGMSTREAM * vgmstream; VGMSTREAM * vgmstream = NULL;
int32_t (*read_32bit)(off_t,STREAMFILE*); segmented_layout_data *data_s = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*); int32_t(*read_32bit)(off_t, STREAMFILE*);
int16_t(*read_16bit)(off_t, STREAMFILE*);
/* check extension */ /* check extension */
if (!check_extensions(streamFile, "abk")) if (!check_extensions(streamFile, "abk"))
@ -205,7 +206,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
goto fail; goto fail;
/* use table offset to check endianness */ /* use table offset to check endianness */
if (guess_endianness32bit(0x1C,streamFile)) { if (guess_endianness32bit(0x1C, streamFile)) {
read_32bit = read_32bitBE; read_32bit = read_32bitBE;
read_16bit = read_16bitBE; read_16bit = read_16bitBE;
} else { } else {
@ -240,10 +241,8 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
/* For some reason, there are duplicate entries pointing at the same sound tables */ /* For some reason, there are duplicate entries pointing at the same sound tables */
is_dupe = 0; is_dupe = 0;
for (k = 0; k < total_sound_tables; k++) for (k = 0; k < total_sound_tables; k++) {
{ if (table_offset == sound_table_offsets[k]) {
if (table_offset==sound_table_offsets[k])
{
is_dupe = 1; is_dupe = 1;
break; break;
} }
@ -278,45 +277,85 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
if (target_entry_offset == 0) if (target_entry_offset == 0)
goto fail; goto fail;
/* 0x00: type (0x00 - normal, 0x01 - streamed, 0x02 - streamed and prefetched(?) */ /* 0x00: type (0x00 - normal, 0x01 - streamed, 0x02 - streamed looped */
/* 0x01: ??? */ /* 0x01: ??? */
/* 0x04: index for normal sounds, offset for streamed sounds */ /* 0x04: index for normal sounds, offset for streamed sounds */
/* 0x08: offset for prefetched sounds */ /* 0x08: loop offset for streamed sounds */
sound_type = read_8bit(target_entry_offset + 0x00, streamFile); sound_type = read_8bit(target_entry_offset + 0x00, streamFile);
switch (sound_type) { switch (sound_type) {
case 0x00: case 0x00:
if (!bnk_offset) if (!bnk_offset)
goto fail; goto fail;
bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1; bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1;
vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, 1); vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, 1);
if (!vgmstream) if (!vgmstream)
goto fail; goto fail;
break;
case 0x01: break;
case 0x02:
astData = open_streamfile_by_ext(streamFile, "ast"); case 0x01:
if (!astData) astData = open_streamfile_by_ext(streamFile, "ast");
goto fail; if (!astData)
goto fail;
if (sound_type == 0x01)
schl_offset = read_32bit(target_entry_offset + 0x04, streamFile); schl_offset = read_32bit(target_entry_offset + 0x04, streamFile);
else if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER)
schl_offset = read_32bit(target_entry_offset + 0x08, streamFile); goto fail;
if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER) vgmstream = parse_schl_block(astData, schl_offset, 0);
if (!vgmstream)
goto fail;
break;
case 0x02:
astData = open_streamfile_by_ext(streamFile, "ast");
if (!astData)
goto fail;
/* looped sounds basically consist of two independent segments
* the first one is loop start, the second one is loop body */
schl_offset = read_32bit(target_entry_offset + 0x04, streamFile);
schl_loop_offset = read_32bit(target_entry_offset + 0x08, streamFile);
if (read_32bitBE(schl_offset, astData) != EA_BLOCKID_HEADER ||
read_32bitBE(schl_loop_offset, astData) != EA_BLOCKID_HEADER)
goto fail;
/* init layout */
data_s = init_layout_segmented(2);
if (!data_s) goto fail;
/* load intro and loop segments */
data_s->segments[0] = parse_schl_block(astData, schl_offset, 0);
if (!data_s->segments[0]) goto fail;
data_s->segments[1] = parse_schl_block(astData, schl_loop_offset, 0);
if (!data_s->segments[1]) goto fail;
/* setup segmented VGMSTREAMs */
if (!setup_layout_segmented(data_s))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(data_s->segments[0]->channels, 1);
if (!vgmstream) goto fail;
vgmstream->sample_rate = data_s->segments[0]->sample_rate;
vgmstream->num_samples = data_s->segments[0]->num_samples + data_s->segments[1]->num_samples;
vgmstream->loop_start_sample = data_s->segments[0]->num_samples;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->meta_type = meta_EA_SCHL;
vgmstream->coding_type = data_s->segments[0]->coding_type;
vgmstream->layout_type = layout_segmented;
vgmstream->layout_data = data_s;
break;
default:
goto fail; goto fail;
break;
vgmstream = parse_schl_block(astData, schl_offset, 0);
if (!vgmstream)
goto fail;
break;
default:
goto fail;
break;
} }
vgmstream->num_streams = total_sounds; vgmstream->num_streams = total_sounds;
@ -325,6 +364,7 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
fail: fail:
close_streamfile(astData); close_streamfile(astData);
free_layout_segmented(data_s);
return NULL; return NULL;
} }
@ -344,7 +384,7 @@ VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE *streamFile) {
/* 0x05: number of files */ /* 0x05: number of files */
/* 0x06: ??? */ /* 0x06: ??? */
/* 0x07: offset multiplier flag */ /* 0x07: offset multiplier flag */
/* 0x08: combined size of all sounds without padding divided by 0x0100 */ /* 0x08: combined size of all sounds without padding divided by offset mult */
/* 0x0C: table start */ /* 0x0C: table start */
/* no nice way to validate these so we do what we can */ /* no nice way to validate these so we do what we can */
@ -460,7 +500,7 @@ VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) {
} }
/* /*
* 0x04: ??? * 0x04: version
* 0x05: intro segment * 0x05: intro segment
* 0x06: number of segments * 0x06: number of segments
* 0x07: userdata entry size (incorrect?) * 0x07: userdata entry size (incorrect?)