Merge pull request #1017 from bnnm/misc

- Fix some HCA v3 [Megaton Musashi (Switch)]
- Add ADX key, tweaks
- Add .res extension
- cleanup
This commit is contained in:
bnnm 2021-11-18 00:29:17 +01:00 committed by GitHub
commit 1355279f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 645 additions and 649 deletions

View File

@ -238,7 +238,7 @@ it tends to noticeably slow down opening folders, also seems to crash and leave
unusable when reading unsupported formats like Switch Opus (rather than Ogg Opus).
Renaming extensions should prevent those issues, or just uninstall those *Web
Media Extension* better experience anyway.
Media Extension* for better experience anyway.
#### Fallout SFX .ACM
Due to technical limitations, to play Fallout 1 SFX you need to rename them from

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

@ -545,7 +545,7 @@
<ClCompile Include="meta\sps_n1.c" />
<ClCompile Include="meta\spt_spd.c" />
<ClCompile Include="meta\stm.c" />
<ClCompile Include="meta\str_asr.c" />
<ClCompile Include="meta\knon.c" />
<ClCompile Include="meta\str_snds.c" />
<ClCompile Include="meta\str_wav.c" />
<ClCompile Include="meta\strm_abylight.c" />

View File

@ -1117,7 +1117,7 @@
<ClCompile Include="meta\stm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\str_asr.c">
<ClCompile Include="meta\knon.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\str_snds.c">

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

@ -2,46 +2,44 @@
#include "../coding/coding.h"
/* .DSF - from Ocean game(s?) [Last Rites (PC)] */
VGMSTREAM * init_vgmstream_dsf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_dsf(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate;
int loop_flag, channels, sample_rate;
size_t data_size;
/* checks */
if (!check_extensions(streamFile, "dsf"))
if (!is_id32be(0x00,sf, "OCEA") || !is_id64be(0x04,sf, "N DSA\0\0\0"))
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" */
if (!check_extensions(sf, "dsf"))
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;
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(channel_count, loop_flag);
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 / channel_count) * 14); /* bytes-to-samples */
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,streamFile);
read_string(vgmstream->stream_name,0x20+1, 0x26,sf);
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;

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

@ -4,40 +4,39 @@
/* 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;
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 = streamFile->stream_index;
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!check_extensions(streamFile, "h4m"))
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 (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" */
if (!check_extensions(sf, "h4m"))
goto fail;
/* header */
start_offset = read_32bitBE(0x10, streamFile); /* header_size */
start_offset = read_u32be(0x10, sf); /* header_size */
if (start_offset != 0x44) /* known size */
goto fail;
if (read_32bitBE(0x14, streamFile) != get_streamfile_size(streamFile) - start_offset) /* body_size */
if (read_u32be(0x14, sf) != get_streamfile_size(sf) - start_offset) /* body_size */
goto fail;
if (read_32bitBE(0x18, streamFile) == 0) /* blocks */
if (read_u32be(0x18, sf) == 0) /* blocks */
goto fail;
/* 0x1c: video_frames */
if (read_32bitBE(0x20, streamFile) == 0) /* audio_frames */
if (read_u32be(0x20, sf) == 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 */
if (read_u32be(0x30, sf) == 0) /* max_audio_frame_size */
goto fail;
/* 0x34: hres */
/* 0x36: vres */
@ -45,12 +44,12 @@ VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
/* 0x39: v_srate */
/* 0x3a: unk3A (0 or 0x12) */
/* 0x3b: unk3B (0) */
channel_count = read_8bit(0x3c,streamFile);
if (read_8bit(0x3d,streamFile) != 16) /* bitdepth */
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 = (uint8_t)read_8bit(0x3e,streamFile); /* flags? */
extra_tracks = read_8bit(0x3f,streamFile);
sample_rate = read_32bitBE(0x40,streamFile);
format = read_u8(0x3e,sf); /* flags? */
extra_tracks = read_u8(0x3f,sf);
sample_rate = read_s32be(0x40,sf);
loop_flag = 0;
@ -66,7 +65,7 @@ VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = get_streamfile_size(streamFile) / total_subsongs; /* approx... */
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;
@ -84,7 +83,7 @@ VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
goto fail;
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
/* calc num_samples manually */
@ -96,7 +95,7 @@ VGMSTREAM * init_vgmstream_h4m(STREAMFILE *streamFile) {
block_update(vgmstream->next_block_offset,vgmstream);
vgmstream->num_samples += vgmstream->current_block_samples;
}
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
while (vgmstream->next_block_offset < get_streamfile_size(sf));
vgmstream->full_block_size = 0; /* extra cleanup for H4M */
block_update(start_offset, vgmstream);
}

65
src/meta/knon.c Normal file
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

@ -4,33 +4,39 @@
/* OGL - Shin'en custom Vorbis [Jett Rocket (Wii), FAST Racing NEO (WiiU)] */
VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_ogl(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
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;
/* check extension, case insensitive */
if (!check_extensions(streamFile,"ogl"))
/* 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_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_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 */
channel_count = read_8bit (0x21,streamFile);
sample_rate = read_32bitLE(0x22,streamFile);
channels = read_u8 (0x21,sf);
sample_rate = read_s32le(0x22,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = sample_rate;
@ -45,7 +51,7 @@ VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
vgmstream->coding_type = coding_VORBIS_custom;
vgmstream->codec_data = init_vorbis_custom(streamFile, 0x14, VORBIS_OGL, &cfg);
vgmstream->codec_data = init_vorbis_custom(sf, 0x14, VORBIS_OGL, &cfg);
if (!vgmstream->codec_data) goto fail;
start_offset = cfg.data_start_offset;
@ -56,13 +62,13 @@ VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile) {
/* non-looping files do this */
if (!num_samples) {
uint32_t avg_bitrate = read_32bitLE(0x2a,streamFile); /* inside id packet */
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, streamFile, start_offset) )
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -1,31 +1,32 @@
#include "meta.h"
/* IMU - found in Alter Echo (PS2) */
VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_ps2_omu(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
int loop_flag, channels;
/* check extension */
if ( !check_extensions(streamFile,"omu") )
/* checks */
if (!is_id32be(0x00,sf, "OMU "))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4F4D5520 && /* "OMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
if (!check_extensions(sf,"omu"))
goto fail;
if (!is_id32be(0x08,sf, "FRMT"))
goto fail;
loop_flag = 1;
channel_count = (int)read_8bit(0x14,streamFile);
channels = read_u8(0x14,sf);
start_offset = 0x40;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
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->num_samples = (read_u32le(0x3C,sf) / (vgmstream->channels*2));
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
@ -34,8 +35,7 @@ VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile) {
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;
return vgmstream;

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;
/* 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;
/* (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;
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

@ -3,45 +3,45 @@
#include "../layout/layout.h"
/* STHD - Dream Factory .stx [Kakuto Chojin (Xbox)] */
VGMSTREAM * init_vgmstream_sthd(STREAMFILE *streamFile) {
VGMSTREAM * init_vgmstream_sthd(STREAMFILE *sf) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
if (!check_extensions(streamFile, "stx"))
if (!is_id32be(0x00,sf, "STHD"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x53544844) /* "STHD" */
if (!check_extensions(sf, "stx"))
goto fail;
/* first block has special values */
if (read_32bitLE(0x04,streamFile) != 0x0800 &&
read_32bitLE(0x0c,streamFile) != 0x0001 &&
read_32bitLE(0x14,streamFile) != 0x0000)
if (read_u16le(0x04,sf) != 0x0800 ||
read_u32le(0x0c,sf) != 0x0001 ||
read_u32le(0x14,sf) != 0x0000)
goto fail;
channel_count = read_16bitLE(0x06,streamFile);
loop_flag = read_16bitLE(0x18,streamFile) != -1;
start_offset = 0x800;
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_32bitLE(0x20, streamFile); /* repeated ~8 times? */
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,streamFile,start_offset))
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,streamFile);
int loop_end_block = (uint16_t)read_16bitLE(0x1c,streamFile);
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;
@ -55,7 +55,7 @@ VGMSTREAM * init_vgmstream_sthd(STREAMFILE *streamFile) {
vgmstream->num_samples += xbox_ima_bytes_to_samples(vgmstream->current_block_size, 1);
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);
}

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

@ -2,31 +2,34 @@
#include "../coding/coding.h"
/* XMU - found in Alter Echo (Xbox) */
VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
VGMSTREAM* init_vgmstream_xmu(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
size_t start_offset;
int loop_flag, channel_count;
size_t data_size;
/* check extension */
if (!check_extensions(streamFile,"xmu"))
/* checks */
if (!is_id32be(0x00,sf, "XMU "))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x584D5520 && /* "XMU " */
read_32bitBE(0x08,streamFile) != 0x46524D54) /* "FRMT" */
if (!check_extensions(sf,"xmu"))
goto fail;
if (!is_id32be(0x08,sf, "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" */
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_32bitLE(0x10,streamFile);
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;
@ -34,7 +37,7 @@ VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_XBOX_IMA;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

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

@ -431,7 +431,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,