Updated VGMStream to r1667-99-g1355279f

CQTexperiment
Christopher Snowhill 2021-11-17 21:11:40 -08:00
parent 58384cb831
commit d8dcb75ec6
22 changed files with 646 additions and 650 deletions

View File

@ -417,7 +417,7 @@
836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; };
836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.c */; };
836F703018BDC2190095E648 /* sqex_scd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF418BDC2190095E648 /* sqex_scd.c */; };
836F703218BDC2190095E648 /* str_asr.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* str_asr.c */; };
836F703218BDC2190095E648 /* knon.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF618BDC2190095E648 /* knon.c */; };
836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; };
836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.c */; };
@ -1232,7 +1232,7 @@
836F6EF218BDC2190095E648 /* sli.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sli.c; sourceTree = "<group>"; };
836F6EF318BDC2190095E648 /* spt_spd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spt_spd.c; sourceTree = "<group>"; };
836F6EF418BDC2190095E648 /* sqex_scd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sqex_scd.c; sourceTree = "<group>"; };
836F6EF618BDC2190095E648 /* str_asr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_asr.c; sourceTree = "<group>"; };
836F6EF618BDC2190095E648 /* knon.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = knon.c; sourceTree = "<group>"; };
836F6EF718BDC2190095E648 /* str_snds.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = str_snds.c; sourceTree = "<group>"; };
836F6EF918BDC2190095E648 /* svs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = svs.c; sourceTree = "<group>"; };
836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = "<group>"; };
@ -1950,6 +1950,7 @@
83D20075248DDB760048BD24 /* kat.c */,
834FE0C3215C79E6000A5D3D /* kma9_streamfile.h */,
83A21F83201D8981000F04B9 /* kma9.c */,
836F6EF618BDC2190095E648 /* knon.c */,
836F6E5918BDC2180095E648 /* kraw.c */,
8346D97625BF838C00D1A8B0 /* ktac.c */,
83AA7F792519C042004C5298 /* ktsc.c */,
@ -2154,7 +2155,6 @@
8317C24826982CC1007DD0B8 /* sspr.c */,
8306B0C12098458C000302D4 /* sthd.c */,
83AA5D231F6E2F9C0020821C /* stm.c */,
836F6EF618BDC2190095E648 /* str_asr.c */,
836F6EF718BDC2190095E648 /* str_snds.c */,
834FE0C2215C79E6000A5D3D /* str_wav.c */,
83C7280722BC893B00678B4A /* strm_abylight.c */,
@ -2634,7 +2634,7 @@
836F702018BDC2190095E648 /* rkv.c in Sources */,
834FE0F4215C79ED000A5D3D /* wsi.c in Sources */,
83D26A7A26E66D98001A9475 /* adp_bos.c in Sources */,
836F703218BDC2190095E648 /* str_asr.c in Sources */,
836F703218BDC2190095E648 /* knon.c in Sources */,
837CEB0223487F2C00E62A4A /* raw_int.c in Sources */,
836F702818BDC2190095E648 /* sat_dvi.c in Sources */,
832BF82D21E0514B006F50F1 /* nus3audio.c in Sources */,

View File

@ -49,7 +49,7 @@
#define HCA_VERSION_V102 0x0102 /* V1.2+ [Gekka Ryouran Romance (PSP)] */
#define HCA_VERSION_V103 0x0103 /* V1.4+ [Phantasy Star Online 2 (PC), Binary Domain (PS3)] */
#define HCA_VERSION_V200 0x0200 /* V2.0+ [Yakuza 5 (PS3)] */
#define HCA_VERSION_V300 0x0300 /* V3.0+ [Uma Musume (Android)] */
#define HCA_VERSION_V300 0x0300 /* V3.0+ [Uma Musume (Android), Megaton Musashi (Switch)-sfx-hfrgroups] */
/* maxs depend on encoder quality settings (for example, stereo has:
* highest=0x400, high=0x2AA, medium=0x200, low=0x155, lowest=0x100) */
@ -966,8 +966,6 @@ int clHCA_DecodeHeader(clHCA* hca, const void *data, unsigned int size) {
//TODO: should work but untested
if (hca->ms_stereo)
return HCA_ERROR_HEADER;
if (hca->hfr_group_count > 0 && hca->version == HCA_VERSION_V300)
return HCA_ERROR_HEADER;
/* clHCA is correctly initialized and decoder state reset
* (keycode is not changed between calls) */

View File

@ -410,6 +410,7 @@ static const char* extension_list[] = {
"ras",
"raw", //txth/reserved [Madden NHL 97 (PC)-pcm8u]
"rda", //FFmpeg/reserved [Rhythm Destruction (PC)]
"res", //txth/reserved [Spider-Man: Web of Shadows (PSP)]
"rkv",
"rnd",
"rof",
@ -1073,7 +1074,7 @@ static const meta_info meta_info_list[] = {
{meta_UBI_JADE, "Ubisoft Jade RIFF header"},
{meta_SEG, "Stormfront SEG header"},
{meta_NDS_STRM_FFTA2, "Final Fantasy Tactics A2 RIFF Header"},
{meta_STR_ASR, "Donkey Kong Jet Race KNON/WII Header"},
{meta_KNON, "Paon KNON header"},
{meta_ZWDSP, "Zack and Wiki custom DSP Header"},
{meta_GCA, "GCA DSP Header"},
{meta_SPT_SPD, "SPT+SPD DSP Header"},
@ -1095,7 +1096,7 @@ static const meta_info meta_info_list[] = {
{meta_RSTM_shrunken, "Nintendo RSTM header, corrupted by Atlus"},
{meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"},
{meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"},
{meta_SAT_BAKA, "BAKA header from Crypt Killer"},
{meta_SAT_BAKA, "Konami BAKA header"},
{meta_SWAV, "Nintendo SWAV header"},
{meta_VSF, "Square-Enix VSF header"},
{meta_NDS_RRDS, "Ridger Racer DS Header"},

View File

@ -8,6 +8,10 @@
#include "../coding/coding.h"
#ifdef VGM_DEBUG_OUTPUT
//#define ADX_BRUTEFORCE
#endif
#define ADX_KEY_MAX_TEST_FRAMES 32768
#define ADX_KEY_TEST_BUFFER_SIZE 0x8000
@ -295,23 +299,19 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
return 1;
}
else if (type == 8 && is_ascii) {
const char * keystring = (const char *)keybuf;
const char* keystring = (const char*)keybuf;
derive_adx_key8(keystring, xor_start, xor_mult, xor_add);
return 1;
}
else if (type == 9 && key_size == 0x08) {
uint64_t keycode = get_u64be(keybuf);
if (subkey) {
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
derive_adx_key9(keycode, xor_start, xor_mult, xor_add);
derive_adx_key9(keycode, subkey, xor_start, xor_mult, xor_add);
return 1;
}
else if (type == 9 && key_size == 0x08+0x02) {
uint64_t file_key = get_u64be(keybuf+0x00);
uint16_t file_sub = get_u16be(keybuf+0x08);
uint64_t keycode = file_key * ( ((uint64_t)file_sub << 16u) | ((uint16_t)~file_sub + 2u) );
derive_adx_key9(keycode, xor_start, xor_mult, xor_add);
uint64_t file_keycode = get_u64be(keybuf+0x00);
uint16_t file_subkey = get_u16be(keybuf+0x08);
derive_adx_key9(file_keycode, file_subkey, xor_start, xor_mult, xor_add);
return 1;
}
}
@ -414,11 +414,34 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
keymask = 0x1000;
}
#ifdef ADX_BRUTEFORCE
STREAMFILE* sf_keys = open_streamfile_by_filename(sf, "keys.bin");
uint8_t* buf = NULL;
uint64_t keycode = 0;
if (sf_keys) {
size_t keys_size = get_streamfile_size(sf_keys);
buf = malloc(keys_size);
read_streamfile(buf, 0, keys_size, sf_keys);
keycount = keys_size - 0x08;
VGM_LOG("ADX BF: test keys.bin (type %i)\n", 0);
}
#endif
/* try all keys until one decrypts correctly vs expected scales */
for (key_id = 0; key_id < keycount; key_id++) {
uint16_t key_xor, key_mul, key_add;
uint16_t xor, mul, add;
#ifdef ADX_BRUTEFORCE
if (buf) {
keycode = get_u64be(buf + key_id);
derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add);
}
else
#endif
/* get pre-derived XOR values or derive if needed */
if (keys[key_id].start || keys[key_id].mult || keys[key_id].add) {
key_xor = keys[key_id].start;
@ -430,10 +453,7 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
}
else if (type == 9 && keys[key_id].key9) {
uint64_t keycode = keys[key_id].key9;
if (subkey) {
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
derive_adx_key9(keycode, &key_xor, &key_mul, &key_add);
derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add);
}
else {
VGM_LOG("ADX: incorrectly defined key id=%i\n", key_id);
@ -459,7 +479,7 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key8);
}
else if (type == 9 && keys[key_id].key9) {
derive_adx_key9(keys[key_id].key9, &test_xor, &test_mul, &test_add);
derive_adx_key9(keys[key_id].key9, subkey, &test_xor, &test_mul, &test_add);
VGM_LOG("key9: pre=%04x %04x %04x vs calc=%04x %04x %04x = %s (%"PRIu64")\n",
xor,mul,add, test_xor,test_mul,test_add,
xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key9);
@ -486,6 +506,10 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
if (i != bruteframe_count)
continue;
#ifdef ADX_BRUTEFORCE
VGM_LOG("ADX BF: good key at %x, %08x%08x\n", key_id, (uint32_t)(keycode>>32), (uint32_t)(keycode>>0));
#endif
/* all scales are valid, key is good */
*xor_start = key_xor;
*xor_mult = key_mul;
@ -493,6 +517,12 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
rc = 1;
break;
}
#ifdef ADX_BRUTEFORCE
close_streamfile(sf_keys);
free(buf);
#endif
}
done:

View File

@ -258,6 +258,9 @@ static const adxkey_info adxkey9_list[] = {
/* Sonic Colors Ultimate (multi) */
{0x0000,0x0000,0x0000, NULL,1991062320101111}, // 000712DC5250B6F7
/* Shin Megami Tensei V (Switch) */
{0x000c,0x13b5,0x1fdb, NULL,0}, // guessed with VGAudio (possible key: 613B4FEE / 1631277038)
};
static const int adxkey8_list_count = sizeof(adxkey8_list) / sizeof(adxkey8_list[0]);
@ -360,13 +363,17 @@ end:
}
static void derive_adx_key9(uint64_t key9, uint16_t * out_start, uint16_t * out_mult, uint16_t * out_add) {
static void derive_adx_key9(uint64_t key9, uint16_t subkey, uint16_t* p_start, uint16_t* p_mult, uint16_t* p_add) {
uint16_t start = 0, mult = 0, add = 0;
/* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */
if (key9 == 0)
goto end;
if (subkey) {
key9 = key9 * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
key9--;
start = (int)(((key9 >> 27) & 0x7fff));
mult = (int)(((key9 >> 12) & 0x7ffc) | 1);
@ -379,9 +386,9 @@ static void derive_adx_key9(uint64_t key9, uint16_t * out_start, uint16_t * out_
//mult |= add << 16;
end:
*out_start = start;
*out_mult = mult;
*out_add = add;
*p_start = start;
*p_mult = mult;
*p_add = add;
}
#endif/*_ADX_KEYS_H_*/

View File

@ -1,51 +1,49 @@
#include "meta.h"
#include "../coding/coding.h"
/* .DSF - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM * init_vgmstream_dsf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate;
size_t data_size;
/* checks */
if (!check_extensions(streamFile, "dsf"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4F434541 && /* "OCEA" */
read_32bitBE(0x00,streamFile) != 0x4E204453 && /* "N DS" */
read_32bitBE(0x00,streamFile) != 0x41000000) /* "A\0\0\0" */
goto fail;
/* 0x10(2): always 1? */
/* 0x12(4): total nibbles / 0x10? */
/* 0x16(4): always 0? */
start_offset = read_32bitLE(0x1a,streamFile);
sample_rate = read_32bitLE(0x1e,streamFile);
channel_count = read_32bitLE(0x22,streamFile) + 1;
data_size = get_streamfile_size(streamFile) - start_offset;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_DSF;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ((data_size / 0x08 / channel_count) * 14); /* bytes-to-samples */
vgmstream->coding_type = coding_DSA;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x08;
read_string(vgmstream->stream_name,0x20+1, 0x26,streamFile);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../coding/coding.h"
/* .DSF - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM* init_vgmstream_dsf(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels, sample_rate;
size_t data_size;
/* checks */
if (!is_id32be(0x00,sf, "OCEA") || !is_id64be(0x04,sf, "N DSA\0\0\0"))
goto fail;
if (!check_extensions(sf, "dsf"))
goto fail;
/* 0x10(2): always 1? */
/* 0x12(4): total nibbles / 0x10? */
/* 0x16(4): always 0? */
start_offset = read_u32le(0x1a,sf);
sample_rate = read_s32le(0x1e,sf);
channels = read_s32le(0x22,sf) + 1;
data_size = get_streamfile_size(sf) - start_offset;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_DSF;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = ((data_size / 0x08 / channels) * 14); /* bytes-to-samples */
vgmstream->coding_type = coding_DSA;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x08;
read_string(vgmstream->stream_name,0x20+1, 0x26,sf);
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -2,45 +2,48 @@
#include "../util.h"
#include "../coding/coding.h"
static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset);
static VGMSTREAM* init_vgmstream_kt_wiibgm_offset(STREAMFILE* sf, off_t offset);
/* Koei Tecmo G1L - container format, sometimes containing a single stream.
* It probably makes more sense to extract it externally, it's here mainly for Hyrule Warriors */
VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int type;
int total_streams, target_stream = streamFile->stream_index;
off_t stream_offset;
VGMSTREAM* init_vgmstream_kt_g1l(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int type;
int total_streams, target_stream = sf->stream_index;
off_t stream_offset;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
if (!check_extensions(streamFile,"g1l"))
goto fail;
/* check header */
if ((read_32bitBE(0x0, streamFile) != 0x47314C5F /* "G1L_" (BE) */
|| read_32bitBE(0x0, streamFile) != 0x5F4C3147) /* "_L1G" (LE) */
&& read_32bitBE(0x4, streamFile) != 0x30303030) /* "0000" (version?) */
goto fail;
/* checks */
if (!is_id32be(0x00, sf, "G1L_") && /* BE */
!is_id32le(0x00, sf, "G1L_")) /* LE */
goto fail;
if (read_32bitBE(0x0, streamFile) == 0x47314C5F) {
read_32bit = read_32bitBE;
} else {
if (!check_extensions(sf,"g1l"))
goto fail;
if (!is_id32be(0x04, sf, "0000")) /* version? */
goto fail;
if (is_id32be(0x00, sf, "G1L_")) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
}
}
/* 0x08: filesize, 0x0c: header size */
type = read_32bit(0x10,streamFile);
total_streams = read_32bit(0x14,streamFile);
type = read_32bit(0x10,sf);
total_streams = read_32bit(0x14,sf);
if (target_stream==0) target_stream = 1;
if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail;
if (target_stream < 0 || target_stream > total_streams || total_streams < 1) goto fail;
stream_offset = read_32bit(0x18 + 0x4*(target_stream-1),streamFile);
stream_offset = read_32bit(0x18 + 0x4*(target_stream-1),sf);
//stream_size = stream_offset - stream_next_offset;//not ok, sometimes entries are unordered/repeats */
switch(type) { /* type may not be correct */
case 0x09: /* DSP (WiiBGM) from Hyrule Warriors (Wii U) */
vgmstream = init_vgmstream_kt_wiibgm_offset(streamFile, stream_offset);
vgmstream = init_vgmstream_kt_wiibgm_offset(sf, stream_offset);
break;
case 0x06: /* ATRAC9 (RIFF) from One Piece Pirate Warriors 3 (Vita) */
case 0x01: /* ATRAC3plus (RIFF) from One Piece Pirate Warriors 2 (PS3) */
@ -51,41 +54,41 @@ VGMSTREAM * init_vgmstream_kt_g1l(STREAMFILE *streamFile) {
}
return vgmstream;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
close_vgmstream(vgmstream);
return NULL;
}
/* Koei Tecmo "WiiBGM" DSP format - found in Hyrule Warriors, Romance of the Three Kingdoms 12 */
VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE *streamFile) {
return init_vgmstream_kt_wiibgm_offset(streamFile, 0x0);
VGMSTREAM * init_vgmstream_kt_wiibgm(STREAMFILE *sf) {
return init_vgmstream_kt_wiibgm_offset(sf, 0x0);
}
static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t offset) {
VGMSTREAM * vgmstream = NULL;
static VGMSTREAM* init_vgmstream_kt_wiibgm_offset(STREAMFILE* sf, off_t offset) {
VGMSTREAM* vgmstream = NULL;
int loop_flag, channel_count;
off_t start_offset;
if (!check_extensions(streamFile,"g1l,dsp"))
/* check */
if (!is_id64be(offset+0x0, sf, "WiiBGM\0\0") &&
read_32bitBE(offset+0x4, sf) != 0x474D0000)
goto fail;
if (read_32bitBE(offset+0x0, streamFile) != 0x57696942 && /* "WiiB" */
read_32bitBE(offset+0x4, streamFile) != 0x474D0000) /* "GM\0\0" */
if (!check_extensions(sf,"g1l,dsp"))
goto fail;
/* check type details */
loop_flag = read_32bitBE(offset+0x14, streamFile) > 0;
channel_count = read_8bit(offset+0x23, streamFile);
loop_flag = read_32bitBE(offset+0x14, sf) > 0;
channel_count = read_u8(offset+0x23, sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(offset+0x10, streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(offset+0x26, streamFile);
vgmstream->loop_start_sample = read_32bitBE(offset+0x14, streamFile);
vgmstream->num_samples = read_32bitBE(offset+0x10, sf);
vgmstream->sample_rate = (uint16_t)read_16bitBE(offset+0x26, sf);
vgmstream->loop_start_sample = read_32bitBE(offset+0x14, sf);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_DSP_subint;
@ -93,10 +96,10 @@ static VGMSTREAM * init_vgmstream_kt_wiibgm_offset(STREAMFILE *streamFile, off_t
vgmstream->interleave_block_size = 0x1;
vgmstream->meta_type = meta_KT_WIIBGM;
dsp_read_coefs_be(vgmstream,streamFile, offset+0x5C, 0x60);
dsp_read_coefs_be(vgmstream,sf, offset+0x5C, 0x60);
start_offset = offset+0x800;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;

View File

@ -1,109 +1,108 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* H4M - from Hudson HVQM4 videos [Resident Evil 0 (GC), Tales of Symphonia (GC)]
* (info from hcs/Nisto's h4m_audio_decode) */
VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
int format, extra_tracks, sample_rate;
int total_subsongs, target_subsong = streamFile->stream_index;
/* checks */
if (!check_extensions(streamFile, "h4m"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4856514D && /* "HVQM" */
read_32bitBE(0x04,streamFile) != 0x3420312E) /* "4 1." */
goto fail;
if (read_32bitBE(0x08,streamFile) != 0x33000000 && /* "3\0\0\0" */
read_32bitBE(0x08,streamFile) != 0x35000000) /* "5\0\0\0" */
goto fail;
/* header */
start_offset = read_32bitBE(0x10, streamFile); /* header_size */
if (start_offset != 0x44) /* known size */
goto fail;
if (read_32bitBE(0x14, streamFile) != get_streamfile_size(streamFile) - start_offset) /* body_size */
goto fail;
if (read_32bitBE(0x18, streamFile) == 0) /* blocks */
goto fail;
/* 0x1c: video_frames */
if (read_32bitBE(0x20, streamFile) == 0) /* audio_frames */
goto fail;
/* 0x24: frame interval */
/* 0x28: max_video_frame_size */
/* 0x2c: unk2C (0) */
if (read_32bitBE(0x30, streamFile) == 0) /* max_audio_frame_size */
goto fail;
/* 0x34: hres */
/* 0x36: vres */
/* 0x38: h_srate */
/* 0x39: v_srate */
/* 0x3a: unk3A (0 or 0x12) */
/* 0x3b: unk3B (0) */
channel_count = read_8bit(0x3c,streamFile);
if (read_8bit(0x3d,streamFile) != 16) /* bitdepth */
goto fail; //todo Pikmin (GC) is using some kind of variable blocks
format = (uint8_t)read_8bit(0x3e,streamFile); /* flags? */
extra_tracks = read_8bit(0x3f,streamFile);
sample_rate = read_32bitBE(0x40,streamFile);
loop_flag = 0;
/* tracks for languages [Pokemon Channel], or sometimes used to fake multichannel [Tales of Symphonia] */
total_subsongs = extra_tracks + 1;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = get_streamfile_size(streamFile) / total_subsongs; /* approx... */
vgmstream->codec_config = format; /* for blocks */
vgmstream->meta_type = meta_H4M;
vgmstream->layout_type = layout_blocked_h4m;
switch(format & 0x7F) {
case 0x00:
vgmstream->coding_type = coding_H4M_IMA;
break;
/* no games known to use these, h4m_audio_decode may decode them */
case 0x01: /* Uncompressed PCM */
case 0x04: /* 8-bit (A)DPCM */
default:
VGM_LOG("H4M: unknown codec %x\n", format);
goto fail;
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
/* calc num_samples manually */
{
vgmstream->stream_index = target_subsong; /* extra setup for H4M */
vgmstream->full_block_size = 0; /* extra setup for H4M */
vgmstream->next_block_offset = start_offset;
do {
block_update(vgmstream->next_block_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_samples;
}
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
vgmstream->full_block_size = 0; /* extra cleanup for H4M */
block_update(start_offset, vgmstream);
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
/* H4M - from Hudson HVQM4 videos [Resident Evil 0 (GC), Tales of Symphonia (GC)]
* (info from hcs/Nisto's h4m_audio_decode) */
VGMSTREAM* init_vgmstream_h4m(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
int format, extra_tracks, sample_rate;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id64be(0x00,sf, "HVQM4 1."))
goto fail;
if (!is_id32be(0x08,sf, "3\0\0\0") &&
!is_id32be(0x08,sf, "5\0\0\0"))
goto fail;
if (!check_extensions(sf, "h4m"))
goto fail;
/* header */
start_offset = read_u32be(0x10, sf); /* header_size */
if (start_offset != 0x44) /* known size */
goto fail;
if (read_u32be(0x14, sf) != get_streamfile_size(sf) - start_offset) /* body_size */
goto fail;
if (read_u32be(0x18, sf) == 0) /* blocks */
goto fail;
/* 0x1c: video_frames */
if (read_u32be(0x20, sf) == 0) /* audio_frames */
goto fail;
/* 0x24: frame interval */
/* 0x28: max_video_frame_size */
/* 0x2c: unk2C (0) */
if (read_u32be(0x30, sf) == 0) /* max_audio_frame_size */
goto fail;
/* 0x34: hres */
/* 0x36: vres */
/* 0x38: h_srate */
/* 0x39: v_srate */
/* 0x3a: unk3A (0 or 0x12) */
/* 0x3b: unk3B (0) */
channel_count = read_u8(0x3c,sf);
if (read_u8(0x3d,sf) != 16) /* bitdepth */
goto fail; //todo Pikmin (GC) is using some kind of variable blocks
format = read_u8(0x3e,sf); /* flags? */
extra_tracks = read_u8(0x3f,sf);
sample_rate = read_s32be(0x40,sf);
loop_flag = 0;
/* tracks for languages [Pokemon Channel], or sometimes used to fake multichannel [Tales of Symphonia] */
total_subsongs = extra_tracks + 1;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = get_streamfile_size(sf) / total_subsongs; /* approx... */
vgmstream->codec_config = format; /* for blocks */
vgmstream->meta_type = meta_H4M;
vgmstream->layout_type = layout_blocked_h4m;
switch(format & 0x7F) {
case 0x00:
vgmstream->coding_type = coding_H4M_IMA;
break;
/* no games known to use these, h4m_audio_decode may decode them */
case 0x01: /* Uncompressed PCM */
case 0x04: /* 8-bit (A)DPCM */
default:
VGM_LOG("H4M: unknown codec %x\n", format);
goto fail;
}
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
/* calc num_samples manually */
{
vgmstream->stream_index = target_subsong; /* extra setup for H4M */
vgmstream->full_block_size = 0; /* extra setup for H4M */
vgmstream->next_block_offset = start_offset;
do {
block_update(vgmstream->next_block_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_samples;
}
while (vgmstream->next_block_offset < get_streamfile_size(sf));
vgmstream->full_block_size = 0; /* extra cleanup for H4M */
block_update(start_offset, vgmstream);
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,65 @@
#include "meta.h"
#include "../coding/coding.h"
/* KNON - from Donkey Kong: Barrel Blast (Wii) */
VGMSTREAM* init_vgmstream_knon(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels;
/* checks*/
if (!is_id32be(0x00,sf, "KNON"))
goto fail;
/* .str: PCM files
* .asr: DSP files */
if (!check_extensions(sf, "str,asr"))
goto fail;
if (!is_id32be(0x08,sf, "WII "))
goto fail;
loop_flag = (read_32bitBE(0x44,sf) != 0);
channels = 2;
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitBE(0x40,sf);
switch (read_32bitBE(0x20,sf)) {
case 0x4B415354: /* "KAST" */
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = dsp_bytes_to_samples(read_32bitBE(0x3C,sf), channels);
vgmstream->loop_start_sample = dsp_bytes_to_samples(read_32bitBE(0x44,sf), channels);
vgmstream->loop_end_sample = dsp_bytes_to_samples(read_32bitBE(0x48,sf), channels);
vgmstream->interleave_block_size = 0x10;
dsp_read_coefs_be(vgmstream, sf, 0x8c, 0x60);
break;
case 0x4B505354: /* "KPST" */
vgmstream->coding_type = coding_PCM16BE;
vgmstream->num_samples = pcm16_bytes_to_samples(read_32bitBE(0x3C,sf), channels);
vgmstream->loop_start_sample = pcm16_bytes_to_samples(read_32bitBE(0x44,sf), channels);
vgmstream->loop_end_sample = pcm16_bytes_to_samples(read_32bitBE(0x48,sf), channels);
vgmstream->interleave_block_size = 0x10;
break;
default:
goto fail;
}
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_KNON;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -330,7 +330,7 @@ VGMSTREAM * init_vgmstream_seg(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nds_strm_ffta2(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_str_asr(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_knon(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_zwdsp(STREAMFILE * streamFile);

View File

@ -11,11 +11,15 @@ VGMSTREAM* init_vgmstream_mus_vc(STREAMFILE* sf) {
/* checks */
if (read_u32be(0x00,sf) != 0xFBBFFBBF && /* BE */
read_u32le(0x00,sf) != 0xFBBFFBBF) /* LE */
goto fail;
if (!check_extensions(sf, "mus"))
goto fail;
if (read_u32be(0x08,sf) != 0xBBBBBBBB &&
read_u32be(0x14,sf) != 0xBBBBBBBB &&
if (read_u32be(0x08,sf) != 0xBBBBBBBB ||
read_u32be(0x14,sf) != 0xBBBBBBBB ||
read_u32be(0x2c,sf) != 0xBEBEBEBE)
goto fail;

View File

@ -2,12 +2,12 @@
#include "../coding/coding.h"
static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size);
static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset);
static int get_ogg_page_size(STREAMFILE* sf, off_t page_offset, off_t *out_data_offset, size_t *out_page_size);
static int ogg_get_num_samples(STREAMFILE* sf, off_t start_offset);
/* Ogg Opus - standard Opus with optional looping comments [The Pillars of Earth (PC), Monster Boy and the Cursed Kingdom (Switch)] */
VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_ogg_opus(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_offset = 0;
size_t page_size = 0;
int loop_flag, channel_count, original_rate;
@ -15,35 +15,36 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
/* checks */
if (!is_id32be(0x00,sf, "OggS"))
goto fail;
/* .opus: standard, .lopus: fake extension for plugins
* .ogg: less common, .logg: same
* .bgm: Utawarerumono: Mask of Truth (PC) */
if (!check_extensions(streamFile, "opus,lopus,ogg,logg,bgm"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4F676753) /* "OggS" */
if (!check_extensions(sf, "opus,lopus,ogg,logg,bgm"))
goto fail;
/* see: https://tools.ietf.org/html/rfc7845.html */
start_offset = 0x00;
/* parse 1st page: opus head */
if (!get_ogg_page_size(streamFile, start_offset, &data_offset, &page_size))
if (!get_ogg_page_size(sf, start_offset, &data_offset, &page_size))
goto fail;
if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */
read_32bitBE(data_offset+0x04,streamFile) != 0x48656164) /* "Head" */
if (!is_id32be(data_offset+0x00,sf, "Opus") ||
!is_id32be(data_offset+0x04,sf, "Head"))
goto fail;
/* 0x01: version 1, fixed */
channel_count = read_8bit(data_offset+0x09,streamFile);
channel_count = read_u8(data_offset+0x09,sf);
/* 0x0A: skip samples */
original_rate = read_32bitLE(data_offset+0x0c,streamFile);
original_rate = read_s32le(data_offset+0x0c,sf);
/* 0x10: gain */
/* 0x12: mapping family */
/* parse 2nd page: opus tags (also mandatory) */
if (!get_ogg_page_size(streamFile, start_offset+page_size, &data_offset, &page_size))
if (!get_ogg_page_size(sf, start_offset+page_size, &data_offset, &page_size))
goto fail;
if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */
read_32bitBE(data_offset+0x04,streamFile) != 0x54616773) /* "Tags" */
if (!is_id32be(data_offset+0x00,sf, "Opus") ||
!is_id32be(data_offset+0x04,sf, "Tags"))
goto fail;
loop_flag = 0;
@ -54,15 +55,15 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
int i;
int has_encoder_options = 0, has_title = 0;
vendor_size = read_32bitLE(data_offset+0x08,streamFile);
comment_count = read_32bitLE(data_offset+0x0c+vendor_size,streamFile);
vendor_size = read_s32le(data_offset+0x08,sf);
comment_count = read_s32le(data_offset+0x0c+vendor_size,sf);
/* parse comments */
offset = data_offset + 0x0c + vendor_size + 0x04;
for (i = 0; i < comment_count; i++) {
user_comment_size = read_32bitLE(offset+0x00,streamFile);
user_comment_size = read_s32le(offset+0x00,sf);
user_comment_max = user_comment_size > 1024 ? 1024 : user_comment_size;
read_string(user_comment,user_comment_max+1, offset+0x04,streamFile);
read_string(user_comment,user_comment_max+1, offset+0x04,sf);
/* parse loop strings */
@ -112,13 +113,13 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_OGG_OPUS;
vgmstream->sample_rate = 48000; /* Opus always resamples to this */
vgmstream->num_samples = ogg_get_num_samples(streamFile, 0x00);
vgmstream->num_samples = ogg_get_num_samples(sf, 0x00);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
#ifdef VGM_USE_FFMPEG
{
vgmstream->codec_data = init_ffmpeg_offset(streamFile, start_offset, get_streamfile_size(streamFile));
vgmstream->codec_data = init_ffmpeg_offset(sf, start_offset, get_streamfile_size(sf));
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
@ -129,7 +130,7 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
goto fail;
#endif
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;
@ -140,23 +141,23 @@ fail:
/* parse OggS's bizarre segment table */
static int get_ogg_page_size(STREAMFILE *streamFile, off_t page_offset, off_t *out_data_offset, size_t *out_page_size) {
static int get_ogg_page_size(STREAMFILE* sf, off_t page_offset, off_t* p_data_offset, size_t* p_page_size) {
uint8_t segments;
size_t page_size = 0;
int i;
if (read_32bitBE(page_offset+0x00,streamFile) != 0x4F676753) /* "OggS" */
if (!is_id32be(page_offset+0x00,sf, "OggS"))
goto fail;
/* read all segment sizes */
segments = (uint8_t)read_8bit(page_offset+0x1a, streamFile);
segments = read_u8(page_offset+0x1a, sf);
for (i = 0; i < segments; i++) {
page_size += (uint8_t)read_8bit(page_offset + 0x1b + i, streamFile);
page_size += read_u8(page_offset + 0x1b + i, sf);
}
page_size += 0x1b + segments;
if (out_data_offset) *out_data_offset = page_offset + 0x1b + segments;
if (out_page_size) *out_page_size = page_size;
if (p_data_offset) *p_data_offset = page_offset + 0x1b + segments;
if (p_page_size) *p_page_size = page_size;
return 1;
fail:
return 0;
@ -164,18 +165,18 @@ fail:
/* Ogg doesn't have num_samples info, must manually seek+read last granule
* (Xiph is insistent this is the One True Way). */
static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset) {
uint32_t expected_id = 0x4F676753;
off_t offset = get_streamfile_size(streamFile) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04;
static int ogg_get_num_samples(STREAMFILE *sf, off_t start_offset) {
uint32_t expected_id = get_id32be("OggS");
off_t offset = get_streamfile_size(sf) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04;
//todo better buffer reads (Ogg page max is 0xFFFF)
//lame way to force buffer, assuming it's around that
read_32bitBE(offset - 0x4000, streamFile);
read_u32be(offset - 0x4000, sf);
while (offset >= start_offset) {
uint32_t current_id = read_32bitBE(offset, streamFile);
uint32_t current_id = read_u32be(offset, sf);
if (current_id == expected_id) { /* if more checks are needed last page starts with 0x0004 */
return read_32bitLE(offset+0x04+0x01+0x01, streamFile); /* get last granule = total samples (64b but whatevs) */
return read_s32le(offset+0x04+0x01+0x01, sf); /* get last granule = total samples (64b but whatevs) */
}
offset--;

View File

@ -380,10 +380,9 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_common(STREAMFILE* sf) {
}
if (is_rpgmvo) { /* [RPG Maker MV (PC), RPG Maker MZ (PC)] */
if (read_32bitBE(0x00,sf) != 0x5250474D && /* "RPGM" */
read_32bitBE(0x00,sf) != 0x56000000) { /* "V\0\0\0" */
if (!is_id64be(0x00,sf, "RPGMV\0\0\0"))
goto fail;
}
ovmi.decryption_callback = rpgmvo_ogg_decryption_callback;
cfg.start = 0x10;

View File

@ -1,72 +1,78 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* OGL - Shin'en custom Vorbis [Jett Rocket (Wii), FAST Racing NEO (WiiU)] */
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
size_t partial_file_size;
int loop_flag, channel_count, sample_rate;
uint32_t num_samples, loop_start_sample, loop_end_sample;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"ogl"))
goto fail;
/* OGL headers are very basic with no ID but libvorbis should reject garbage data anyway */
loop_flag = read_32bitLE(0x00,streamFile) > 0; /* absolute loop offset */
loop_start_sample = read_32bitLE(0x04,streamFile);
//loop_start_block = read_32bitLE(0x08,streamFile);
num_samples = read_32bitLE(0x0c,streamFile);
partial_file_size = read_32bitLE(0x10,streamFile); /* header + data not counting end padding */
if (partial_file_size > get_streamfile_size(streamFile)) goto fail;
loop_end_sample = num_samples; /* there is no data after num_samples (ie.- it's really num_samples) */
/* actually peeking into the Vorbis id packet */
channel_count = read_8bit (0x21,streamFile);
sample_rate = read_32bitLE(0x22,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_OGL;
#ifdef VGM_USE_VORBIS
{
vorbis_custom_config cfg = {0};
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_VORBIS_custom;
vgmstream->codec_data = init_vorbis_custom(streamFile, 0x14, VORBIS_OGL, &cfg);
if (!vgmstream->codec_data) goto fail;
start_offset = cfg.data_start_offset;
}
#else
goto fail;
#endif
/* non-looping files do this */
if (!num_samples) {
uint32_t avg_bitrate = read_32bitLE(0x2a,streamFile); /* inside id packet */
/* approximate as we don't know the sizes of all packet headers */ //todo this is wrong... but somehow works?
vgmstream->num_samples = (partial_file_size - start_offset) * ((sample_rate*10/avg_bitrate)+1);
}
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
/* OGL - Shin'en custom Vorbis [Jett Rocket (Wii), FAST Racing NEO (WiiU)] */
VGMSTREAM* init_vgmstream_ogl(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
size_t partial_file_size;
int loop_flag, channels, sample_rate;
uint32_t num_samples, loop_start_sample, loop_end_sample;
/* checks */
if (read_u32le(0x00, sf) > 0x10000000) /* limit loop samples (should catch fourccs) */
goto fail;
if (!is_id32be(0x17, sf, "vorb")) /* Vorbis id packet */
goto fail;
if (!check_extensions(sf,"ogl"))
goto fail;
/* OGL headers are very basic with no ID but libvorbis should reject garbage data anyway */
loop_flag = read_s32le(0x00,sf) > 0; /* absolute loop offset */
loop_start_sample = read_s32le(0x04,sf);
//loop_start_block = read_s32le(0x08,streamFile);
num_samples = read_s32le(0x0c,sf);
partial_file_size = read_s32le(0x10,sf); /* header + data not counting end padding */
if (partial_file_size > get_streamfile_size(sf))
goto fail;
loop_end_sample = num_samples; /* there is no data after num_samples (ie.- it's really num_samples) */
/* actually peeking into the Vorbis id packet */
channels = read_u8 (0x21,sf);
sample_rate = read_s32le(0x22,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->meta_type = meta_OGL;
#ifdef VGM_USE_VORBIS
{
vorbis_custom_config cfg = {0};
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_VORBIS_custom;
vgmstream->codec_data = init_vorbis_custom(sf, 0x14, VORBIS_OGL, &cfg);
if (!vgmstream->codec_data) goto fail;
start_offset = cfg.data_start_offset;
}
#else
goto fail;
#endif
/* non-looping files do this */
if (!num_samples) {
uint32_t avg_bitrate = read_u32le(0x2a,sf); /* inside id packet */
/* approximate as we don't know the sizes of all packet headers */ //todo this is wrong... but somehow works?
vgmstream->num_samples = (partial_file_size - start_offset) * ((sample_rate*10/avg_bitrate)+1);
}
/* open the file for reading */
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,45 +1,45 @@
#include "meta.h"
/* IMU - found in Alter Echo (PS2) */
VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* check extension */
if ( !check_extensions(streamFile,"omu") )
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4F4D5520 && /* "OMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
loop_flag = 1;
channel_count = (int)read_8bit(0x14,streamFile);
start_offset = 0x40;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = (int32_t)(read_32bitLE(0x3C,streamFile)/(vgmstream->channels*2));
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x200;
vgmstream->meta_type = meta_PS2_OMU;
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
/* IMU - found in Alter Echo (PS2) */
VGMSTREAM* init_vgmstream_ps2_omu(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channels;
/* checks */
if (!is_id32be(0x00,sf, "OMU "))
goto fail;
if (!check_extensions(sf,"omu"))
goto fail;
if (!is_id32be(0x08,sf, "FRMT"))
goto fail;
loop_flag = 1;
channels = read_u8(0x14,sf);
start_offset = 0x40;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = (read_u32le(0x3C,sf) / (vgmstream->channels*2));
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x200;
vgmstream->meta_type = meta_PS2_OMU;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,72 +1,50 @@
#include "meta.h"
#include "../util.h"
/* manakoAT 28.01.2009 :
BAKA - found in "Crypt Killer (Saturn)...
looks like some developers were really bored, every file starts with
the word "BAKA" which is the japanese word for "IDIOT" :o)
Files containing "begloop" markers at EOF...
some files should loop, but i don't know how to get the loopstart here!*/
VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
/* BAKA - from KCET games [Crypt Killer (Saturn)] */
VGMSTREAM* init_vgmstream_sat_baka(STREAMFILE *sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag = 0;
int channel_count;
int loop_flag, channels;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("baka",filename_extension(filename))) goto fail;
/* checks */
if (!is_id32be(0x00,sf, "BAKA"))
goto fail;
/* (extensionless): original
* .baka: header id */
if (!check_extensions(sf, ",baka"))
goto fail;
/* RIFF style chunks */
if (!is_id32be(0x08,sf, " AHO") ||
!is_id32be(0x0C,sf, "PAPA") ||
!is_id32be(0x26,sf, "MAMA"))
goto fail;
//todo begloop markers at EOF
loop_flag = 0;
channels = 2;
start_offset = 0x2E;
/* check header */
if ((read_32bitBE(0x00,streamFile) != 0x42414B41 && /* "BAKA" */
read_32bitBE(0x08,streamFile) != 0x2041484F && /* " AHO" */
read_32bitBE(0x0C,streamFile) != 0x50415041 && /* "PAPA" */
read_32bitBE(0x26,streamFile) != 0x4D414D41)) /* "MAMA" */
goto fail;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x2E;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PCM16BE;
vgmstream->num_samples = read_32bitBE(0x16,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitBE(0x16,streamFile);
}
vgmstream->num_samples = read_u32be(0x16,sf);
vgmstream->coding_type = coding_PCM16BE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2;
vgmstream->meta_type = meta_SAT_BAKA;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,67 +1,67 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
/* STHD - Dream Factory .stx [Kakuto Chojin (Xbox)] */
VGMSTREAM * init_vgmstream_sthd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if (!check_extensions(streamFile, "stx"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53544844) /* "STHD" */
goto fail;
/* first block has special values */
if (read_32bitLE(0x04,streamFile) != 0x0800 &&
read_32bitLE(0x0c,streamFile) != 0x0001 &&
read_32bitLE(0x14,streamFile) != 0x0000)
goto fail;
channel_count = read_16bitLE(0x06,streamFile);
loop_flag = read_16bitLE(0x18,streamFile) != -1;
start_offset = 0x800;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_STHD;
vgmstream->sample_rate = read_32bitLE(0x20, streamFile); /* repeated ~8 times? */
vgmstream->coding_type = coding_XBOX_IMA_int;
vgmstream->layout_type = layout_blocked_sthd;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
/* calc num_samples manually (blocks data varies in size) */
{
/* loop values may change to +1 in first actual block, but this works ok enough */
int loop_start_block = (uint16_t)read_16bitLE(0x1a,streamFile);
int loop_end_block = (uint16_t)read_16bitLE(0x1c,streamFile);
int block_count = 1; /* header block = 0 */
vgmstream->next_block_offset = start_offset;
do {
block_update(vgmstream->next_block_offset,vgmstream);
if (block_count == loop_start_block)
vgmstream->loop_start_sample = vgmstream->num_samples;
if (block_count == loop_end_block)
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->num_samples += xbox_ima_bytes_to_samples(vgmstream->current_block_size, 1);
block_count++;
}
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
block_update(start_offset, vgmstream);
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
/* STHD - Dream Factory .stx [Kakuto Chojin (Xbox)] */
VGMSTREAM * init_vgmstream_sthd(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if (!is_id32be(0x00,sf, "STHD"))
goto fail;
if (!check_extensions(sf, "stx"))
goto fail;
/* first block has special values */
if (read_u16le(0x04,sf) != 0x0800 ||
read_u32le(0x0c,sf) != 0x0001 ||
read_u32le(0x14,sf) != 0x0000)
goto fail;
channel_count = read_s16le(0x06,sf);
loop_flag = read_s16le(0x18,sf) != -1;
start_offset = read_u16le(0x04,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_STHD;
vgmstream->sample_rate = read_s32le(0x20, sf); /* repeated ~8 times? */
vgmstream->coding_type = coding_XBOX_IMA_int;
vgmstream->layout_type = layout_blocked_sthd;
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
/* calc num_samples manually (blocks data varies in size) */
{
/* loop values may change to +1 in first actual block, but this works ok enough */
int loop_start_block = (uint16_t)read_16bitLE(0x1a,sf);
int loop_end_block = (uint16_t)read_16bitLE(0x1c,sf);
int block_count = 1; /* header block = 0 */
vgmstream->next_block_offset = start_offset;
do {
block_update(vgmstream->next_block_offset,vgmstream);
if (block_count == loop_start_block)
vgmstream->loop_start_sample = vgmstream->num_samples;
if (block_count == loop_end_block)
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->num_samples += xbox_ima_bytes_to_samples(vgmstream->current_block_size, 1);
block_count++;
}
while (vgmstream->next_block_offset < get_streamfile_size(sf));
block_update(start_offset, vgmstream);
}
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -1,97 +0,0 @@
#include "meta.h"
#include "../util.h"
/* STR -ASR (from Donkey Kong Jet Race) */
VGMSTREAM * init_vgmstream_str_asr(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename)) && /* PCM Files */
strcasecmp("asr",filename_extension(filename))) /* DSP Files */
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4B4E4F4E && /* "KNON" */
read_32bitBE(0x04,streamFile) != 0x00000000 && /* "0x0" */
read_32bitBE(0x08,streamFile) != 0x57494920) goto fail; /* "WII\0x20" */
loop_flag = (read_32bitBE(0x44,streamFile)!=0);
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
switch (read_32bitBE(0x20,streamFile)) {
case 0x4B415354: /* KAST - DSP encoding */
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = (read_32bitBE(0x3C,streamFile))*14/8/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile))*14/8/channel_count;
vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile))*14/8/channel_count;
}
vgmstream->interleave_block_size = 0x10;
break;
case 0x4B505354: /* KPST - PCM encoding */
vgmstream->coding_type = coding_PCM16BE;
vgmstream->num_samples = (read_32bitBE(0x3C,streamFile))/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = (read_32bitBE(0x44,streamFile))/2/channel_count;
vgmstream->loop_end_sample = (read_32bitBE(0x48,streamFile))/2/channel_count;
}
vgmstream->interleave_block_size = 0x10;
break;
default:
goto fail;
}
/* Interleave and Layout settings */
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_STR_ASR;
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x8C+i*2,streamFile);
}
if (vgmstream->channels) {
for (i=0;i<16;i++) {
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xEC+i*2,streamFile);
}
}
}
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -11,11 +11,12 @@ VGMSTREAM* init_vgmstream_strm_abylight(STREAMFILE* sf) {
/* checks */
if ( !check_extensions(sf,"strm") )
if (!is_id32be(0x00,sf, "STRM"))
goto fail;
if (read_32bitBE(0x00,sf) != 0x5354524D) /* "STRM" */
if (!check_extensions(sf,"strm"))
goto fail;
if (read_32bitLE(0x04,sf) != 0x03E8) /* version 1000? */
goto fail;

View File

@ -1,44 +1,47 @@
#include "meta.h"
#include "../coding/coding.h"
/* XMU - found in Alter Echo (Xbox) */
VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
size_t start_offset;
int loop_flag, channel_count;
size_t data_size;
/* check extension */
if (!check_extensions(streamFile,"xmu"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
goto fail;
start_offset = 0x800;
channel_count=read_8bit(0x14,streamFile); /* always stereo files */
loop_flag = read_8bit(0x16,streamFile); /* no Loop found atm */
data_size = read_32bitLE(0x7FC,streamFile); /* next to "DATA" */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_XMU;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
#include "meta.h"
#include "../coding/coding.h"
/* XMU - found in Alter Echo (Xbox) */
VGMSTREAM* init_vgmstream_xmu(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
size_t start_offset;
int loop_flag, channel_count;
size_t data_size;
/* checks */
if (!is_id32be(0x00,sf, "XMU "))
goto fail;
if (!check_extensions(sf,"xmu"))
goto fail;
if (!is_id32be(0x08,sf, "FRMT"))
goto fail;
start_offset = 0x800;
channel_count = read_u8(0x14,sf); /* always stereo files */
loop_flag = read_u8(0x16,sf); /* no Loop found atm */
data_size = read_u32le(0x7FC,sf); /* next to "DATA" */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_XMU;
vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -153,7 +153,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_ubi_jade_container,
init_vgmstream_seg,
init_vgmstream_nds_strm_ffta2,
init_vgmstream_str_asr,
init_vgmstream_knon,
init_vgmstream_gca,
init_vgmstream_spt_spd,
init_vgmstream_ish_isd,
@ -204,7 +204,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_apple_caff,
init_vgmstream_pc_mxst,
init_vgmstream_sab,
init_vgmstream_exakt_sc,
init_vgmstream_wii_bns,
init_vgmstream_wii_was,
init_vgmstream_pona_3do,
@ -235,7 +234,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_ps2_wad,
init_vgmstream_dsp_xiii,
init_vgmstream_dsp_cabelas,
init_vgmstream_ps2_adm,
init_vgmstream_lpcm_shade,
init_vgmstream_dsp_bdsp,
init_vgmstream_ps2_vms,
@ -316,7 +314,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_va3,
init_vgmstream_mta2,
init_vgmstream_mta2_container,
init_vgmstream_ngc_ulw,
init_vgmstream_xa_xa30,
init_vgmstream_xa_04sw,
init_vgmstream_ea_bnk,
@ -540,7 +537,10 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_raw_pcm, /* .raw raw PCM */
init_vgmstream_s14_sss, /* .s14/sss raw siren14 */
init_vgmstream_raw_al, /* .al/al2 raw A-LAW */
init_vgmstream_ngc_ulw, /* .ulw raw u-Law */
init_vgmstream_exakt_sc, /* .sc raw PCM */
init_vgmstream_zwdsp, /* fake format */
init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */
init_vgmstream_baf_badrip, /* crap, to be removed */
init_vgmstream_rxws_badrip, /* crap, to be removed */
#ifdef VGM_USE_FFMPEG

View File

@ -440,7 +440,7 @@ typedef enum {
meta_PS2_ASS, /* ASS */
meta_SEG, /* Eragon */
meta_NDS_STRM_FFTA2, /* Final Fantasy Tactics A2 */
meta_STR_ASR, /* Donkey Kong Jet Race */
meta_KNON,
meta_ZWDSP, /* Zack and Wiki */
meta_VGS, /* Guitar Hero Encore - Rocks the 80s */
meta_DCS_WAV,