EA SCHl: Added MPF/MUS format

This commit is contained in:
NicknineTheEagle 2018-12-27 20:01:36 +03:00
parent 39b5480ca6
commit 808188dbcd
4 changed files with 90 additions and 0 deletions

View File

@ -239,6 +239,7 @@ static const char* extension_list[] = {
//"mpc", //common
"mpdsp",
"mpds",
"mpf",
"mps", //txth/reserved [Scandal (PS2)]
"ms",
"msa",

View File

@ -351,6 +351,93 @@ fail:
return NULL;
}
/* EA MPF/MUS combo - used in newer 6th gen games for storing music */
VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
off_t section_offset, entry_offset, subentry_num, eof_offset, schl_offset;
uint16_t sec1_num;
uint8_t version, sub_version, sec2_num;
int32_t(*read_32bit)(off_t, STREAMFILE*);
int16_t(*read_16bit)(off_t, STREAMFILE*);
STREAMFILE *musFile = NULL;
VGMSTREAM *vgmstream = NULL;
int target_stream = streamFile->stream_index, total_streams;
/* check extension */
if (!check_extensions(streamFile, "mpf"))
goto fail;
/* detect endianness */
if (read_32bitBE(0x00, streamFile) == 0x50464478) { /* "PFDx" */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else if (read_32bitBE(0x00, streamFile) == 0x78444650) { /* "xDFP" */
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
} else {
goto fail;
}
musFile = open_streamfile_by_ext(streamFile, "mus");
if (!musFile) goto fail;
version = read_8bit(0x04, streamFile);
sub_version = read_8bit(0x05, streamFile);
if (version < 0x04 || version > 0x05) goto fail;
if (version == 0x05 && sub_version > 0x02) goto fail; /* newer version using SNR/SNS */
if (version == 0x04) {
/* we need to go through the first two sections to find sound table */
sec1_num = read_16bit(0x12, streamFile);
sec2_num = read_8bit(0x0f, streamFile);
/* get the last entry offset */
section_offset = 0x20;
entry_offset = read_16bit(section_offset + (sec1_num - 1) * 0x02, streamFile) * 0x04;
/* HACK: there's some weird bitstream here that's store differently in LE and BE */
/* I can't figure it out, so let's just use a workaround for now */
if (read_32bitBE(0x00, streamFile) == 0x50464478) {
subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 15) & 0xFF;
} else {
subentry_num = (read_32bitBE(entry_offset + 0x04, streamFile) >> 20) & 0xFF;
}
section_offset = entry_offset + 0x10 + subentry_num * 0x04;
entry_offset = read_16bit(section_offset + (sec2_num - 1) * 0x02, streamFile) * 0x04;
subentry_num = read_16bit(entry_offset + 0x0e, streamFile);
section_offset = entry_offset + 0x10 + subentry_num * 0x10;
entry_offset = read_32bit(section_offset, streamFile) * 0x04;
section_offset = read_32bit(entry_offset + 0x00, streamFile) * 0x04;
eof_offset = read_32bit(entry_offset + 0x04, streamFile) * 0x04;
total_streams = (eof_offset - section_offset) / 0x08;
} else if (version == 0x05) {
section_offset = read_32bit(0x34, streamFile);
eof_offset = read_32bit(0x38, streamFile);
total_streams = (eof_offset - section_offset) / 0x08;
}
if (target_stream == 0) target_stream = 1;
if (target_stream < 0 || total_streams == 0 || target_stream > total_streams)
goto fail;
schl_offset = read_32bit(section_offset + (target_stream - 1) * 0x08 + 0x00, streamFile) * 0x80;
if (read_32bitBE(schl_offset, musFile) != EA_BLOCKID_HEADER)
goto fail;
vgmstream = parse_schl_block(musFile, schl_offset, total_streams);
if (!vgmstream)
goto fail;
close_streamfile(musFile);
return vgmstream;
fail:
close_streamfile(musFile);
return NULL;
}
/* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */
static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams) {
off_t start_offset, header_offset;

View File

@ -645,6 +645,7 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_hdr_dat(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE * steeamFile);
VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile);

View File

@ -352,6 +352,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ea_bnk,
init_vgmstream_ea_abk,
init_vgmstream_ea_hdr_dat,
init_vgmstream_ea_mpf_mus,
init_vgmstream_ea_schl_fixed,
init_vgmstream_sk_aud,
init_vgmstream_stm,