Add MPEG to EA SCHl [Harry Potter and the Chamber of Secrets (PS2)]

This commit is contained in:
bnnm 2017-07-01 23:55:10 +02:00
parent d85c033c9d
commit 68071467c2
3 changed files with 65 additions and 12 deletions

View File

@ -373,7 +373,8 @@ static void decode_mpeg_interleave(VGMSTREAM * vgmstream, mpeg_codec_data * data
data->bytes_used_in_interleave_buffer = 0;
for (i=0; i < data->ms_size; i++) {
if (data->interleave_type == MPEG_P3D) /* P3D have a strange way to interleave so just use first offset */
if (data->interleave_type == MPEG_P3D /* P3D have a strange way to interleave so just use first offset */
|| data->interleave_type == MPEG_EA) /* EA MPEG is simply frame by frame normal MPEG */
decode_mpeg_interleave_samples(&vgmstream->ch[0], data, data->ms[i], channels, i, vgmstream->interleave_block_size);
else
decode_mpeg_interleave_samples(&vgmstream->ch[i], data, data->ms[i], channels, i, vgmstream->interleave_block_size);
@ -529,12 +530,6 @@ static int update_frame_sizes(mpeg_codec_data * data, STREAMFILE *streamfile, of
/* Manually find new frame size. Not ideal but mpg123_info.framesize is wrong sometimes */
if ( !mpeg_get_frame_info(streamfile, offset, &info) )
goto fail;
/* could mess some calcs */
VGM_ASSERT(data->sample_rate_per_frame != info.sample_rate || data->samples_per_frame != info.frame_samples,
"MPEG: variable frame info found @ 0x%08lx", offset);
/* new frame */
data->current_frame_size = info.frame_size;
/* get FSB padding for MPEG1/2 Layer III (MPEG1 Layer II doesn't use it, and Layer I doesn't seem to be supported) */
@ -543,6 +538,10 @@ static int update_frame_sizes(mpeg_codec_data * data, STREAMFILE *streamfile, of
? data->interleave_value - (data->current_frame_size % data->interleave_value)
: 0;
}
/* could mess some calcs */
VGM_ASSERT(data->sample_rate_per_frame != info.sample_rate || data->samples_per_frame != info.frame_samples,
"MPEG: variable frame info found @ 0x%08lx", offset);
}
else if (data->interleave_type == MPEG_P3D) { /* varying frames size, even though the frame header says 0x120 */
uint32_t header = read_32bitBE(offset,streamfile);
@ -561,7 +560,14 @@ static int update_frame_sizes(mpeg_codec_data * data, STREAMFILE *streamfile, of
VGM_LOG("MPEG: unknown frame size @ %lx, %x\n", offset, read_32bitBE(offset+0x120,streamfile));
goto fail;
}
}
else if (data->interleave_type == MPEG_EA) { /* straight frame by frame */
mpeg_frame_info info;
/* Manually find new frame size. Not ideal but mpg123_info.framesize is wrong sometimes */
if ( !mpeg_get_frame_info(streamfile, offset, &info) )
goto fail;
data->current_frame_size = info.frame_size;
}
return 1;

View File

@ -71,6 +71,7 @@ typedef struct {
static int parse_stream_header(STREAMFILE* streamFile, ea_header* ea, off_t begin_offset, int max_length);
static uint32_t read_patch(STREAMFILE* streamFile, off_t* offset);
static int get_ea_total_samples(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea);
static off_t get_ea_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea);
/* EA SCHl - from EA games (roughly 1997~2010, generated by EA Canada's sx.exe / Sound eXchange) */
@ -170,9 +171,26 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
}
break;
case EA_CODEC2_MT5: /* MicroTalk (5:1) */
#ifdef VGM_USE_MPEG
case EA_CODEC2_LAYER2: /* MPEG Layer II, aka MP2 */
case EA_CODEC2_LAYER3: /* MPEG Layer III, aka MP3 */
case EA_CODEC2_LAYER3: { /* MPEG Layer III, aka MP3 */
mpeg_codec_data *mpeg_data = NULL;
coding_t mpeg_coding_type;
off_t mpeg_start_offset = get_ea_mpeg_start_offset(streamFile, start_offset, &ea);
if (!mpeg_start_offset) goto fail;
mpeg_data = init_mpeg_codec_data_interleaved(streamFile, mpeg_start_offset, &mpeg_coding_type, vgmstream->channels, MPEG_EA, 0);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
vgmstream->coding_type = mpeg_coding_type;
//vgmstream->layout_type = layout_mpeg;
//mpeg_set_error_logging(mpeg_data, 0); /* should not be needed anymore with the interleave decoder */
break;
}
#endif
case EA_CODEC2_MT5: /* MicroTalk (5:1) */
case EA_CODEC2_EALAYER3: /* MP3 variant */
default:
VGM_LOG("EA: unknown codec2 0x%02x for platform 0x%02x\n", ea.codec2, ea.platform);
@ -504,8 +522,7 @@ static int get_ea_total_samples(STREAMFILE* streamFile, off_t start_offset, cons
int i, num_samples = 0;
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;
int32_t (*read_32bit)(off_t,STREAMFILE*) = ea->big_endian ? read_32bitBE : read_32bitLE;
while (block_offset < file_size) {
uint32_t id, block_size;
@ -559,3 +576,33 @@ static int get_ea_total_samples(STREAMFILE* streamFile, off_t start_offset, cons
return num_samples;
}
/* find data start offset inside the first SCDl; not very elegant but oh well */
static off_t get_ea_mpeg_start_offset(STREAMFILE* streamFile, off_t start_offset, const ea_header* ea) {
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;
while (block_offset < file_size) {
uint32_t id, block_size;
id = read_32bitBE(block_offset+0x00,streamFile);
block_size = read_32bitLE(block_offset+0x04,streamFile);
if (block_size > 0xF0000000) /* size is always LE, except in early MAC apparently */
block_size = read_32bitBE(block_offset+0x04,streamFile);
if (id == 0x5343446C) { /* "SCDl" data block found */
off_t offset = read_32bit(block_offset+0x0c,streamFile); /* first channel offset is ok, MPEG channels share offsets */
return block_offset + 0x0c + ea->channels*0x04 + offset;
} else if (id == 0x5343436C) { /* "SCCl" data count found */
block_offset += block_size; /* size includes header */
continue;
} else {
goto fail;
}
}
fail:
return 0;
}

View File

@ -825,7 +825,7 @@ typedef struct {
#endif
#ifdef VGM_USE_MPEG
typedef enum { /*MPEG_NONE,*/ MPEG_FIXED, MPEG_FSB, MPEG_P3D } mpeg_interleave_type;
typedef enum { /*MPEG_NONE,*/ MPEG_FIXED, MPEG_FSB, MPEG_P3D, MPEG_EA } mpeg_interleave_type;
typedef struct {
uint8_t *buffer; /* raw (coded) data buffer */
size_t buffer_size;