Add SCHl .hab/gsf/abk and custom mpf+mus pairs, remove trj/trm map pair

This commit is contained in:
bnnm 2019-01-02 16:15:03 +01:00
parent 7211e0e0ec
commit 49628d6198
2 changed files with 99 additions and 22 deletions

View File

@ -156,10 +156,12 @@ static const char* extension_list[] = {
"genh",
"gms",
"gsb",
//"gsf", //conflicts with GBA gsf plugins?
"gtd",
"gwm",
"h4m",
"hab",
"hca",
"hdr",
"hgc1",
@ -417,8 +419,6 @@ static const char* extension_list[] = {
"thp",
"tk5",
"tra",
"trj",
"trm",
"tun",
"txth",
"txtp",

View File

@ -5,24 +5,24 @@
/* header version */
#define EA_VERSION_NONE -1
#define EA_VERSION_V0 0x00 // ~early PC (when codec1 was used)
#define EA_VERSION_V1 0x01 // ~PC
#define EA_VERSION_V2 0x02 // ~PS era
#define EA_VERSION_V3 0x03 // ~PS2 era
#define EA_VERSION_V0 0x00 /* ~early PC (when codec1 was used) */
#define EA_VERSION_V1 0x01 /* ~PC */
#define EA_VERSION_V2 0x02 /* ~PS1 */
#define EA_VERSION_V3 0x03 /* ~PS2 */
/* platform constants (unasigned values seem internal only) */
#define EA_PLATFORM_GENERIC -1 // typically Wii/X360/PS3/videos
/* platform constants (unassigned values seem internal only) */
#define EA_PLATFORM_GENERIC -1 /* typically Wii/X360/PS3/videos */
#define EA_PLATFORM_PC 0x00
#define EA_PLATFORM_PSX 0x01
#define EA_PLATFORM_N64 0x02
#define EA_PLATFORM_MAC 0x03
#define EA_PLATFORM_SAT 0x04
#define EA_PLATFORM_PS2 0x05
#define EA_PLATFORM_GC_WII 0x06 // reused later for Wii
#define EA_PLATFORM_GC_WII 0x06
#define EA_PLATFORM_XBOX 0x07
#define EA_PLATFORM_X360 0x09 // also "Xenon"
#define EA_PLATFORM_X360 0x09
#define EA_PLATFORM_PSP 0x0A
#define EA_PLATFORM_PS3 0x0E // very rare [Need for Speed: Carbon (PS3)]
#define EA_PLATFORM_PS3 0x0E /* very rare [Need for Speed: Carbon (PS3)] */
#define EA_PLATFORM_3DS 0x14
/* codec constants (undefined are probably reserved, ie.- sx.exe encodes PCM24/DVI but no platform decodes them) */
@ -112,9 +112,24 @@ static void update_ea_stream_size_and_samples(STREAMFILE* streamFile, off_t star
/* EA SCHl with variable header - from EA games (roughly 1997~2010); generated by EA Canada's sx.exe/Sound eXchange */
VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
/* check extension; exts don't seem enforced by EA's tools, but usually:
* STR/ASF/MUS ~early, EAM ~mid, SNG/AUD ~late, rest uncommon/one game (ex. STRM: MySims Kingdom Wii) */
if (!check_extensions(streamFile,"str,asf,mus,eam,sng,aud,sx,strm,xa,xsf,exa,stm,trj,trm"))
/* check extension */
/* they don't seem enforced by EA's tools but usually:
* .asf: ~early [ex. Need for Speed (PC)]
* .str: ~early [ex. FIFA 2002 (PS1)]
* .eam: ~mid (fake?)
* .exa: ~mid [ex. 007 - From Russia with Love]
* .sng: ~late (fake?)
* .aud: ~late [ex. FIFA 14 (3DS)]
* .strm: MySims Kingdom (Wii)
* .stm: FIFA 12 (3DS)
* .sx/xa: fake?
* .hab: GoldenEye - Rogue Agent (inside .big)
* .xsf: 007 - Agent Under Fire (Xbox)
* .gsf: 007 - Everything or Nothing (GC)
* .mus: map/mpf+mus only?
* (extensionless): SSX (PS2) (inside .big) */
if (!check_extensions(streamFile,"asf,str,eam,exa,sng,aud,sx,xa,strm,stm,hab,xsf,gsf,mus,"))
goto fail;
/* check header */
@ -147,8 +162,12 @@ VGMSTREAM * init_vgmstream_ea_bnk(STREAMFILE *streamFile) {
off_t offset;
/* check extension */
/* .bnk: sfx, .sdt: speech, .mus: streams/jingles (rare) */
if (!check_extensions(streamFile,"bnk,sdt,mus"))
/* .bnk: common
* .sdt: Harry Potter games
* .mus: streams/jingles (rare)
* .abk: GoldenEye - Rogue Agent
* .ast: FIFA 2004 (inside .big) */
if (!check_extensions(streamFile,"bnk,sdt,mus,abk,ast"))
goto fail;
/* check header (doesn't use EA blocks, otherwise very similar to SCHl) */
@ -363,7 +382,59 @@ fail:
return NULL;
}
/* EA MAP/MUS combo - used in some old games for interactive music info */
/* open map/mpf+mus pairs that aren't exact pairs, since EA's games can load any combo */
static STREAMFILE * open_mapfile_pair(STREAMFILE *streamFile) {
static const char *const mapfile_pairs[][2] = {
/* standard cases, replace map part with mus part (from the end to preserve prefixes) */
{"MUS_CTRL.MPF","MUS_STR.MUS"}, /* GoldenEye - Rogue Agent (PS2) */
{"mus_ctrl.mpf","mus_str.mus"}, /* GoldenEye - Rogue Agent (others) */
{".mpf","_main.mus"}, /* 007 - Everything or Nothing (GC) */
/* hack when when multiple maps point to the same mus, uses name before "+"
* ex. ZZZTR00A.TRJ+ZTR00PGR.MAP or ZZZTR00A.TRJ+ZTR00R0A.MAP both point to ZZZTR00A.TRJ */
{"+",""}, /* Need for Speed III (PS1) */
};
STREAMFILE *musFile = NULL;
char file_name[PATH_LIMIT];
int pair_count = (sizeof(mapfile_pairs)/sizeof(mapfile_pairs[0]));
int i;
size_t file_len, map_len;
get_streamfile_filename(streamFile, file_name, PATH_LIMIT);
file_len = strlen(file_name);
for (i = 0; i < pair_count; i++) {
const char *map_name = mapfile_pairs[i][0];
const char *mus_name = mapfile_pairs[i][1];
map_len = strlen(map_name);
if (map_name[0] == '+') {
/* use name before "+" */
char *mod_name = strchr(file_name, '+');
if (mod_name == NULL)
continue;
mod_name[0] = '\0';
}
else {
/* replace map_name with expected mus_name */
if (file_len < map_len)
continue;
if (strncmp(file_name+(file_len - map_len), map_name, map_len) != 0)
continue;
file_name[file_len - map_len] = '\0';
strcat(file_name, mus_name);
}
musFile = open_streamfile_by_filename(streamFile, file_name);
if (musFile) return musFile;
get_streamfile_filename(streamFile, file_name, PATH_LIMIT); /* reset for next loop */
}
return NULL;
}
/* EA MAP/MUS combo - used in older games for interactive music (for EA's PathFinder tool) */
VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) {
uint8_t version, num_sounds, num_userdata, userdata_size;
off_t section_offset, schl_offset;
@ -383,7 +454,10 @@ VGMSTREAM * init_vgmstream_ea_map_mus(STREAMFILE *streamFile) {
if (version > 1) goto fail;
musFile = open_streamfile_by_ext(streamFile, "mus");
if (!musFile) {
musFile = open_mapfile_pair(streamFile);
if (!musFile) goto fail;
}
/*
* 0x04: ???
@ -427,7 +501,7 @@ fail:
return NULL;
}
/* EA MPF/MUS combo - used in newer 6th gen games for storing music */
/* EA MPF/MUS combo - used in newer 6th gen games for interactive music (for EA's PathFinder tool) */
VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
off_t section_offset, entry_offset, subentry_num, eof_offset, off_mult, schl_offset;
size_t sec2_size;
@ -463,12 +537,15 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
if (version == 5 && sub_version > 2) goto fail; /* newer version using SNR/SNS */
musFile = open_streamfile_by_ext(streamFile, "mus");
if (!musFile) {
musFile = open_mapfile_pair(streamFile);
if (!musFile) goto fail;
}
/* HACK: number of sub-entries is stored in bitstreams that are different in LE and BE */
/* I can't figure it out, so let's just use a workaround for now */
if (version == 3 && sub_version == 1) { /* SSX Tricky /*
if (version == 3 && sub_version == 1) { /* SSX Tricky */
/* we need to go through the first two sections to find sound table */
sec1_num = read_16bit(0x12, streamFile);
sec2_size = read_8bit(0x0e, streamFile);
@ -517,7 +594,7 @@ VGMSTREAM * init_vgmstream_ea_mpf_mus(STREAMFILE *streamFile) {
eof_offset = read_32bit(entry_offset + 0x04, streamFile) * 0x04;
total_streams = (eof_offset - section_offset) / 0x08;
off_mult = 0x04;
} else if (version == 4) { /* SSX 3, Need for Speed: Underground 2 /*
} else if (version == 4) { /* SSX 3, Need for Speed: Underground 2 */
/* 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);