mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
VAG: EoR/Maxis engine variations
This commit is contained in:
parent
a3be024fe2
commit
a22377f980
@ -1024,6 +1024,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_RAW_PCM, "PC .raw raw header"},
|
||||
{meta_VAG, "Sony VAG header"},
|
||||
{meta_VAG_custom, "Sony VAG header (custom)"},
|
||||
{meta_VAG_footer, "Sony VAG footer"},
|
||||
{meta_AAAP, "Acclaim Austin AAAp header"},
|
||||
{meta_SEB, "Game Arts .SEB header"},
|
||||
{meta_STR_WAV, "Blitz Games .STR+WAV header"},
|
||||
|
@ -166,8 +166,9 @@ VGMSTREAM* init_vgmstream_ea_schl(STREAMFILE* sf) {
|
||||
* .hab: GoldenEye - Rogue Agent (inside .big)
|
||||
* .xsf: 007 - Agent Under Fire (Xbox)
|
||||
* .gsf: 007 - Everything or Nothing (GC)
|
||||
* (extensionless): SSX (PS2) (inside .big) */
|
||||
if (!check_extensions(sf,"asf,lasf,str,chk,eam,exa,sng,aud,sx,xa,strm,stm,hab,xsf,gsf,"))
|
||||
* (extensionless): SSX (PS2) (inside .big)
|
||||
* .r: The Sims 2: Pets (PSP) (not l/r, shorter "res") */
|
||||
if (!check_extensions(sf,"asf,lasf,str,chk,eam,exa,sng,aud,sx,xa,strm,stm,hab,xsf,gsf,,r"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
@ -307,8 +308,9 @@ VGMSTREAM* init_vgmstream_ea_bnk(STREAMFILE* sf) {
|
||||
* .hdt/ldt: Burnout games (PSP)
|
||||
* .abk: GoldenEye - Rogue Agent
|
||||
* .ast: FIFA 2004 (inside .big)
|
||||
* .cat: FIFA 2000 (PC, chant.cat) */
|
||||
if (!check_extensions(sf,"bnk,sdt,hdt,ldt,abk,ast,cat"))
|
||||
* .cat: FIFA 2000 (PC, chant.cat)
|
||||
* (extensionless): The Sims 2 spinoffs (PSP) */
|
||||
if (!check_extensions(sf,"bnk,sdt,hdt,ldt,abk,ast,cat,"))
|
||||
goto fail;
|
||||
|
||||
if (target_stream == 0) target_stream = 1;
|
||||
|
@ -103,8 +103,9 @@ VGMSTREAM* init_vgmstream_mic_koei(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM * init_vgmstream_raw_pcm(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_vag_aaap(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_vag(STREAMFILE *sf);
|
||||
VGMSTREAM * init_vgmstream_vag_aaap(STREAMFILE *sf);
|
||||
VGMSTREAM * init_vgmstream_vag_footer(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM * init_vgmstream_seb(STREAMFILE *streamFile);
|
||||
|
||||
|
116
src/meta/vag.c
116
src/meta/vag.c
@ -5,7 +5,7 @@
|
||||
/* VAGp - Sony SDK format, created by various official tools */
|
||||
VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t start_offset, file_size, channel_size, interleave, interleave_first = 0, interleave_first_skip = 0;
|
||||
uint32_t start_offset, file_size, channel_size, stream_name_size, interleave, interleave_first = 0, interleave_first_skip = 0;
|
||||
meta_t meta_type;
|
||||
int channels = 0, loop_flag, sample_rate;
|
||||
uint32_t vag_id, version, reserved;
|
||||
@ -26,8 +26,9 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
* .vas: Kingdom Hearts II (PS2)
|
||||
* .xa2: Shikigami no Shiro (PS2)
|
||||
* .snd: Alien Breed (Vita)
|
||||
* .svg: ModernGroove: Ministry of Sound Edition (PS2) */
|
||||
if (!check_extensions(sf,"vag,swag,str,vig,l,r,vas,xa2,snd,svg"))
|
||||
* .svg: ModernGroove: Ministry of Sound Edition (PS2)
|
||||
* (extensionless): The Urbz (PS2), The Sims series (PS2) */
|
||||
if (!check_extensions(sf,"vag,swag,str,vig,l,r,vas,xa2,snd,svg,"))
|
||||
return NULL;
|
||||
|
||||
file_size = get_streamfile_size(sf);
|
||||
@ -51,6 +52,11 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
/* 0x20-30: name (optional) */
|
||||
/* 0x30: data start (first 0x10 usually 0s to init SPU) */
|
||||
|
||||
/* a few Edge of Reality titles use the blank adpcm frame to
|
||||
* store a longer stream name, so the length is defined here
|
||||
* to allow for it to be overridden for such rare exceptions */
|
||||
stream_name_size = 0x10;
|
||||
|
||||
/* check variation */
|
||||
switch(vag_id) {
|
||||
|
||||
@ -159,15 +165,27 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
|
||||
loop_flag = 0;
|
||||
}
|
||||
else if (version == 0x40000000) {
|
||||
/* Killzone (PS2) */
|
||||
start_offset = 0x30;
|
||||
else if (version == 0x02000000 || version == 0x40000000) {
|
||||
/* Edge of Reality engine (PS2) (0x02), Killzone (PS2) (0x40) */
|
||||
/* Stream starts at 0x40 for both variants. EoR/Maxis uses the
|
||||
* blank SPU init frame to store the loop flag in its 1st byte.
|
||||
* Later EoR games (Over the Hedge) have 32 char stream names,
|
||||
* and moved the loop flag stored in the reserved field at 0x1E */
|
||||
start_offset = 0x40;
|
||||
channels = 1;
|
||||
interleave = 0;
|
||||
|
||||
channel_size = read_u32le(0x0C,sf) / channels;
|
||||
channel_size = read_u32le(0x0C,sf);
|
||||
sample_rate = read_s32le(0x10,sf);
|
||||
loop_flag = 0;
|
||||
loop_flag = 0; /* adpcm flags always 0x02 in Killzone */
|
||||
|
||||
/* EoR/Maxis title specific
|
||||
* always blank in Killzone */
|
||||
if (version == 0x02000000) {
|
||||
//uint8_t c = read_u8(0x30, sf); /* maybe better to do (c >= 0x30 && c <= 0x7A)? */
|
||||
if (read_u8(0x30, sf) >= 0x20 && read_u8(0x30, sf) <= 0x7E) stream_name_size = 0x20;
|
||||
loop_flag = ps_find_loop_offsets(sf, start_offset, channel_size, channels, interleave, &loop_start_sample, &loop_end_sample);
|
||||
}
|
||||
}
|
||||
else if (version == 0x00020001 || version == 0x00030000) {
|
||||
/* standard Vita/PS4 .vag [Chronovolt (Vita), Grand Kingdom (PS4)] */
|
||||
@ -300,10 +318,10 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
|
||||
/* ignore bigfiles and bad extractions (approximate) */
|
||||
/* padding is set to 2 MiB to avoid breaking Jak series' VAGs */
|
||||
if (channel_size * channels + interleave * channels + start_offset * channels + 0x200000 < get_streamfile_size(sf) ||
|
||||
channel_size * channels > get_streamfile_size(sf)) {
|
||||
if (channel_size * channels + interleave * channels + start_offset * channels + 0x200000 < file_size ||
|
||||
channel_size * channels > file_size) {
|
||||
vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n",
|
||||
channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf));
|
||||
channel_size, channels, interleave * channels, start_offset * channels, file_size);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -329,7 +347,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) {
|
||||
if (has_interleave_last && channels > 1 && interleave)
|
||||
vgmstream->interleave_last_block_size = channel_size % interleave;
|
||||
|
||||
read_string(vgmstream->stream_name,0x10+1, 0x20,sf); /* always, can be null */
|
||||
read_string(vgmstream->stream_name, stream_name_size + 1, 0x20, sf); /* always, can be null */
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
@ -353,7 +371,7 @@ VGMSTREAM* init_vgmstream_vag_aaap(STREAMFILE* sf) {
|
||||
if (!is_id32be(0x00, sf, "AAAp"))
|
||||
return NULL;
|
||||
|
||||
/* .vag - assumed, we don't know the original filenames */
|
||||
/* .vag: original names before hashing */
|
||||
if (!check_extensions(sf, "vag"))
|
||||
return NULL;
|
||||
|
||||
@ -363,7 +381,7 @@ VGMSTREAM* init_vgmstream_vag_aaap(STREAMFILE* sf) {
|
||||
|
||||
/* file has VAGp header for each channel */
|
||||
for (i = 0; i < channels; i++) {
|
||||
if (read_u32be(vag_offset + i * 0x30, sf) != 0x56414770) /* "VAGp" */
|
||||
if (!is_id32be(vag_offset + i * 0x30, sf, "VAGp"))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -395,3 +413,73 @@ fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* VAGp (footer) - Sims 2 console spinoffs [The Sims 2: Pets (PS2), The Sims 2: Castaway (PS2)] */
|
||||
VGMSTREAM* init_vgmstream_vag_footer(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
size_t file_size, stream_size;
|
||||
off_t header_offset, start_offset;
|
||||
int channels, interleave, sample_rate, loop_flag;
|
||||
int32_t loop_start_sample = 0, loop_end_sample = 0;
|
||||
uint32_t version;
|
||||
|
||||
|
||||
file_size = get_streamfile_size(sf);
|
||||
header_offset = file_size - 0x40;
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(header_offset, sf, "VAGp"))
|
||||
return NULL;
|
||||
|
||||
/* (extensionless): Sims 2 console spinoffs
|
||||
* .vag: assumed, may be added by tools */
|
||||
if (!check_extensions(sf, ",vag"))
|
||||
return NULL;
|
||||
|
||||
|
||||
/* all the data is in little endian */
|
||||
version = read_u32le(header_offset + 0x04, sf);
|
||||
stream_size = read_u32le(header_offset + 0x0C, sf);
|
||||
sample_rate = read_u32le(header_offset + 0x10, sf);
|
||||
|
||||
/* what's meant to be the SPU init frame instead has garbage data, apart from the very 1st byte */
|
||||
/* see the comment under (case 0x56414770:) where (version == 0x02000000) in init_vgmstream_vag */
|
||||
//loop_flag = read_u8(header_offset + 0x30, sf); /* ? */
|
||||
|
||||
/* in the very unlikely chance anyone else was
|
||||
* unhinged enough to do something like this */
|
||||
if (version != 0x00000002) goto fail;
|
||||
/* stream "header" (footer) is aligned to 0x40 */
|
||||
if (align_size_to_block(stream_size + 0x40, 0x40) != file_size)
|
||||
goto fail;
|
||||
|
||||
channels = 1;
|
||||
interleave = 0;
|
||||
start_offset = 0;
|
||||
|
||||
loop_flag = ps_find_loop_offsets(sf, start_offset, stream_size, channels, interleave, &loop_start_sample, &loop_end_sample);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_VAG_footer;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->loop_start_sample = loop_start_sample;
|
||||
vgmstream->loop_end_sample = loop_end_sample;
|
||||
vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels);
|
||||
|
||||
read_string(vgmstream->stream_name, 0x10 + 1, header_offset + 0x20, sf);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ init_vgmstream_t init_vgmstream_functions[] = {
|
||||
init_vgmstream_ngc_dsp_std_int,
|
||||
init_vgmstream_vag,
|
||||
init_vgmstream_vag_aaap,
|
||||
init_vgmstream_vag_footer,
|
||||
init_vgmstream_ild,
|
||||
init_vgmstream_ngc_str,
|
||||
init_vgmstream_ea_schl,
|
||||
|
@ -309,6 +309,7 @@ typedef enum {
|
||||
meta_PS2_MIC, /* KOEI MIC File */
|
||||
meta_VAG,
|
||||
meta_VAG_custom,
|
||||
meta_VAG_footer,
|
||||
meta_AAAP,
|
||||
meta_SEB,
|
||||
meta_STR_WAV, /* Blitz Games STR+WAV files */
|
||||
|
Loading…
Reference in New Issue
Block a user