mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 07:44:43 +01:00
Fix AKB2 subsongs [Mobius Final Fantasy (PC)]
This commit is contained in:
parent
eb4168f9b9
commit
8534006035
106
src/meta/akb.c
106
src/meta/akb.c
@ -3,7 +3,7 @@
|
||||
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
/* AKB (AAC only) - found in SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
|
||||
size_t filesize;
|
||||
@ -34,7 +34,7 @@ fail:
|
||||
|
||||
|
||||
/* AKB - found in SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, extra_data_offset = 0;
|
||||
size_t file_size, header_size, extra_header_size = 0, extra_data_size = 0;
|
||||
@ -113,7 +113,7 @@ VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile) {
|
||||
}
|
||||
|
||||
case 0x06: { /* aac [The World Ends with You (iPad)] */
|
||||
/* init_vgmstream_akb above has priority, but this works fine too */
|
||||
/* init_vgmstream_akb_mp4 above has priority, but this works fine too */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,file_size-start_offset);
|
||||
@ -149,80 +149,108 @@ fail:
|
||||
|
||||
|
||||
/* AKB2 - found in later SQEX iOS games */
|
||||
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, header_offset;
|
||||
size_t datasize;
|
||||
int loop_flag = 0, channel_count, codec;
|
||||
int akb_header_size, sound_index = 0, sound_offset_data, sound, sound_header_size, material_offset_data, material_index = 0, material, extradata, encryption_flag;
|
||||
off_t start_offset, material_offset, extradata_offset;
|
||||
size_t material_size, extradata_size, stream_size;
|
||||
int loop_flag = 0, channel_count, encryption_flag, codec, sample_rate, num_samples, loop_start, loop_end;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
|
||||
/* check extensions */
|
||||
/* .akb.bytes is the usual extension in later games */
|
||||
if ( !check_extensions(streamFile, "akb") )
|
||||
if ( !check_extensions(streamFile, "akb,bytes") )
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
/* checks */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x414B4232) /* "AKB2" */
|
||||
goto fail;
|
||||
if (read_32bitLE(0x08,streamFile) != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
akb_header_size = read_16bitLE(0x06, streamFile);
|
||||
sound_offset_data = akb_header_size + sound_index * 0x10;
|
||||
sound = read_32bitLE(sound_offset_data + 0x04, streamFile);
|
||||
sound_header_size = read_16bitLE(sound + 0x02, streamFile);
|
||||
material_offset_data = sound + sound_header_size + material_index * 0x10;
|
||||
material = sound + read_32bitLE(material_offset_data + 0x04, streamFile);
|
||||
encryption_flag = read_8bit(material + 0x03, streamFile) & 0x08;
|
||||
extradata = material + read_16bitLE(material + 0x04, streamFile);
|
||||
/* parse tables */
|
||||
{
|
||||
off_t table_offset;
|
||||
size_t table_size, entry_size;
|
||||
off_t akb_header_size = read_16bitLE(0x06, streamFile);
|
||||
int table_count = read_8bit(0x0c, streamFile);
|
||||
|
||||
start_offset = material + read_16bitLE(material + 0x04, streamFile) + read_32bitLE(material + 0x18, streamFile);
|
||||
header_offset = material;
|
||||
/* probably each table has its type somewhere, but only seen last table = sound table */
|
||||
if (table_count > 2) /* 2 only seen in some Mobius FF sound banks */
|
||||
goto fail;
|
||||
entry_size = 0x10; /* technically every entry/table has its own size but to simplify... */
|
||||
|
||||
table_offset = read_32bitLE(akb_header_size + (table_count-1)*entry_size + 0x04, streamFile);
|
||||
table_size = read_16bitLE(table_offset + 0x02, streamFile);
|
||||
|
||||
total_subsongs = read_8bit(table_offset + 0x0f, streamFile); /* can contain 0 entries too */
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
|
||||
|
||||
material_offset = table_offset + read_32bitLE(table_offset + table_size + (target_subsong-1)*entry_size + 0x04, streamFile);
|
||||
}
|
||||
|
||||
/** stream header **/
|
||||
/* 0x00: 0? */
|
||||
codec = read_8bit(material_offset+0x01,streamFile);
|
||||
channel_count = read_8bit(material_offset+0x02,streamFile);
|
||||
encryption_flag = read_8bit(material_offset+0x03,streamFile);
|
||||
material_size = read_16bitLE(material_offset+0x04,streamFile);
|
||||
sample_rate = (uint16_t)read_16bitLE(material_offset+0x06,streamFile);
|
||||
stream_size = read_32bitLE(material_offset+0x08,streamFile);
|
||||
num_samples = read_32bitLE(material_offset+0x0c,streamFile);
|
||||
|
||||
loop_start = read_32bitLE(material_offset+0x10,streamFile);
|
||||
loop_end = read_32bitLE(material_offset+0x14,streamFile);
|
||||
extradata_size = read_32bitLE(material_offset+0x18,streamFile);
|
||||
/* rest: ? (empty or 0x3f80) */
|
||||
|
||||
loop_flag = (loop_end > 0);
|
||||
extradata_offset = material_offset + material_size;
|
||||
start_offset = material_offset + material_size + extradata_size;
|
||||
|
||||
channel_count = read_8bit(header_offset+0x02,streamFile);
|
||||
loop_flag = read_32bitLE(header_offset+0x14,streamFile) > 0; /* loop end */
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* 0x04: version? 0x08: filesize, 0x28: file_id?, others: no idea */
|
||||
codec = read_8bit(header_offset+0x01,streamFile);
|
||||
datasize = read_32bitLE(header_offset+0x08,streamFile);
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(header_offset+0x06,streamFile);
|
||||
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
|
||||
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
|
||||
vgmstream->num_samples = read_32bitLE(header_offset+0x0c,streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(header_offset+0x10,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(header_offset+0x14,streamFile);
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
vgmstream->stream_size = stream_size;
|
||||
|
||||
vgmstream->meta_type = meta_AKB;
|
||||
|
||||
switch (codec) {
|
||||
case 0x02: { /* MSAPDCM [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
if (encryption_flag) goto fail;
|
||||
case 0x02: { /* MSADPCM [The Irregular at Magic High School Lost Zero (Android)] */
|
||||
if (encryption_flag & 0x08) goto fail;
|
||||
vgmstream->coding_type = coding_MSADPCM;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata + 0x02, streamFile);
|
||||
vgmstream->interleave_block_size = read_16bitLE(extradata_offset + 0x02, streamFile);
|
||||
|
||||
/* adjusted samples; bigger or smaller than base samples, but seems more accurate
|
||||
* (base samples may have more than possible and read over file size otherwise, very strange)
|
||||
* loop_end seems to exist even with loop disabled */
|
||||
vgmstream->num_samples = read_32bitLE(extradata + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata + 0x0c, streamFile);
|
||||
vgmstream->num_samples = read_32bitLE(extradata_offset + 0x04, streamFile);
|
||||
vgmstream->loop_start_sample = read_32bitLE(extradata_offset + 0x08, streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitLE(extradata_offset + 0x0c, streamFile);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 0x05: { /* ogg vorbis [The World Ends with You (iPhone / latest update)] */
|
||||
case 0x05: { /* Ogg Vorbis [The World Ends with You (iOS / latest update)] */
|
||||
ffmpeg_codec_data *ffmpeg_data;
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,datasize);
|
||||
ffmpeg_data = init_ffmpeg_offset(streamFile, start_offset,stream_size);
|
||||
if ( !ffmpeg_data ) goto fail;
|
||||
|
||||
vgmstream->codec_data = ffmpeg_data;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
/* When loop_flag num_samples may be much larger than real num_samples (it's fine when looping is off)
|
||||
* Actual num_samples would be loop_end_sample+1, but more testing is needed */
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
@ -125,7 +125,7 @@ VGMSTREAM * init_vgmstream_mp4_aac_ffmpeg(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile);
|
||||
VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
|
||||
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb_mp4(STREAMFILE *streamFile);
|
||||
#endif
|
||||
|
||||
VGMSTREAM * init_vgmstream_sfl(STREAMFILE * streamFile);
|
||||
@ -622,8 +622,8 @@ VGMSTREAM * init_vgmstream_x360_cxs(STREAMFILE* streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_akb_multi(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb2_multi(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_x360_ast(STREAMFILE *streamFile);
|
||||
|
||||
|
@ -69,7 +69,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_mp4_aac,
|
||||
#endif
|
||||
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
|
||||
init_vgmstream_akb,
|
||||
init_vgmstream_akb_mp4,
|
||||
#endif
|
||||
init_vgmstream_sadb,
|
||||
init_vgmstream_ps2_bmdx,
|
||||
@ -330,8 +330,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ps2_vds_vdm,
|
||||
init_vgmstream_x360_cxs,
|
||||
init_vgmstream_dsp_adx,
|
||||
init_vgmstream_akb_multi,
|
||||
init_vgmstream_akb2_multi,
|
||||
init_vgmstream_akb,
|
||||
init_vgmstream_akb2,
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
init_vgmstream_mp4_aac_ffmpeg,
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user