Updated VGMStream to r1640-104-gc92e4f85
parent
3aa2e3149f
commit
ac998301c6
|
@ -518,6 +518,8 @@
|
|||
839933612591E8C1001855AF /* sbk.c in Sources */ = {isa = PBXBuildFile; fileRef = 8399335E2591E8C0001855AF /* sbk.c */; };
|
||||
83997F5B22D9569E00633184 /* rad.c in Sources */ = {isa = PBXBuildFile; fileRef = 83997F5722D9569E00633184 /* rad.c */; };
|
||||
839B54521EEE1D9600048A2D /* ngc_ulw.c in Sources */ = {isa = PBXBuildFile; fileRef = 831BD11F1EEE1CF200198540 /* ngc_ulw.c */; };
|
||||
839C3D27270D49FF00E13653 /* lpcm_fb.c in Sources */ = {isa = PBXBuildFile; fileRef = 839C3D22270D49FF00E13653 /* lpcm_fb.c */; };
|
||||
839C3D28270D49FF00E13653 /* lopu.c in Sources */ = {isa = PBXBuildFile; fileRef = 839C3D26270D49FF00E13653 /* lopu.c */; };
|
||||
839E21E01F2EDAF100EE54D7 /* vorbis_custom_data_fsb.h in Headers */ = {isa = PBXBuildFile; fileRef = 839E21D61F2EDAF000EE54D7 /* vorbis_custom_data_fsb.h */; };
|
||||
839E21E11F2EDAF100EE54D7 /* vorbis_custom_decoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21D71F2EDAF000EE54D7 /* vorbis_custom_decoder.c */; };
|
||||
839E21E21F2EDAF100EE54D7 /* vorbis_custom_utils_wwise.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21D81F2EDAF000EE54D7 /* vorbis_custom_utils_wwise.c */; };
|
||||
|
@ -1328,6 +1330,8 @@
|
|||
8399335D2591E8C0001855AF /* ubi_sb_garbage_streamfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ubi_sb_garbage_streamfile.h; sourceTree = "<group>"; };
|
||||
8399335E2591E8C0001855AF /* sbk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sbk.c; sourceTree = "<group>"; };
|
||||
83997F5722D9569E00633184 /* rad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rad.c; sourceTree = "<group>"; };
|
||||
839C3D22270D49FF00E13653 /* lpcm_fb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lpcm_fb.c; sourceTree = "<group>"; };
|
||||
839C3D26270D49FF00E13653 /* lopu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lopu.c; sourceTree = "<group>"; };
|
||||
839E21D61F2EDAF000EE54D7 /* vorbis_custom_data_fsb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vorbis_custom_data_fsb.h; sourceTree = "<group>"; };
|
||||
839E21D71F2EDAF000EE54D7 /* vorbis_custom_decoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_decoder.c; sourceTree = "<group>"; };
|
||||
839E21D81F2EDAF000EE54D7 /* vorbis_custom_utils_wwise.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_wwise.c; sourceTree = "<group>"; };
|
||||
|
@ -1945,6 +1949,8 @@
|
|||
83D20074248DDB760048BD24 /* ktsr.c */,
|
||||
830EBE122004656E0023AA10 /* ktss.c */,
|
||||
8373342423F60CDB00DE14DC /* kwb.c */,
|
||||
839C3D26270D49FF00E13653 /* lopu.c */,
|
||||
839C3D22270D49FF00E13653 /* lpcm_fb.c */,
|
||||
8373341F23F60CDB00DE14DC /* lrmd_streamfile.h */,
|
||||
8373342223F60CDB00DE14DC /* lrmd.c */,
|
||||
836F6E5A18BDC2180095E648 /* lsf.c */,
|
||||
|
@ -2656,6 +2662,7 @@
|
|||
834FE109215C79ED000A5D3D /* idsp_ie.c in Sources */,
|
||||
83299FD01E7660C7003A3242 /* bik.c in Sources */,
|
||||
8346D97C25BF838C00D1A8B0 /* mjb_mjh.c in Sources */,
|
||||
839C3D27270D49FF00E13653 /* lpcm_fb.c in Sources */,
|
||||
8373341823F60C7B00DE14DC /* tgcadpcm_decoder.c in Sources */,
|
||||
83FC417326D3304D009A2022 /* xsh_xsd_xss.c in Sources */,
|
||||
836F6F3318BDC2190095E648 /* ngc_dtk_decoder.c in Sources */,
|
||||
|
@ -2756,6 +2763,7 @@
|
|||
83AA7F812519C042004C5298 /* silence.c in Sources */,
|
||||
834FE0B3215C798C000A5D3D /* acm_decoder_util.c in Sources */,
|
||||
837CEA7A23487E2500E62A4A /* ffmpeg_decoder_utils.c in Sources */,
|
||||
839C3D28270D49FF00E13653 /* lopu.c in Sources */,
|
||||
837CEAF823487F2C00E62A4A /* xmv_valve.c in Sources */,
|
||||
836F6F6718BDC2190095E648 /* acm.c in Sources */,
|
||||
834FE0FD215C79ED000A5D3D /* vpk.c in Sources */,
|
||||
|
|
|
@ -404,9 +404,9 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
|
|||
VGM_ASSERT(stream->codecpar->trailing_padding > 0, "FFMPEG: trailing_padding %i\n", (int)stream->codecpar->trailing_padding);
|
||||
VGM_ASSERT(stream->codecpar->seek_preroll > 0, "FFMPEG: seek_preroll %i\n", (int)stream->codecpar->seek_preroll);//seek delay: OPUS
|
||||
VGM_ASSERT(stream->start_time > 0, "FFMPEG: start_time %i\n", (int)stream->start_time); //delay
|
||||
#if 0 //LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
|
||||
VGM_ASSERT(stream->first_discard_sample > 0, "FFMPEG: first_discard_sample %i\n", (int)stream->first_discard_sample); //padding: MP3
|
||||
VGM_ASSERT(stream->last_discard_sample > 0, "FFMPEG: last_discard_sample %i\n", (int)stream->last_discard_sample); //padding: MP3
|
||||
#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 64, 100)
|
||||
VGM_ASSERT(stream->skip_samples > 0, "FFMPEG: skip_samples %i\n", (int)stream->skip_samples); //delay: MP4
|
||||
VGM_ASSERT(stream->start_skip_samples > 0, "FFMPEG: start_skip_samples %i\n", (int)stream->start_skip_samples); //delay: MP3
|
||||
#endif
|
||||
|
|
|
@ -349,7 +349,7 @@ static STREAMFILE* setup_opus_streamfile(STREAMFILE* sf, opus_config* cfg, off_t
|
|||
/* setup subfile */
|
||||
new_sf = open_wrap_streamfile(sf);
|
||||
new_sf = open_io_streamfile_ex_f(new_sf, &io_data, sizeof(opus_io_data), opus_io_read, opus_io_size, opus_io_init, opus_io_close);
|
||||
new_sf = open_buffer_streamfile_f(new_sf, 0);
|
||||
//new_sf = open_buffer_streamfile_f(new_sf, 0); /* seems slightly slower on typical files */
|
||||
return new_sf;
|
||||
fail:
|
||||
return NULL;
|
||||
|
|
|
@ -266,6 +266,7 @@ static const char* extension_list[] = {
|
|||
"l",
|
||||
"l00", //txth/reserved [Disney's Dinosaur (PS2)]
|
||||
"laac", //fake extension for .aac (tri-Ace)
|
||||
"ladpcm", //not fake
|
||||
"laif", //fake extension for .aif (various)
|
||||
"laiff", //fake extension for .aiff
|
||||
"laifc", //fake extension for .aifc
|
||||
|
@ -289,7 +290,7 @@ static const char* extension_list[] = {
|
|||
"lmp4", //fake extension for .mp4
|
||||
"lmpc", //fake extension for .mpc, FFmpeg/not parsed
|
||||
"logg", //fake extension for .ogg
|
||||
"lopus", //fake extension for .opus
|
||||
"lopus", //fake extension for .opus, used by LOPU too
|
||||
"lp",
|
||||
"lpcm",
|
||||
"lpk",
|
||||
|
@ -1364,6 +1365,8 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_BNK_RELIC, "Relic BNK header"},
|
||||
{meta_XSH_XSD_XSS, "Treyarch XSH+XSD/XSS header"},
|
||||
{meta_PSB, "M2 PSB header"},
|
||||
{meta_LOPU_FB, "French-Bread LOPU header"},
|
||||
{meta_LPCM_FB, "French-Bread LPCM header"},
|
||||
};
|
||||
|
||||
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "../coding/coding.h"
|
||||
#include "../coding/hca_decoder_clhca.h"
|
||||
|
||||
//#define HCA_BRUTEFORCE
|
||||
#define HCA_BRUTEFORCE
|
||||
#ifdef HCA_BRUTEFORCE
|
||||
static void bruteforce_hca_key(STREAMFILE* sf, hca_codec_data* hca_data, unsigned long long* p_keycode, uint16_t subkey);
|
||||
#endif
|
||||
|
@ -22,12 +22,12 @@ VGMSTREAM* init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) {
|
|||
|
||||
|
||||
/* checks */
|
||||
if ((read_u32be(0x00,sf) & 0x7F7F7F7F) != get_id32be("HCA\0")) /* masked in encrypted files */
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "hca"))
|
||||
return NULL;
|
||||
|
||||
if ((read_u32be(0x00,sf) & 0x7F7F7F7F) != 0x48434100) /* "HCA\0", possibly masked */
|
||||
goto fail;
|
||||
|
||||
/* init vgmstream and library's context, will validate the HCA */
|
||||
hca_data = init_hca(sf);
|
||||
if (!hca_data) {
|
||||
|
@ -212,15 +212,15 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data
|
|||
off_t keys_size, bytes;
|
||||
int pos;
|
||||
uint64_t old_key = 0;
|
||||
uint64_t key = 0;
|
||||
|
||||
|
||||
VGM_LOG("HCA: test keys.bin (type %i)\n", type);
|
||||
|
||||
*p_keycode = 0;
|
||||
|
||||
/* load whole file in memory for performance (exes with keys shouldn't be too big) */
|
||||
sf_keys = open_streamfile_by_filename(sf, "keys.bin");
|
||||
if (!sf_keys) goto done;
|
||||
if (!sf_keys) return;
|
||||
|
||||
VGM_LOG("HCA: test keys.bin (type %i)\n", type);
|
||||
*p_keycode = 0;
|
||||
|
||||
keys_size = get_streamfile_size(sf_keys);
|
||||
|
||||
|
@ -234,7 +234,6 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data
|
|||
|
||||
pos = 0;
|
||||
while (pos < keys_size - 4) {
|
||||
uint64_t key;
|
||||
VGM_ASSERT(pos % 0x1000000 == 0, "HCA: pos %x...\n", pos);
|
||||
|
||||
/* keys are usually u64le but other orders may exist */
|
||||
|
@ -256,8 +255,10 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data
|
|||
|
||||
cur_score = 0;
|
||||
test_key(hca_data, key, subkey, &cur_score, p_keycode);
|
||||
if (cur_score == 1)
|
||||
if (cur_score == 1) {
|
||||
best_score = cur_score;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cur_score > 0 && cur_score <= 500) {
|
||||
VGM_LOG("HCA: possible key=%08x%08x (score=%i) at %x\n",
|
||||
|
@ -268,25 +269,32 @@ static void bruteforce_hca_key_bin_type(STREAMFILE* sf, hca_codec_data* hca_data
|
|||
}
|
||||
|
||||
done:
|
||||
VGM_ASSERT(best_score > 0, "HCA: best key=%08x%08x (score=%i)\n",
|
||||
(uint32_t)((*p_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(*p_keycode & 0xFFFFFFFF), best_score);
|
||||
VGM_ASSERT(best_score < 0, "HCA: key not found\n");
|
||||
if (best_score < 0 || best_score > 10000)
|
||||
if (best_score < 0 || best_score > 10000) {
|
||||
*p_keycode = 0;
|
||||
VGM_LOG("HCA: good key not found\n");
|
||||
}
|
||||
else {
|
||||
/* print key as p_keycode includes subkey */
|
||||
VGM_LOG("HCA: best key=%08x%08x (score=%i)\n",
|
||||
(uint32_t)((key >> 32) & 0xFFFFFFFF), (uint32_t)(key & 0xFFFFFFFF), best_score);
|
||||
}
|
||||
|
||||
close_streamfile(sf_keys);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
static void bruteforce_hca_key_bin(STREAMFILE* sf, hca_codec_data* hca_data, unsigned long long* p_keycode, uint16_t subkey) {
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64LE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64BE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32LE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32BE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64LE_1);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64BE_1);
|
||||
/*
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32LE_1);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64BE_1);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32BE_1);
|
||||
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64LE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32LE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_64BE_4);
|
||||
bruteforce_hca_key_bin_type(sf, hca_data, p_keycode, subkey, HBF_TYPE_32BE_4);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -303,13 +311,13 @@ static void bruteforce_hca_key_txt(STREAMFILE* sf, hca_codec_data* hca_data, uns
|
|||
char line[1024];
|
||||
|
||||
|
||||
VGM_LOG("HCA: test keys.txt\n");
|
||||
|
||||
*p_keycode = 0;
|
||||
|
||||
/* load whole file in memory for performance (exes with keys shouldn't be too big) */
|
||||
sf_keys = open_streamfile_by_filename(sf, "keys.txt");
|
||||
if (!sf_keys) goto done;
|
||||
if (!sf_keys) return;
|
||||
|
||||
VGM_LOG("HCA: test keys.txt\n");
|
||||
*p_keycode = 0;
|
||||
|
||||
keys_size = get_streamfile_size(sf_keys);
|
||||
|
||||
|
|
|
@ -758,9 +758,24 @@ static const hcakey_info hcakey_list[] = {
|
|||
|
||||
// m HOLD'EM (Android)
|
||||
{369211553984367}, // 00014FCBC385AF6F
|
||||
|
||||
|
||||
// Sonic Colors Ultimate (multi)
|
||||
{1991062320101111}, // 000712DC5250B6F7
|
||||
|
||||
// ALTDEUS: Beyond Chronos (PC) [base-string 14238637353525924 + mods)]
|
||||
{14238637353525934}, // 003295F7198AE2AE - bgm
|
||||
{14238637353525954}, // 003295F7198AE2C2 - se
|
||||
{14238637353525944}, // 003295F7198AE2B8 - voice
|
||||
|
||||
// SHOW BY ROCK!! Fes A Live (Android)
|
||||
{54605542411982574}, // 00C1FF73963BD6EE
|
||||
|
||||
// Touhou Danmaku Kagura (Android)
|
||||
{5654863921795627}, // 001417119B4FD22B
|
||||
|
||||
// Nogizaka 46 Fractal (Android)
|
||||
{984635491346198130}, // 0DAA20C336EEAE72
|
||||
|
||||
};
|
||||
|
||||
#endif/*_HCA_KEYS_H_*/
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* LOPU - French-Bread's Opus [Melty Blood: Type Lumina (Switch)] */
|
||||
VGMSTREAM* init_vgmstream_lopu_fb(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t start_offset, data_size;
|
||||
int loop_flag, channels, sample_rate;
|
||||
int32_t num_samples, loop_start, loop_end, skip;
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "LOPU"))
|
||||
goto fail;
|
||||
|
||||
/* .lopus: real extension (honest) */
|
||||
if (!check_extensions(sf, "lopus"))
|
||||
goto fail;
|
||||
|
||||
start_offset = read_u32le(0x04, sf);
|
||||
sample_rate = read_s32le(0x08, sf);
|
||||
channels = read_s16le(0x0c, sf);
|
||||
/* 0x10: ? (1984) */
|
||||
num_samples = read_s32le(0x14, sf);
|
||||
loop_start = read_s32le(0x18, sf);
|
||||
loop_end = read_s32le(0x1c, sf) + 1;
|
||||
/* 0x20: frame size */
|
||||
skip = read_s16le(0x24, sf);
|
||||
data_size = read_u32le(0x28, sf);
|
||||
/* rest: null */
|
||||
|
||||
loop_flag = (loop_end > 0); /* -1 if no loop */
|
||||
num_samples -= skip;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_LOPU_FB;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
vgmstream->codec_data = init_ffmpeg_switch_opus(sf, start_offset, data_size, vgmstream->channels, skip, vgmstream->sample_rate);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
#else
|
||||
goto fail;
|
||||
#endif
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* LPCM - French-Bread's DSP [Melty Blood: Type Lumina (Switch)] */
|
||||
VGMSTREAM* init_vgmstream_lpcm_fb(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
uint32_t start_offset;
|
||||
int loop_flag, channels, sample_rate;
|
||||
int32_t num_samples;
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "LPCM"))
|
||||
goto fail;
|
||||
|
||||
/* .ladpcm: real extension (honest) */
|
||||
if (!check_extensions(sf, "ladpcm"))
|
||||
goto fail;
|
||||
|
||||
/* 0x04: dsp offset (0x20) */
|
||||
if (read_u32le(0x04, sf) != 0x20)
|
||||
goto fail;
|
||||
|
||||
num_samples = read_s32le(0x20, sf);
|
||||
/* 0x24: nibbles? */
|
||||
sample_rate = read_s32le(0x28, sf);
|
||||
/* 0x2c: 0? */
|
||||
/* 0x30: 2? */
|
||||
/* 0x34: nibbles? */
|
||||
/* 0x38: 2? */
|
||||
if (read_u32le(0x38, sf) != 2)
|
||||
goto fail;
|
||||
|
||||
channels = 1;
|
||||
loop_flag = 0;
|
||||
|
||||
start_offset = 0x78; /* could be 0x80 but this is closer to num_samples */
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_LPCM_FB;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
dsp_read_coefs_le(vgmstream, sf, 0x3c, 0);
|
||||
/* 0x5c: hist? */
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
|
@ -964,4 +964,8 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf);
|
|||
|
||||
VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_lopu_fb(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_lpcm_fb(STREAMFILE* sf);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
|
|
@ -25,16 +25,16 @@ VGMSTREAM* init_vgmstream_mp4_aac_ffmpeg(STREAMFILE* sf) {
|
|||
|
||||
|
||||
/* checks */
|
||||
/* .bin: Final Fantasy Dimensions (iOS), Final Fantasy V (iOS)
|
||||
* .msd: UNO (iOS) */
|
||||
if (!check_extensions(sf,"mp4,m4a,m4v,lmp4,bin,lbin,msd"))
|
||||
goto fail;
|
||||
|
||||
if ((read_u32be(0x00,sf) & 0xFFFFFF00) != 0) /* first atom BE size (usually ~0x18) */
|
||||
goto fail;
|
||||
if (!is_id32be(0x04,sf, "ftyp"))
|
||||
goto fail;
|
||||
|
||||
/* .bin: Final Fantasy Dimensions (iOS), Final Fantasy V (iOS)
|
||||
* .msd: UNO (iOS) */
|
||||
if (!check_extensions(sf,"mp4,m4a,m4v,lmp4,bin,lbin,msd"))
|
||||
goto fail;
|
||||
|
||||
file_size = get_streamfile_size(sf);
|
||||
|
||||
ffmpeg_data = init_ffmpeg_offset(sf, start_offset, file_size);
|
||||
|
@ -86,7 +86,7 @@ fail:
|
|||
|
||||
/* read useful MP4 chunks */
|
||||
static void parse_mp4(STREAMFILE* sf, mp4_header* mp4) {
|
||||
off_t offset, suboffset, max_offset, max_suboffset;
|
||||
uint32_t offset, suboffset, max_offset, max_suboffset;
|
||||
|
||||
|
||||
/* MOV format chunks, called "atoms", size goes first because Apple */
|
||||
|
@ -117,12 +117,25 @@ static void parse_mp4(STREAMFILE* sf, mp4_header* mp4) {
|
|||
mp4->loop_start = read_u32be(offset + 0x08 + 0x2c,sf);
|
||||
mp4->loop_end = read_u32be(offset + 0x08 + 0x30,sf);
|
||||
}
|
||||
/* could stop reading since FFmpeg will too */
|
||||
max_offset = 0;
|
||||
}
|
||||
/* M2 emu's .m4a (codename zoom) */
|
||||
else if (is_id32be(offset + 0x08 + 0x00,sf, "ZOOM")) {
|
||||
/* 0x00: id */
|
||||
mp4->encoder_delay = read_s32be(offset + 0x08 + 0x04,sf); /* Apple's 2112, also in iTunes tag */
|
||||
/* 0x08: end padding */
|
||||
mp4->num_samples = read_s32be(offset + 0x08 + 0x0c,sf);
|
||||
mp4->loop_start = read_s32be(offset + 0x08 + 0x10,sf);
|
||||
mp4->loop_end = read_s32be(offset + 0x08 + 0x14,sf);
|
||||
mp4->loop_flag = (mp4->loop_end != 0);
|
||||
if (mp4->loop_flag)
|
||||
mp4->loop_end++; /* assumed, matches num_samples this way */
|
||||
max_offset = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x6D6F6F76: { /* "moov" (header) */
|
||||
suboffset = offset += 0x08;
|
||||
suboffset = offset + 0x08;
|
||||
max_suboffset = offset + size;
|
||||
while (suboffset < max_suboffset) {
|
||||
uint32_t subsize = read_u32be(suboffset + 0x00,sf);
|
||||
|
@ -145,6 +158,7 @@ static void parse_mp4(STREAMFILE* sf, mp4_header* mp4) {
|
|||
mp4->num_samples = read_s32be(criw_offset + 0x0c,sf);
|
||||
mp4->loop_flag = (mp4->loop_end > 0);
|
||||
/* next 2 fields are null */
|
||||
max_offset = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -200,9 +200,19 @@ static int get_loops_gameexe_ini(STREAMFILE* sf, int* p_loop_flag, int32_t* p_lo
|
|||
length = ext-1-namebase;
|
||||
file_size = get_streamfile_size(sf_loop);
|
||||
|
||||
/* format of line is:
|
||||
* #DSTRACK = 00000000 - eeeeeeee - ssssssss = "name" = "name2?"
|
||||
* ^22 ^33 ^45 ^57
|
||||
/* According to the official documentation of RealLiveMax (the public version of RealLive), format of line is:
|
||||
* #DSTRACK = 00000000 - eeeeeeee - ssssssss = "filename" = "alias for game script"
|
||||
* ^22 ^33 ^45 ^57?
|
||||
*
|
||||
* Original text from the documentation (written in Japanese) is:
|
||||
* ; ■BGMの登録:DirectSound
|
||||
* ;(※必要ない場合は登録しないで下さい。)
|
||||
* ; 終了位置の設定が 99999999 なら最後まで演奏します。
|
||||
* ; ※設定値はサンプル数で指定して下さい。(旧システムではバイト指定でしたので注意してください。)
|
||||
* ;=========================================================================================================
|
||||
* ; 開始位置 - 終了位置 - リピート = ファイル名 = 登録名
|
||||
* #DSTRACK = 00000000 - 01896330 - 00088270 = "b_manuke" = "b_manuke"
|
||||
* #DSTRACK = 00000000 - 01918487 - 00132385 = "c_happy" = "c_happy"
|
||||
*/
|
||||
|
||||
for (found = 0, offset = 0; !found && offset<file_size; offset++) {
|
||||
|
|
|
@ -51,6 +51,7 @@ typedef struct {
|
|||
int loop_flag;
|
||||
int32_t loop_start;
|
||||
int32_t loop_end;
|
||||
int duration_test;
|
||||
|
||||
} psb_header_t;
|
||||
|
||||
|
@ -153,6 +154,9 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
|
|||
case 24: vgmstream->coding_type = coding_PCM24LE; break; /* Legend of Mana (PC) */
|
||||
default: goto fail;
|
||||
}
|
||||
|
||||
if (psb.duration_test && psb.loop_start + psb.loop_end < vgmstream->num_samples)
|
||||
vgmstream->loop_end_sample += psb.loop_start;
|
||||
break;
|
||||
|
||||
case MSADPCM: /* [Senxin Aleste (AC)] */
|
||||
|
@ -218,6 +222,8 @@ VGMSTREAM* init_vgmstream_psb(STREAMFILE* sf) {
|
|||
}
|
||||
|
||||
vgmstream->num_samples = read_u32le(psb.stream_offset[0] + 0x00, sf);
|
||||
if (psb.duration_test && psb.loop_start + psb.loop_end < vgmstream->num_samples)
|
||||
vgmstream->loop_end_sample += psb.loop_start;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -592,7 +598,9 @@ static int parse_psb_channels(psb_header_t* psb, psb_node_t* nchans) {
|
|||
psb->loop_start = psb_node_get_result(&nsub).num;
|
||||
|
||||
psb_node_by_index(&node, 1, &nsub);
|
||||
psb->loop_end = psb_node_get_result(&nsub).num + psb->loop_start; /* duration */
|
||||
psb->loop_end = psb_node_get_result(&nsub).num + 1; /* assumed, matches num_samples */
|
||||
/* duration [LoM (PC), Namco Museum V1 (PC)] or standard [G-Darius (Sw)] (no apparent flags) */
|
||||
psb->duration_test = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -527,6 +527,8 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||
init_vgmstream_bnk_relic,
|
||||
init_vgmstream_xsh_xsd_xss,
|
||||
init_vgmstream_psb,
|
||||
init_vgmstream_lopu_fb,
|
||||
init_vgmstream_lpcm_fb,
|
||||
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
|
||||
|
|
|
@ -756,6 +756,8 @@ typedef enum {
|
|||
meta_BNK_RELIC,
|
||||
meta_XSH_XSD_XSS,
|
||||
meta_PSB,
|
||||
meta_LOPU_FB,
|
||||
meta_LPCM_FB,
|
||||
|
||||
} meta_t;
|
||||
|
||||
|
|
Loading…
Reference in New Issue