mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-22 13:20:16 +01:00
Fix some .mul [Tomb Raider 2013 (PS4)]
This commit is contained in:
parent
e5d89222ab
commit
86be2b74ad
@ -1,6 +1,7 @@
|
|||||||
#include "meta.h"
|
#include "meta.h"
|
||||||
#include "../layout/layout.h"
|
#include "../layout/layout.h"
|
||||||
#include "../coding/coding.h"
|
#include "../coding/coding.h"
|
||||||
|
#include "../util/endianness.h"
|
||||||
#include "mul_streamfile.h"
|
#include "mul_streamfile.h"
|
||||||
|
|
||||||
typedef enum { PSX, DSP, IMA, XMA1, FSB4 } mul_codec;
|
typedef enum { PSX, DSP, IMA, XMA1, FSB4 } mul_codec;
|
||||||
@ -16,15 +17,15 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) {
|
|||||||
int loop_flag, channel_count, sample_rate, num_samples, loop_start;
|
int loop_flag, channel_count, sample_rate, num_samples, loop_start;
|
||||||
int big_endian;
|
int big_endian;
|
||||||
mul_codec codec;
|
mul_codec codec;
|
||||||
uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL;
|
read_u32_t read_u32;
|
||||||
|
read_f32_t read_f32;
|
||||||
|
|
||||||
|
|
||||||
/* checks */
|
/* checks */
|
||||||
/* .mul: found in the exe, used by the bigfile extractor (Gibbed.TombRaider)
|
/* .mul: found in the exe/reversed names, used by the bigfile extractor (Gibbed.TombRaider)
|
||||||
* (some files have companion .mus/sam files but seem to be sequences/control stuff)
|
* (some files have companion .mus/sam files but seem to be sequences/control stuff)
|
||||||
* .(extensionless): filenames as found in the bigfile
|
|
||||||
* .emff: fake extension ('Eidos Music File Format') */
|
* .emff: fake extension ('Eidos Music File Format') */
|
||||||
if (!check_extensions(sf, "mul,,emff"))
|
if (!check_extensions(sf, "mul,emff"))
|
||||||
goto fail;
|
goto fail;
|
||||||
if (read_u32be(0x10,sf) != 0 ||
|
if (read_u32be(0x10,sf) != 0 ||
|
||||||
read_u32be(0x14,sf) != 0 ||
|
read_u32be(0x14,sf) != 0 ||
|
||||||
@ -34,6 +35,7 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) {
|
|||||||
|
|
||||||
big_endian = guess_endianness32bit(0x00, sf);
|
big_endian = guess_endianness32bit(0x00, sf);
|
||||||
read_u32 = big_endian ? read_u32be : read_u32le;
|
read_u32 = big_endian ? read_u32be : read_u32le;
|
||||||
|
read_f32 = big_endian ? read_f32be : read_f32le;
|
||||||
|
|
||||||
sample_rate = read_u32(0x00,sf);
|
sample_rate = read_u32(0x00,sf);
|
||||||
loop_start = read_u32(0x04,sf);
|
loop_start = read_u32(0x04,sf);
|
||||||
@ -46,13 +48,15 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) {
|
|||||||
/* 0x28: loop offset within audio data (not file offset) */
|
/* 0x28: loop offset within audio data (not file offset) */
|
||||||
/* 0x2c: some value related to loop? */
|
/* 0x2c: some value related to loop? */
|
||||||
/* 0x34: id? */
|
/* 0x34: id? */
|
||||||
/* 0x38+: channel config until ~0x100? (multiple 0x3F800000 / 1.0f depending on the number of channels) */
|
/* 0x38+: channel config until ~0x100? (multiple 1.0f depending on the number of channels) */
|
||||||
|
|
||||||
/* test known "version" (some float) later versions start from 0x24 instead of 0x20 */
|
/* extra tests just in case (1.0=common, varies but goes around ~2800.0) */
|
||||||
if (!(read_u32(0x38,sf) == 0x3F800000 || /* common */
|
{
|
||||||
read_u32(0x38,sf) == 0x4530F000 || /* Avengers */
|
float check1 = read_f32(0x38,sf);
|
||||||
read_u32(0x3c,sf) == 0x3F800000)) /* Tomb Raider Underworld */
|
float check2 = read_f32(0x3c,sf);
|
||||||
|
if (!(check1 >= 1.0 && check1 <= 3000.0) && check2 != 1.0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
loop_flag = (loop_start >= 0); /* 0xFFFFFFFF when not looping */
|
loop_flag = (loop_start >= 0); /* 0xFFFFFFFF when not looping */
|
||||||
|
|
||||||
@ -115,13 +119,20 @@ fail:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* find first block with header info (probably hardcoded) */
|
||||||
static off_t get_start_offset(STREAMFILE* sf) {
|
static off_t get_start_offset(STREAMFILE* sf) {
|
||||||
|
uint32_t test1, test2;
|
||||||
|
|
||||||
/* find first block with header info */
|
/* earlier games */
|
||||||
if (read_u32be(0x0800,sf) != 0 || read_u32be(0x0804,sf) != 0) /* earlier games */
|
test1 = read_u32be(0x0800,sf);
|
||||||
|
test2 = read_u32be(0x0804,sf);
|
||||||
|
if ((test1 != 0 && test1 != 0xFFFFFFFF) || (test2 != 0 && test2 != 0xFFFFFFFF))
|
||||||
return 0x800;
|
return 0x800;
|
||||||
|
|
||||||
if (read_u32be(0x2000,sf) != 0 || read_u32be(0x2004,sf) != 0) /* later games */
|
/* later games */
|
||||||
|
test1 = read_u32be(0x2000,sf);
|
||||||
|
test2 = read_u32be(0x2004,sf);
|
||||||
|
if ((test1 != 0 && test1 != 0xFFFFFFFF) || (test2 != 0 && test2 != 0xFFFFFFFF))
|
||||||
return 0x2000;
|
return 0x2000;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -167,13 +178,16 @@ static int guess_codec(STREAMFILE* sf, off_t start_offset, int big_endian, int c
|
|||||||
uint32_t block_size = read_u32(offset+0x04, sf);
|
uint32_t block_size = read_u32(offset+0x04, sf);
|
||||||
uint32_t data_size = read_u32(offset+0x10, sf);
|
uint32_t data_size = read_u32(offset+0x10, sf);
|
||||||
|
|
||||||
|
if (block_type == 0xFFFFFFFF || block_size == 0xFFFFFFFF || data_size == 0xFFFFFFFF)
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (block_type != 0x00) {
|
if (block_type != 0x00) {
|
||||||
offset += 0x10 + block_size;
|
offset += 0x10 + block_size;
|
||||||
continue; /* not audio */
|
continue; /* not audio */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* test FSB4 header */
|
/* test FSB4 header */
|
||||||
if (read_u32be(offset + 0x10, sf) == 0x46534234 || read_u32be(offset + 0x20, sf) == 0x46534234) {
|
if (is_id32be(offset + 0x10, sf, "FSB4") || is_id32be(offset + 0x20, sf, "FSB4")) {
|
||||||
*p_codec = FSB4;
|
*p_codec = FSB4;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user