Fix EA SCHl BR and handle multilang better [Battlefield: Hardline (PS3)]

This commit is contained in:
bnnm 2019-03-09 23:51:56 +01:00
parent b4fff010dd
commit 0719c2cc61
2 changed files with 49 additions and 59 deletions

View File

@ -10,6 +10,10 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
size_t block_size, block_samples;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
uint32_t flag_lang = (vgmstream->codec_config >> 16) & 0xFFFF;
int flag_be = (vgmstream->codec_config & 0x02);
int flag_adpcm = (vgmstream->codec_config & 0x01);
/* EOF reads: signal we have nothing and let the layout fail */
if (block_offset >= get_streamfile_size(streamFile)) {
@ -23,35 +27,21 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
{
uint32_t block_id = read_32bitBE(block_offset+0x00,streamFile);
if (vgmstream->codec_config & 0x02) /* size is always LE, except in early SS/MAC */
if (flag_be) /* size is always LE, except in early SS/MAC */
block_size = read_32bitBE(block_offset + 0x04,streamFile);
else
block_size = read_32bitLE(block_offset + 0x04,streamFile);
switch(block_id) {
case 0x5343446C: /* "SCDl" */
case 0x5344454E: /* "SDEN" */
case 0x53444652: /* "SDFR" */
case 0x53444745: /* "SDGE" */
case 0x53444445: /* "SDDE" */
case 0x53444954: /* "SDIT" */
case 0x53445350: /* "SDSP" */
case 0x53444553: /* "SDES" */
case 0x53444D58: /* "SDMX" */
case 0x53445255: /* "SDRU" */
case 0x53444A41: /* "SDJA" */
case 0x53444A50: /* "SDJP" */
case 0x5344504C: /* "SDPL" */
/* audio chunk */
if (block_id == 0x5343446C || block_id == (0x53440000 | flag_lang)) {
/* "SCDl" or "SDxx" audio chunk */
if (vgmstream->coding_type == coding_PSX)
block_samples = ps_bytes_to_samples(block_size-0x10, vgmstream->channels);
else
block_samples = read_32bit(block_offset+0x08,streamFile);
break;
default:
/* ignore other chunks (audio "SCHl/SCCl/...", video "pIQT/MADk/...", etc) */
}
else {
/* ignore other chunks (audio "SCHl/SCCl/...", non-target lang, video "pIQT/MADk/...", etc) */
block_samples = 0; /* layout ignores this */
break;
}
/* "SCHl" start block (movie "SHxx" shouldn't use multi files) */
@ -185,7 +175,7 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
}
/* read ADPCM history before each channel if needed (not actually read in sx.exe) */
if (vgmstream->codec_config & 0x01) {
if (flag_adpcm) {
for (i = 0; i < vgmstream->channels; i++) {
//vgmstream->ch[i].adpcm_history1_32 = read_16bit(vgmstream->ch[i].offset+0x00,streamFile);
//vgmstream->ch[i].adpcm_history3_32 = read_16bit(vgmstream->ch[i].offset+0x02,streamFile);

View File

@ -74,6 +74,7 @@
#define EA_BLOCKID_LOC_JA 0x00004A41 /* Japanese, older */
#define EA_BLOCKID_LOC_JP 0x00004A50 /* Japanese, newer */
#define EA_BLOCKID_LOC_PL 0x0000504C /* Polish */
#define EA_BLOCKID_LOC_BR 0x00004252 /* Brazilian Portuguese */
#define EA_BNK_HEADER_LE 0x424E4B6C /* "BNKl" */
#define EA_BNK_HEADER_BE 0x424E4B62 /* "BNKb" */
@ -146,7 +147,8 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_RU) && /* "SHRU" */
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JA) && /* "SHJA" */
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_JP) && /* "SHJP" */
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_PL)) /* "SHPL" */
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_PL) && /* "SHPL" */
read_32bitBE(0x00,streamFile) != (EA_BLOCKID_LOC_HEADER | EA_BLOCKID_LOC_BR)) /* "SHBR" */
goto fail;
/* Stream is divided into blocks/chunks: SCHl=audio header, SCCl=count of SCDl, SCDl=data xN, SCLl=loop end, SCEl=end.
@ -702,8 +704,16 @@ fail:
static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int standalone) {
off_t start_offset, header_offset;
size_t header_size;
uint32_t header_id;
ea_header ea = { 0 };
/* use higher bits to store target localized block in case of multilang video,
* so only header sub-id will be read and other langs skipped */
header_id = read_32bitBE(offset + 0x00, streamFile);
if ((header_id & 0xFFFF0000) == EA_BLOCKID_LOC_HEADER) {
ea.codec_config |= (header_id & 0xFFFF) << 16;
}
if (guess_endianness32bit(offset + 0x04, streamFile)) { /* size is always LE, except in early SS/MAC */
header_size = read_32bitBE(offset + 0x04, streamFile);
ea.codec_config |= 0x02;
@ -1497,6 +1507,7 @@ static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start
size_t file_size = get_streamfile_size(streamFile);
off_t block_offset = start_offset;
int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE;
uint32_t header_lang = (ea->codec_config >> 16) & 0xFFFF;
while (block_offset < file_size) {
uint32_t block_id, block_size;
@ -1508,27 +1519,16 @@ static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start
if (block_size > 0x00F00000) /* size is always LE, except in early SAT/MAC */
block_size = read_32bitBE(block_offset+0x04,streamFile);
switch(block_id) {
case EA_BLOCKID_DATA: /* "SCDl" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_EN: /* "SDEN" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_FR: /* "SDFR" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_GE: /* "SDGE" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_DE: /* "SDDE" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_IT: /* "SDIT" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_SP: /* "SDSP" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_ES: /* "SDES" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_MX: /* "SDMX" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_RU: /* "SDRU" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_JA: /* "SDJA" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_JP: /* "SDJP" */
case EA_BLOCKID_LOC_DATA | EA_BLOCKID_LOC_PL: /* "SDPL" */
if (block_id == EA_BLOCKID_DATA || block_id == ((EA_BLOCKID_LOC_DATA | header_lang))) {
/* "SCDl" or target "SDxx" multilang blocks */
offset = read_32bit(block_offset+0x0c,streamFile); /* first value seems ok, second is something else in EALayer3 */
return block_offset + 0x0c + ea->channels*0x04 + offset;
case 0x00000000:
}
else if (block_id == 0x00000000) {
goto fail; /* just in case */
default:
}
else {
block_offset += block_size; /* size includes header */
break;
}
}