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 */; }; 836F702E18BDC2190095E648 /* sli.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF218BDC2190095E648 /* sli.c */; };
836F702F18BDC2190095E648 /* spt_spd.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF318BDC2190095E648 /* spt_spd.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 */; }; 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 */; }; 836F703318BDC2190095E648 /* str_snds.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF718BDC2190095E648 /* str_snds.c */; };
836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; }; 836F703518BDC2190095E648 /* svs.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EF918BDC2190095E648 /* svs.c */; };
836F703618BDC2190095E648 /* thp.c in Sources */ = {isa = PBXBuildFile; fileRef = 836F6EFA18BDC2190095E648 /* thp.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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 836F6EFA18BDC2190095E648 /* thp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = thp.c; sourceTree = "<group>"; };
@ -1950,6 +1950,7 @@
83D20075248DDB760048BD24 /* kat.c */, 83D20075248DDB760048BD24 /* kat.c */,
834FE0C3215C79E6000A5D3D /* kma9_streamfile.h */, 834FE0C3215C79E6000A5D3D /* kma9_streamfile.h */,
83A21F83201D8981000F04B9 /* kma9.c */, 83A21F83201D8981000F04B9 /* kma9.c */,
836F6EF618BDC2190095E648 /* knon.c */,
836F6E5918BDC2180095E648 /* kraw.c */, 836F6E5918BDC2180095E648 /* kraw.c */,
8346D97625BF838C00D1A8B0 /* ktac.c */, 8346D97625BF838C00D1A8B0 /* ktac.c */,
83AA7F792519C042004C5298 /* ktsc.c */, 83AA7F792519C042004C5298 /* ktsc.c */,
@ -2154,7 +2155,6 @@
8317C24826982CC1007DD0B8 /* sspr.c */, 8317C24826982CC1007DD0B8 /* sspr.c */,
8306B0C12098458C000302D4 /* sthd.c */, 8306B0C12098458C000302D4 /* sthd.c */,
83AA5D231F6E2F9C0020821C /* stm.c */, 83AA5D231F6E2F9C0020821C /* stm.c */,
836F6EF618BDC2190095E648 /* str_asr.c */,
836F6EF718BDC2190095E648 /* str_snds.c */, 836F6EF718BDC2190095E648 /* str_snds.c */,
834FE0C2215C79E6000A5D3D /* str_wav.c */, 834FE0C2215C79E6000A5D3D /* str_wav.c */,
83C7280722BC893B00678B4A /* strm_abylight.c */, 83C7280722BC893B00678B4A /* strm_abylight.c */,
@ -2634,7 +2634,7 @@
836F702018BDC2190095E648 /* rkv.c in Sources */, 836F702018BDC2190095E648 /* rkv.c in Sources */,
834FE0F4215C79ED000A5D3D /* wsi.c in Sources */, 834FE0F4215C79ED000A5D3D /* wsi.c in Sources */,
83D26A7A26E66D98001A9475 /* adp_bos.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 */, 837CEB0223487F2C00E62A4A /* raw_int.c in Sources */,
836F702818BDC2190095E648 /* sat_dvi.c in Sources */, 836F702818BDC2190095E648 /* sat_dvi.c in Sources */,
832BF82D21E0514B006F50F1 /* nus3audio.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_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_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_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: /* maxs depend on encoder quality settings (for example, stereo has:
* highest=0x400, high=0x2AA, medium=0x200, low=0x155, lowest=0x100) */ * 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 //TODO: should work but untested
if (hca->ms_stereo) if (hca->ms_stereo)
return HCA_ERROR_HEADER; 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 /* clHCA is correctly initialized and decoder state reset
* (keycode is not changed between calls) */ * (keycode is not changed between calls) */

View File

@ -410,6 +410,7 @@ static const char* extension_list[] = {
"ras", "ras",
"raw", //txth/reserved [Madden NHL 97 (PC)-pcm8u] "raw", //txth/reserved [Madden NHL 97 (PC)-pcm8u]
"rda", //FFmpeg/reserved [Rhythm Destruction (PC)] "rda", //FFmpeg/reserved [Rhythm Destruction (PC)]
"res", //txth/reserved [Spider-Man: Web of Shadows (PSP)]
"rkv", "rkv",
"rnd", "rnd",
"rof", "rof",
@ -1073,7 +1074,7 @@ static const meta_info meta_info_list[] = {
{meta_UBI_JADE, "Ubisoft Jade RIFF header"}, {meta_UBI_JADE, "Ubisoft Jade RIFF header"},
{meta_SEG, "Stormfront SEG header"}, {meta_SEG, "Stormfront SEG header"},
{meta_NDS_STRM_FFTA2, "Final Fantasy Tactics A2 RIFF 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_ZWDSP, "Zack and Wiki custom DSP Header"},
{meta_GCA, "GCA DSP Header"}, {meta_GCA, "GCA DSP Header"},
{meta_SPT_SPD, "SPT+SPD 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_RSTM_shrunken, "Nintendo RSTM header, corrupted by Atlus"},
{meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"}, {meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"},
{meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"}, {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_SWAV, "Nintendo SWAV header"},
{meta_VSF, "Square-Enix VSF header"}, {meta_VSF, "Square-Enix VSF header"},
{meta_NDS_RRDS, "Ridger Racer DS Header"}, {meta_NDS_RRDS, "Ridger Racer DS Header"},

View File

@ -8,6 +8,10 @@
#include "../coding/coding.h" #include "../coding/coding.h"
#ifdef VGM_DEBUG_OUTPUT
//#define ADX_BRUTEFORCE
#endif
#define ADX_KEY_MAX_TEST_FRAMES 32768 #define ADX_KEY_MAX_TEST_FRAMES 32768
#define ADX_KEY_TEST_BUFFER_SIZE 0x8000 #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; return 1;
} }
else if (type == 8 && is_ascii) { 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); derive_adx_key8(keystring, xor_start, xor_mult, xor_add);
return 1; return 1;
} }
else if (type == 9 && key_size == 0x08) { else if (type == 9 && key_size == 0x08) {
uint64_t keycode = get_u64be(keybuf); uint64_t keycode = get_u64be(keybuf);
if (subkey) { derive_adx_key9(keycode, subkey, xor_start, xor_mult, xor_add);
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
derive_adx_key9(keycode, xor_start, xor_mult, xor_add);
return 1; return 1;
} }
else if (type == 9 && key_size == 0x08+0x02) { else if (type == 9 && key_size == 0x08+0x02) {
uint64_t file_key = get_u64be(keybuf+0x00); uint64_t file_keycode = get_u64be(keybuf+0x00);
uint16_t file_sub = get_u16be(keybuf+0x08); uint16_t file_subkey = get_u16be(keybuf+0x08);
uint64_t keycode = file_key * ( ((uint64_t)file_sub << 16u) | ((uint16_t)~file_sub + 2u) ); derive_adx_key9(file_keycode, file_subkey, xor_start, xor_mult, xor_add);
derive_adx_key9(keycode, xor_start, xor_mult, xor_add);
return 1; return 1;
} }
} }
@ -414,11 +414,34 @@ static int find_adx_key(STREAMFILE* sf, uint8_t type, uint16_t *xor_start, uint1
keymask = 0x1000; 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 */ /* try all keys until one decrypts correctly vs expected scales */
for (key_id = 0; key_id < keycount; key_id++) { for (key_id = 0; key_id < keycount; key_id++) {
uint16_t key_xor, key_mul, key_add; uint16_t key_xor, key_mul, key_add;
uint16_t xor, mul, 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 */ /* get pre-derived XOR values or derive if needed */
if (keys[key_id].start || keys[key_id].mult || keys[key_id].add) { if (keys[key_id].start || keys[key_id].mult || keys[key_id].add) {
key_xor = keys[key_id].start; 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) { else if (type == 9 && keys[key_id].key9) {
uint64_t keycode = keys[key_id].key9; uint64_t keycode = keys[key_id].key9;
if (subkey) { derive_adx_key9(keycode, subkey, &key_xor, &key_mul, &key_add);
keycode = keycode * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
derive_adx_key9(keycode, &key_xor, &key_mul, &key_add);
} }
else { else {
VGM_LOG("ADX: incorrectly defined key id=%i\n", key_id); 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); xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key8);
} }
else if (type == 9 && keys[key_id].key9) { 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", 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,mul,add, test_xor,test_mul,test_add,
xor==test_xor && mul==test_mul && add==test_add ? "ok" : "ko", keys[key_id].key9); 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) if (i != bruteframe_count)
continue; 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 */ /* all scales are valid, key is good */
*xor_start = key_xor; *xor_start = key_xor;
*xor_mult = key_mul; *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; rc = 1;
break; break;
} }
#ifdef ADX_BRUTEFORCE
close_streamfile(sf_keys);
free(buf);
#endif
} }
done: done:

View File

@ -258,6 +258,9 @@ static const adxkey_info adxkey9_list[] = {
/* Sonic Colors Ultimate (multi) */ /* Sonic Colors Ultimate (multi) */
{0x0000,0x0000,0x0000, NULL,1991062320101111}, // 000712DC5250B6F7 {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]); 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; uint16_t start = 0, mult = 0, add = 0;
/* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */ /* 0 is ignored by CRI's encoder, only from 1..18446744073709551615 */
if (key9 == 0) if (key9 == 0)
goto end; goto end;
if (subkey) {
key9 = key9 * ( ((uint64_t)subkey << 16u) | ((uint16_t)~subkey + 2u) );
}
key9--; key9--;
start = (int)(((key9 >> 27) & 0x7fff)); start = (int)(((key9 >> 27) & 0x7fff));
mult = (int)(((key9 >> 12) & 0x7ffc) | 1); 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; //mult |= add << 16;
end: end:
*out_start = start; *p_start = start;
*out_mult = mult; *p_mult = mult;
*out_add = add; *p_add = add;
} }
#endif/*_ADX_KEYS_H_*/ #endif/*_ADX_KEYS_H_*/

View File

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

View File

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

View File

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

View File

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

View File

@ -2,12 +2,12 @@
#include "../coding/coding.h" #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 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 *streamFile, off_t start_offset); 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)] */ /* 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* init_vgmstream_ogg_opus(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, data_offset = 0; off_t start_offset, data_offset = 0;
size_t page_size = 0; size_t page_size = 0;
int loop_flag, channel_count, original_rate; int loop_flag, channel_count, original_rate;
@ -15,35 +15,36 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
/* checks */ /* checks */
if (!is_id32be(0x00,sf, "OggS"))
goto fail;
/* .opus: standard, .lopus: fake extension for plugins /* .opus: standard, .lopus: fake extension for plugins
* .ogg: less common, .logg: same * .ogg: less common, .logg: same
* .bgm: Utawarerumono: Mask of Truth (PC) */ * .bgm: Utawarerumono: Mask of Truth (PC) */
if (!check_extensions(streamFile, "opus,lopus,ogg,logg,bgm")) if (!check_extensions(sf, "opus,lopus,ogg,logg,bgm"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x4F676753) /* "OggS" */
goto fail; goto fail;
/* see: https://tools.ietf.org/html/rfc7845.html */ /* see: https://tools.ietf.org/html/rfc7845.html */
start_offset = 0x00; start_offset = 0x00;
/* parse 1st page: opus head */ /* 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; goto fail;
if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ if (!is_id32be(data_offset+0x00,sf, "Opus") ||
read_32bitBE(data_offset+0x04,streamFile) != 0x48656164) /* "Head" */ !is_id32be(data_offset+0x04,sf, "Head"))
goto fail; goto fail;
/* 0x01: version 1, fixed */ /* 0x01: version 1, fixed */
channel_count = read_8bit(data_offset+0x09,streamFile); channel_count = read_u8(data_offset+0x09,sf);
/* 0x0A: skip samples */ /* 0x0A: skip samples */
original_rate = read_32bitLE(data_offset+0x0c,streamFile); original_rate = read_s32le(data_offset+0x0c,sf);
/* 0x10: gain */ /* 0x10: gain */
/* 0x12: mapping family */ /* 0x12: mapping family */
/* parse 2nd page: opus tags (also mandatory) */ /* 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; goto fail;
if (read_32bitBE(data_offset+0x00,streamFile) != 0x4F707573 && /* "Opus" */ if (!is_id32be(data_offset+0x00,sf, "Opus") ||
read_32bitBE(data_offset+0x04,streamFile) != 0x54616773) /* "Tags" */ !is_id32be(data_offset+0x04,sf, "Tags"))
goto fail; goto fail;
loop_flag = 0; loop_flag = 0;
@ -54,15 +55,15 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
int i; int i;
int has_encoder_options = 0, has_title = 0; int has_encoder_options = 0, has_title = 0;
vendor_size = read_32bitLE(data_offset+0x08,streamFile); vendor_size = read_s32le(data_offset+0x08,sf);
comment_count = read_32bitLE(data_offset+0x0c+vendor_size,streamFile); comment_count = read_s32le(data_offset+0x0c+vendor_size,sf);
/* parse comments */ /* parse comments */
offset = data_offset + 0x0c + vendor_size + 0x04; offset = data_offset + 0x0c + vendor_size + 0x04;
for (i = 0; i < comment_count; i++) { 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; 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 */ /* parse loop strings */
@ -112,13 +113,13 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_OGG_OPUS; vgmstream->meta_type = meta_OGG_OPUS;
vgmstream->sample_rate = 48000; /* Opus always resamples to this */ 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_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end; vgmstream->loop_end_sample = loop_end;
#ifdef VGM_USE_FFMPEG #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; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;
@ -129,7 +130,7 @@ VGMSTREAM * init_vgmstream_ogg_opus(STREAMFILE *streamFile) {
goto fail; goto fail;
#endif #endif
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;
@ -140,23 +141,23 @@ fail:
/* parse OggS's bizarre segment table */ /* 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; uint8_t segments;
size_t page_size = 0; size_t page_size = 0;
int i; int i;
if (read_32bitBE(page_offset+0x00,streamFile) != 0x4F676753) /* "OggS" */ if (!is_id32be(page_offset+0x00,sf, "OggS"))
goto fail; goto fail;
/* read all segment sizes */ /* 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++) { 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; page_size += 0x1b + segments;
if (out_data_offset) *out_data_offset = page_offset + 0x1b + segments; if (p_data_offset) *p_data_offset = page_offset + 0x1b + segments;
if (out_page_size) *out_page_size = page_size; if (p_page_size) *p_page_size = page_size;
return 1; return 1;
fail: fail:
return 0; return 0;
@ -164,18 +165,18 @@ fail:
/* Ogg doesn't have num_samples info, must manually seek+read last granule /* Ogg doesn't have num_samples info, must manually seek+read last granule
* (Xiph is insistent this is the One True Way). */ * (Xiph is insistent this is the One True Way). */
static int ogg_get_num_samples(STREAMFILE *streamFile, off_t start_offset) { static int ogg_get_num_samples(STREAMFILE *sf, off_t start_offset) {
uint32_t expected_id = 0x4F676753; uint32_t expected_id = get_id32be("OggS");
off_t offset = get_streamfile_size(streamFile) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04; off_t offset = get_streamfile_size(sf) - 0x04-0x01-0x01-0x08-0x04-0x04-0x04;
//todo better buffer reads (Ogg page max is 0xFFFF) //todo better buffer reads (Ogg page max is 0xFFFF)
//lame way to force buffer, assuming it's around that //lame way to force buffer, assuming it's around that
read_32bitBE(offset - 0x4000, streamFile); read_u32be(offset - 0x4000, sf);
while (offset >= start_offset) { 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 */ 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--; 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 (is_rpgmvo) { /* [RPG Maker MV (PC), RPG Maker MZ (PC)] */
if (read_32bitBE(0x00,sf) != 0x5250474D && /* "RPGM" */ if (!is_id64be(0x00,sf, "RPGMV\0\0\0"))
read_32bitBE(0x00,sf) != 0x56000000) { /* "V\0\0\0" */
goto fail; goto fail;
}
ovmi.decryption_callback = rpgmvo_ogg_decryption_callback; ovmi.decryption_callback = rpgmvo_ogg_decryption_callback;
cfg.start = 0x10; cfg.start = 0x10;

View File

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

View File

@ -1,72 +1,50 @@
#include "meta.h" #include "meta.h"
#include "../util.h" #include "../util.h"
/* manakoAT 28.01.2009 : /* BAKA - from KCET games [Crypt Killer (Saturn)] */
BAKA - found in "Crypt Killer (Saturn)... VGMSTREAM* init_vgmstream_sat_baka(STREAMFILE *sf) {
looks like some developers were really bored, every file starts with VGMSTREAM* vgmstream = NULL;
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];
off_t start_offset; off_t start_offset;
int loop_flag = 0; int loop_flag, channels;
int channel_count;
/* check extension, case insensitive */ /* checks */
streamFile->get_name(streamFile,filename,sizeof(filename)); if (!is_id32be(0x00,sf, "BAKA"))
if (strcasecmp("baka",filename_extension(filename))) goto fail; 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 */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x2E;
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100; vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_PCM16BE; vgmstream->num_samples = read_u32be(0x16,sf);
vgmstream->num_samples = read_32bitBE(0x16,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitBE(0x16,streamFile);
}
vgmstream->coding_type = coding_PCM16BE;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2; vgmstream->interleave_block_size = 0x2;
vgmstream->meta_type = meta_SAT_BAKA; vgmstream->meta_type = meta_SAT_BAKA;
/* open the file for reading */ if (!vgmstream_open_stream(vgmstream, sf, start_offset))
{ goto fail;
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; return vgmstream;
/* clean up anything we may have opened */
fail: fail:
if (vgmstream) close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }

View File

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

View File

@ -1,44 +1,47 @@
#include "meta.h" #include "meta.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* XMU - found in Alter Echo (Xbox) */ /* XMU - found in Alter Echo (Xbox) */
VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_xmu(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
size_t start_offset; size_t start_offset;
int loop_flag, channel_count; int loop_flag, channel_count;
size_t data_size; size_t data_size;
/* check extension */ /* checks */
if (!check_extensions(streamFile,"xmu")) if (!is_id32be(0x00,sf, "XMU "))
goto fail; goto fail;
if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */ if (!check_extensions(sf,"xmu"))
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */ goto fail;
goto fail;
if (!is_id32be(0x08,sf, "FRMT"))
start_offset = 0x800; goto fail;
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" */ start_offset = 0x800;
channel_count = read_u8(0x14,sf); /* always stereo files */
/* build the VGMSTREAM */ loop_flag = read_u8(0x16,sf); /* no Loop found atm */
vgmstream = allocate_vgmstream(channel_count,loop_flag); data_size = read_u32le(0x7FC,sf); /* next to "DATA" */
if (!vgmstream) goto fail;
/* build the VGMSTREAM */
vgmstream->meta_type = meta_XMU; vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream->sample_rate = read_32bitLE(0x10,streamFile); if (!vgmstream) goto fail;
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->loop_start_sample = 0; vgmstream->meta_type = meta_XMU;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = xbox_ima_bytes_to_samples(data_size, vgmstream->channels);
vgmstream->coding_type = coding_XBOX_IMA; vgmstream->loop_start_sample = 0;
vgmstream->layout_type = layout_none; vgmstream->loop_end_sample = vgmstream->num_samples;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) vgmstream->coding_type = coding_XBOX_IMA;
goto fail; vgmstream->layout_type = layout_none;
return vgmstream;
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
fail: goto fail;
close_vgmstream(vgmstream); return vgmstream;
return NULL;
} 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_ubi_jade_container,
init_vgmstream_seg, init_vgmstream_seg,
init_vgmstream_nds_strm_ffta2, init_vgmstream_nds_strm_ffta2,
init_vgmstream_str_asr, init_vgmstream_knon,
init_vgmstream_gca, init_vgmstream_gca,
init_vgmstream_spt_spd, init_vgmstream_spt_spd,
init_vgmstream_ish_isd, init_vgmstream_ish_isd,
@ -204,7 +204,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_apple_caff, init_vgmstream_apple_caff,
init_vgmstream_pc_mxst, init_vgmstream_pc_mxst,
init_vgmstream_sab, init_vgmstream_sab,
init_vgmstream_exakt_sc,
init_vgmstream_wii_bns, init_vgmstream_wii_bns,
init_vgmstream_wii_was, init_vgmstream_wii_was,
init_vgmstream_pona_3do, init_vgmstream_pona_3do,
@ -235,7 +234,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_ps2_wad, init_vgmstream_ps2_wad,
init_vgmstream_dsp_xiii, init_vgmstream_dsp_xiii,
init_vgmstream_dsp_cabelas, init_vgmstream_dsp_cabelas,
init_vgmstream_ps2_adm,
init_vgmstream_lpcm_shade, init_vgmstream_lpcm_shade,
init_vgmstream_dsp_bdsp, init_vgmstream_dsp_bdsp,
init_vgmstream_ps2_vms, init_vgmstream_ps2_vms,
@ -316,7 +314,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_va3, init_vgmstream_va3,
init_vgmstream_mta2, init_vgmstream_mta2,
init_vgmstream_mta2_container, init_vgmstream_mta2_container,
init_vgmstream_ngc_ulw,
init_vgmstream_xa_xa30, init_vgmstream_xa_xa30,
init_vgmstream_xa_04sw, init_vgmstream_xa_04sw,
init_vgmstream_ea_bnk, init_vgmstream_ea_bnk,
@ -540,7 +537,10 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_raw_pcm, /* .raw raw PCM */ init_vgmstream_raw_pcm, /* .raw raw PCM */
init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ init_vgmstream_s14_sss, /* .s14/sss raw siren14 */
init_vgmstream_raw_al, /* .al/al2 raw A-LAW */ 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_zwdsp, /* fake format */
init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */
init_vgmstream_baf_badrip, /* crap, to be removed */ init_vgmstream_baf_badrip, /* crap, to be removed */
init_vgmstream_rxws_badrip, /* crap, to be removed */ init_vgmstream_rxws_badrip, /* crap, to be removed */
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG

View File

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