Merge pull request #1554 from EdnessP/master

- Fix broken Asura DSP .SFX header check
- Improve EA MSB based on EA AMB research
This commit is contained in:
bnnm 2024-07-08 17:00:09 +02:00 committed by GitHub
commit 25c2375f5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 61 additions and 52 deletions

View File

@ -16,50 +16,53 @@ VGMSTREAM* init_vgmstream_ea_mpf_mus_eaac(STREAMFILE* sf) {
/* .MSB/MSX - EA Redwood Shores (MSB/MSX)+MUS [The Godfather (PS3/360), The Simpsons Game (PS3/360)] */
VGMSTREAM* init_vgmstream_ea_msb_mus_eaac(STREAMFILE* sf) {
/* container with MPF, extra info, and a pre-defined MUS filename */
/* container with .MPF ("PFDx"), .NAM (numevents/numparts/numdefines), and a pre-defined MUS filename */
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_mpf = NULL;
char mus_name[0x20 + 1];
size_t header_size;
off_t info_offset, mus_name_offset;
size_t mpf_size;
off_t header_offset, mpf_offset, mus_name_offset;
read_u32_t read_u32;
if (read_u64be(0x00, sf) != 0)
return NULL;
if (!check_extensions(sf, "msb,msx"))
return NULL;
header_size = 0x50;
mus_name_offset = 0x30;
/* 0x08: buffer size of the pre-defined .mus filename? (always 0x20)
* 0x20: mpf version number? (always 0x05)
* 0x24: offset to a chunk of plaintext data w/ event and node info & names
* 0x2C: some hash?
* 0x30: intended .mus filename */
read_u32 = guess_read_u32(0x08, sf);
/* extra checks to fail faster before streamfile'ing */
if (read_u32(0x08, sf) != 0x20)
if (read_u64le(0x00, sf) != 0)
return NULL;
if (read_u32(0x20, sf) != 0x05)
header_offset = read_u32(0x08, sf);
if (header_offset != 0x20)
return NULL;
if (read_u32(header_offset, sf) != 0x05) /* version */
return NULL;
/* not exactly the same as mpf size since it's aligned, but doesn't matter here */
info_offset = read_u32(0x24, sf); //+ header_size;
mpf_offset = header_offset + 0x30;
/* Version 0x05:
* 0x04: plaintext events/parts/defines offset (+ mpf offset)
* 0x08: always 0?
* 0x0C: some hash?
* 0x10: intended .mus filename
* 0x30: PFDx data
*/
mus_name_offset = header_offset + 0x10;
/* not exactly the same as mpf size since it's aligned, but correct size is only needed for v3 */
mpf_size = read_u32(header_offset + 0x04, sf);
/* TODO: it should be theoretically possible to use the numparts section
* in the plaintext chunk to get valid stream names using its entry node
* indices by checking if they're within range of the current subsong.
*
* However the main thing currently preventing that from being a thing
* is the fact that the indices deviate starting off by being off by 1,
* and can go up to being off by like 10 or in some rare extreme cases
* up to couple 100s. See if this index logic has some rhyme or reason.
*/
* indices by checking if they're within range of the current subsong */
/* However, there is something funky going on, where for each stream the
* number goes off by 2 (and in some cases by a much larger value) which
* needs to be worked out first before anything else can be done */
read_string(mus_name, sizeof(mus_name), mus_name_offset, sf);
/* usually the same base name, but can rarely be different
* e.g. bargain_bin.msb/msx -> bin.mus [The Simpsons Game]
*/
sf_mpf = open_wrap_streamfile(sf);
sf_mpf = open_clamp_streamfile(sf_mpf, header_size, info_offset);
sf_mpf = open_clamp_streamfile(sf_mpf, mpf_offset, mpf_size);
if (!sf_mpf) goto fail;
vgmstream = init_vgmstream_ea_mpf_mus_eaac_main(sf_mpf, mus_name);

View File

@ -87,41 +87,47 @@ VGMSTREAM* init_vgmstream_ea_mpf_mus_schl(STREAMFILE* sf) {
/* .MSB/MSX - EA Redwood Shores (MSB/MSX)+MUS [007: From Russia with Love, The Godfather (PC/PS2/Xbox/Wii)] */
VGMSTREAM* init_vgmstream_ea_msb_mus_schl(STREAMFILE* sf) {
/* container with MPF, extra info, and a pre-defined MUS filename */
/* container with .MPF ("PFDx"), .NAM (numevents/numparts/numdefines), and a pre-defined MUS filename */
VGMSTREAM* vgmstream = NULL;
STREAMFILE* sf_mpf = NULL;
char mus_name[0x20 + 1];
size_t header_size;
off_t info_offset, mus_name_offset;
size_t mpf_size;
off_t header_offset, mpf_offset, mus_name_offset;
read_u32_t read_u32;
if (read_u64be(0x00, sf) != 0)
return NULL;
if (!check_extensions(sf, "msb,msx"))
return NULL;
header_size = 0x50;
mus_name_offset = 0x30;
/* 0x08: buffer size of the pre-defined .mus filename? (always 0x20)
* 0x20: mpf version number? (always 0x05)
* 0x24: offset to a chunk of plaintext data w/ event and node info & names
* 0x2C: some hash?
* 0x30: intended .mus filename */
read_u32 = guess_read_u32(0x08, sf);
/* extra checks to fail faster before streamfile'ing */
if (read_u32(0x08, sf) != 0x20)
if (read_u64le(0x00, sf) != 0)
return NULL;
if (read_u32(0x20, sf) != 0x05)
header_offset = read_u32(0x08, sf);
if (header_offset != 0x20)
return NULL;
if (read_u32(header_offset, sf) != 0x05) /* version */
return NULL;
mpf_offset = header_offset + 0x30;
/* Version 0x05:
* 0x04: plaintext events/parts/defines offset (+ mpf offset)
* 0x08: always 0?
* 0x0C: some hash?
* 0x10: intended .mus filename
* 0x30: PFDx data
*/
mus_name_offset = header_offset + 0x10;
/* not exactly the same as mpf size since it's aligned, but correct size is only needed for v3 */
info_offset = read_u32(0x24, sf); //+ header_size;
mpf_size = read_u32(header_offset + 0x04, sf);
/* TODO: it should be theoretically possible to use the numparts section
* in the plaintext chunk to get valid stream names using its entry node
* indices by checking if they're within range of the current subsong */
read_string(mus_name, sizeof(mus_name), mus_name_offset, sf);
sf_mpf = open_wrap_streamfile(sf);
sf_mpf = open_clamp_streamfile(sf_mpf, header_size, info_offset);
sf_mpf = open_clamp_streamfile(sf_mpf, mpf_offset, mpf_size);
if (!sf_mpf) goto fail;
vgmstream = init_vgmstream_ea_mpf_mus_schl_main(sf_mpf, mus_name);

View File

@ -18,8 +18,8 @@ VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf) {
/* no clear header id, but this is how they all start */
/* the 0x02s are likely channels and codec (DSPADPCM) */
if (read_u32be(0x00, sf) != 0x00 &&
read_u32be(0x04, sf) != 0x02 &&
if (read_u32be(0x00, sf) != 0x00 ||
read_u32be(0x04, sf) != 0x02 ||
read_u32be(0x08, sf) != 0x02)
return NULL;
@ -44,8 +44,7 @@ VGMSTREAM* init_vgmstream_dsp_asura_sfx(STREAMFILE* sf) {
loop_flag = 0;
/* more safety checks */
if (interleave < 0 ||
interleave < nibble_count / 2 ||
if (interleave < 0 || interleave < nibble_count / 2 ||
interleave > get_streamfile_size(sf) / channels)
goto fail;

View File

@ -1580,9 +1580,10 @@ VGMSTREAM* init_vgmstream_dsp_asura(STREAMFILE* sf) {
uint8_t flag;
/* checks */
if (!is_id32be(0x00, sf, "DSP\x00") && /* GC */
!is_id32be(0x00, sf, "DSP\x01") && /* GC/Wii/WiiU */
!is_id32be(0x00, sf, "DSP\x02")) /* WiiU */
/* "DSP\x00" (GC), "DSP\x01" (GC/Wii/WiiU), "DSP\x02" (WiiU) */
if ((read_u32be(0x00, sf) & 0xFFFFFF00) != get_id32be("DSP\0"))
return NULL;
if (read_u8(0x03, sf) < 0x00 || read_u8(0x03, sf) > 0x02)
return NULL;
/* .dsp: Judge Dredd (GC)
@ -1590,7 +1591,7 @@ VGMSTREAM* init_vgmstream_dsp_asura(STREAMFILE* sf) {
if (!check_extensions(sf, "dsp,wav,lwav"))
return NULL;
/* flag set to 0x00 so far only seen in Judge Dredd, which also uses 0x01
/* flag set to 0x00 so far only seen in Judge Dredd, which also uses 0x01.
* at first assumed being 0 means it has a stream name at 0x48 (unlikely) */
/* flag set to 0x02 means it's ddsp-like stereo */
flag = read_u8(0x03, sf);