Some organization and better endianness checks in EA parsers

This commit is contained in:
NicknineTheEagle 2018-08-08 17:06:39 +03:00
parent ae5e218518
commit 15cc60e604
3 changed files with 48 additions and 46 deletions

View File

@ -23,7 +23,7 @@ void block_update_ea_schl(off_t block_offset, VGMSTREAM * vgmstream) {
{
uint32_t block_id = read_32bitBE(block_offset+0x00,streamFile);
if (guess_endianness32bit(block_offset + 0x04,streamFile)) /* size is always LE, except in early SS/MAC */
if (vgmstream->codec_version & 0x02) /* 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);
@ -180,7 +180,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_version == 1) {
if (vgmstream->codec_version & 0x01) {
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

@ -307,18 +307,17 @@ fail:
/* EA S10A header - seen inside new ABK files. Putting it here in case it's encountered stand-alone. */
static VGMSTREAM * parse_s10a_header(STREAMFILE *streamFile, off_t offset, uint16_t target_index, off_t ast_offset) {
uint32_t header, num_sounds;
uint32_t num_sounds;
off_t snr_offset, sns_offset;
STREAMFILE *astFile = NULL;
VGMSTREAM *vgmstream;
/* header is always big endian */
/* 0x00 - header magic */
/* 0x04 - zero */
/* 0x08 - number of files */
/* 0x0C - offsets table */
header = read_32bitBE(offset + 0x00, streamFile);
if (header != 0x53313041) /* "S10A" */
/* 0x00: header magic */
/* 0x04: zero */
/* 0x08: number of files */
/* 0x0C: offsets table */
if (read_32bitBE(offset + 0x00, streamFile) != 0x53313041) /* "S10A" */
goto fail;
num_sounds = read_32bitBE(offset + 0x08, streamFile);

View File

@ -53,6 +53,7 @@
#define EA_BLOCKID_HEADER 0x5343486C /* "SCHl" */
#define EA_BLOCKID_COUNT 0x5343436C /* "SCCl" */
#define EA_BLOCKID_DATA 0x5343446C /* "SCDl" */
#define EA_BLOCKID_LOOP 0x53434C6C /* "SCLl */
#define EA_BLOCKID_END 0x5343456C /* "SCEl" */
/* Localized block headers, Sxyy - where x is block ID and yy is lang code (e.g. "SHEN"), used in videos */
@ -97,7 +98,7 @@ typedef struct {
static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int total_streams);
static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int target_stream, int total_streams);
static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length);
static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length, int bnk_version);
static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset);
static int get_ea_stream_total_samples(STREAMFILE* streamFile, off_t start_offset, VGMSTREAM* vgmstream);
static off_t get_ea_stream_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea);
@ -140,13 +141,8 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
goto fail;
/* check header (doesn't use EA blocks, otherwise very similar to SCHl) */
if (read_32bitBE(0x00,streamFile) == EA_BNK_HEADER_LE ||
read_32bitBE(0x00,streamFile) == EA_BNK_HEADER_BE)
offset = 0;
else if (read_32bitBE(0x100,streamFile) == EA_BNK_HEADER_LE)
if (read_32bitBE(0x100,streamFile) == EA_BNK_HEADER_LE)
offset = 0x100; /* Harry Potter and the Goblet of Fire (PS2) .mus have weird extra 0x100 bytes */
else
goto fail;
return parse_bnk_header(streamFile, offset, streamFile->stream_index, 0);
@ -263,10 +259,6 @@ VGMSTREAM * init_vgmstream_ea_abk(STREAMFILE *streamFile) {
if (!bnk_offset)
goto fail;
if (read_32bitBE(bnk_offset, streamFile) != EA_BNK_HEADER_LE &&
read_32bitBE(bnk_offset, streamFile) != EA_BNK_HEADER_BE)
goto fail;
bnk_target_stream = read_32bit(target_entry_offset + 0x04, streamFile) + 1;
vgmstream = parse_bnk_header(streamFile, bnk_offset, bnk_target_stream, total_sounds);
if (!vgmstream)
@ -453,14 +445,17 @@ static VGMSTREAM * parse_schl_block(STREAMFILE *streamFile, off_t offset, int to
size_t header_size;
ea_header ea = { 0 };
if (guess_endianness32bit(offset + 0x04, streamFile)) /* size is always LE, except in early SS/MAC */
if (guess_endianness32bit(offset + 0x04, streamFile)) { /* size is always LE, except in early SS/MAC */
header_size = read_32bitBE(offset + 0x04, streamFile);
else
ea.codec_version |= 0x02;
}
else {
header_size = read_32bitLE(offset + 0x04, streamFile);
}
header_offset = offset + 0x08;
if (!parse_variable_header(streamFile, &ea, header_offset, header_size - 0x08))
if (!parse_variable_header(streamFile, &ea, header_offset, header_size - 0x08, 0))
goto fail;
start_offset = offset + header_size; /* starts in "SCCl" (skipped in block layout) or very rarely "SCDl" and maybe movie blocks */
@ -482,14 +477,19 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta
int i, bnk_version;
int total_bnk_sounds, real_bnk_sounds = 0;
/* use header size as endianness flag */
if (guess_endianness32bit(offset + 0x08,streamFile)) {
/* check header */
/* BNK header endianness is platform-native */
if (read_32bitBE(start_offset + 0x00, streamFile) == EA_BNK_HEADER_BE) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
}
else if (read_32bitBE(start_offset + 0x00, streamFile) == EA_BNK_HEADER_LE) {
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
}
else {
goto fail;
}
bnk_version = read_8bit(offset + 0x04,streamFile);
total_bnk_sounds = read_16bit(offset + 0x06,streamFile);
@ -538,7 +538,7 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta
if (target_stream < 0 || header_offset == 0 || real_bnk_sounds < 1) goto fail;
if (!parse_variable_header(streamFile,&ea, header_offset, header_size - header_offset))
if (!parse_variable_header(streamFile,&ea, header_offset, header_size - header_offset, bnk_version))
goto fail;
/* fix absolute offsets so it works in next funcs */
@ -550,11 +550,6 @@ static VGMSTREAM * parse_bnk_header(STREAMFILE *streamFile, off_t offset, int ta
start_offset = ea.offsets[0]; /* first channel, presumably needed for MPEG */
/* it looks like BNKs never store ADPCM history for EA-XA */
if (ea.codec2 == EA_CODEC2_EAXA) {
ea.codec_version = 0;
}
/* rest is common */
return init_vgmstream_ea_variable_header(streamFile, &ea, start_offset, bnk_version, total_streams ? total_streams : real_bnk_sounds);
@ -619,7 +614,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
switch (ea->codec2) {
case EA_CODEC2_EAXA: /* EA-XA, CDXA ADPCM variant */
if (ea->codec1 == EA_CODEC1_EAXA) {
if (ea->version == EA_VERSION_V0) {
if (ea->platform != EA_PLATFORM_SAT && ea->channels > 1)
vgmstream->coding_type = coding_EA_XA; /* original version, stereo stream */
else
@ -768,7 +763,7 @@ static VGMSTREAM * init_vgmstream_ea_variable_header(STREAMFILE *streamFile, ea_
}
/* read ADPCM history before each channel if needed (not actually read in sx.exe) */
if (vgmstream->codec_version == 1) {
if (vgmstream->codec_version & 0x01) {
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);
@ -822,11 +817,11 @@ static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset) {
}
/* decodes EA's GSTR/PT header (mostly cross-referenced with sx.exe) */
static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length) {
static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length, int bnk_version) {
off_t offset = begin_offset;
uint32_t platform_id;
int is_header_end = 0;
int is_bnk = bnk_version;
/* null defaults as 0 can be valid */
ea->version = EA_VERSION_NONE;
@ -1125,16 +1120,24 @@ static int parse_variable_header(STREAMFILE* streamFile, ea_header* ea, off_t be
}
}
/* special flag: 1=has ADPCM history per block, 0=doesn't */
if (ea->codec2 == EA_CODEC2_GCADPCM && ea->platform == EA_PLATFORM_3DS) {
ea->codec_version = 1;
}
else if (ea->codec2 == EA_CODEC2_EAXA && ea->codec1 == EA_CODEC1_NONE) {
/* console V2 uses hist, as does PC/MAC V1 (but not later versions) */
if (ea->version <= EA_VERSION_V1 ||
((ea->platform == EA_PLATFORM_PS2 || ea->platform == EA_PLATFORM_GC_WII || ea->platform == EA_PLATFORM_XBOX)
&& ea->version == EA_VERSION_V2)) {
ea->codec_version = 1;
/* some codecs have ADPCM hist at the start of every block in streams (but not BNKs) */
if (!is_bnk) {
if (ea->codec2 == EA_CODEC2_GCADPCM) {
if (ea->platform == EA_PLATFORM_3DS)
ea->codec_version |= 0x01;
}
else if (ea->codec2 == EA_CODEC2_EAXA) {
/* EA-XA has ADPCM hist in earlier versions */
/* V0, V1: always */
/* V2: consoles only */
/* V3: never */
if (ea->version == EA_VERSION_V1) {
ea->codec_version |= 0x01;
}
else if (ea->version == EA_VERSION_V2) {
if (ea->platform == EA_PLATFORM_PS2 || ea->platform == EA_PLATFORM_GC_WII || ea->platform == EA_PLATFORM_XBOX)
ea->codec_version |= 0x01;
}
}
}