Просмотр исходного кода

Updated VGMStream to r1050-2359-ge1184142

master
Christopher Snowhill 11 месяцев назад
Родитель
Сommit
45accf38ae
10 измененных файлов: 256 добавлений и 16 удалений
  1. +4
    -0
      Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj
  2. +16
    -4
      Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c
  3. +4
    -0
      Frameworks/vgmstream/vgmstream/src/formats.c
  4. +119
    -0
      Frameworks/vgmstream/vgmstream/src/meta/awb.c
  5. +4
    -0
      Frameworks/vgmstream/vgmstream/src/meta/genh.c
  6. +15
    -9
      Frameworks/vgmstream/vgmstream/src/meta/hca.c
  7. +15
    -2
      Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h
  8. +3
    -0
      Frameworks/vgmstream/vgmstream/src/meta/meta.h
  9. +75
    -1
      Frameworks/vgmstream/vgmstream/src/meta/txth.c
  10. +1
    -0
      Frameworks/vgmstream/vgmstream/src/vgmstream.c

+ 4
- 0
Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj Просмотреть файл

@@ -479,6 +479,7 @@
839E21E81F2EDAF100EE54D7 /* mpeg_decoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 839E21DE1F2EDAF000EE54D7 /* mpeg_decoder.h */; };
839E21E91F2EDAF100EE54D7 /* vorbis_custom_utils_sk.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */; };
839E21EB1F2EDB0600EE54D7 /* sk_aud.c in Sources */ = {isa = PBXBuildFile; fileRef = 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */; };
83A16D2B22D2ADE800B90C4C /* awb.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A16D2722D2ADE700B90C4C /* awb.c */; };
83A21F7B201D895B000F04B9 /* blocked_xvag.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A21F7A201D895B000F04B9 /* blocked_xvag.c */; };
83A21F85201D8981000F04B9 /* atx.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A21F7C201D897F000F04B9 /* atx.c */; };
83A21F86201D8981000F04B9 /* xwc.c in Sources */ = {isa = PBXBuildFile; fileRef = 83A21F7D201D8980000F04B9 /* xwc.c */; };
@@ -1142,6 +1143,7 @@
839E21DE1F2EDAF000EE54D7 /* mpeg_decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mpeg_decoder.h; sourceTree = "<group>"; };
839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_sk.c; sourceTree = "<group>"; };
839E21EA1F2EDB0500EE54D7 /* sk_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sk_aud.c; sourceTree = "<group>"; };
83A16D2722D2ADE700B90C4C /* awb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awb.c; sourceTree = "<group>"; };
83A21F7A201D895B000F04B9 /* blocked_xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_xvag.c; sourceTree = "<group>"; };
83A21F7C201D897F000F04B9 /* atx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atx.c; sourceTree = "<group>"; };
83A21F7D201D8980000F04B9 /* xwc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwc.c; sourceTree = "<group>"; };
@@ -1516,6 +1518,7 @@
8306B0D520984590000302D4 /* atsl.c */,
83A21F7C201D897F000F04B9 /* atx.c */,
83EED5D2203A8BC7008BEB45 /* aus.c */,
83A16D2722D2ADE700B90C4C /* awb.c */,
8306B0C32098458C000302D4 /* awc_xma_streamfile.h */,
83AA5D201F6E2F9B0020821C /* awc.c */,
836F6E3618BDC2180095E648 /* baf.c */,
@@ -2406,6 +2409,7 @@
83A21F8B201D8982000F04B9 /* sps_n1.c in Sources */,
836F6F9E18BDC2190095E648 /* mus_acm.c in Sources */,
83709E0E1ECBC1C3005C03D3 /* psv_decoder.c in Sources */,
83A16D2B22D2ADE800B90C4C /* awb.c in Sources */,
831BA6191EAC61A500CF89B0 /* ogl.c in Sources */,
83709E061ECBC1A4005C03D3 /* mc3.c in Sources */,
831BA61F1EAC61A500CF89B0 /* x360_cxs.c in Sources */,


+ 16
- 4
Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c Просмотреть файл

@@ -925,10 +925,11 @@ void clHCA_SetKey(clHCA *hca, unsigned long long keycode) {
}

int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size) {
const int frame_samples = HCA_SUBFRAMES_PER_FRAME * HCA_SAMPLES_PER_SUBFRAME;
const float scale = 32768.0f;
unsigned int ch, sf, s;
int status;
int clips = 0, blanks = 0;
int clips = 0, blanks = 0, channel_blanks[HCA_MAX_CHANNELS] = {0};


/* first blocks can be empty/silent, check all bytes but sync/crc */
@@ -965,8 +966,10 @@ int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size) {
}
else {
signed int psample = (signed int) (fsample * scale);
if (psample == 0 || psample == -1)
if (psample == 0 || psample == -1) {
blanks++;
channel_blanks[ch]++;
}
}
}
}
@@ -974,13 +977,22 @@ int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size) {

/* the more clips the less likely block was correctly decrypted */
if (clips == 1)
clips++;
clips++; /* signal not full score */
if (clips > 1)
return clips;

/* if block is silent result is not useful */
if (blanks == hca->channels * HCA_SUBFRAMES_PER_FRAME * HCA_SAMPLES_PER_SUBFRAME)
if (blanks == hca->channels * frame_samples)
return 0;

/* some bad keys make left channel null and right normal enough (due to joint stereo stuff);
* it's possible real keys could do this but don't give full marks just in case */
if (hca->channels >= 2) {
/* only check main L/R, other channels like BL/BR are probably not useful */
if (channel_blanks[0] == frame_samples && channel_blanks[1] != frame_samples) /* maybe should check max/min values? */
return 3;
}

/* block may be correct (but wrong keys can get this too and should test more blocks) */
return 1;
}


+ 4
- 0
Frameworks/vgmstream/vgmstream/src/formats.c Просмотреть файл

@@ -38,6 +38,7 @@ static const char* extension_list[] = {
"adw",
"adx",
"afc",
"afs2",
"agsc",
"ahx",
"ahv",
@@ -68,6 +69,7 @@ static const char* extension_list[] = {
"atx",
"aud",
"aus",
"awb",
"awc",
"b1s",
@@ -214,6 +216,7 @@ static const char* extension_list[] = {
"kvs",
"l",
"l00", //txth/reserved [Disney's Dinosaur (PS2)]
"laac", //fake extension for .aac (tri-Ace)
"laif", //fake extension for .aif (various)
"laiff", //fake extension for .aiff
@@ -311,6 +314,7 @@ static const char* extension_list[] = {
"otm",
"ovb",
"p04", //txth/reserved [Psychic Force 2012 (DC)]
"p1d", //txth/reserved [Farming Simulator 18 (3DS)]
"p2a", //txth/reserved [Thunderhawk Operation Phoenix (PS2)]
"p2bt",


+ 119
- 0
Frameworks/vgmstream/vgmstream/src/meta/awb.c Просмотреть файл

@@ -0,0 +1,119 @@
#include "meta.h"
#include "../coding/coding.h"
typedef enum { ADX, HCA, AT9, VAG } awb_type;
/* CRI AFS2, container of streaming ADX or HCA, often (but not always) together with a .acb CUE */
VGMSTREAM * init_vgmstream_awb(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL;
STREAMFILE *temp_streamFile = NULL;
off_t offset, subfile_offset, subfile_next;
size_t subfile_size;
int total_subsongs, target_subsong = streamFile->stream_index;
//uint32_t flags;
uint16_t alignment, subkey;
awb_type type;
char *extension = NULL;
/* checks
* .awb: standard
* .afs2: sometimes [Okami HD (PS4)] */
if (!check_extensions(streamFile, "awb,afs2"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x41465332) /* "AFS2" */
goto fail;
//flags = read_32bitLE(0x08,streamFile);
total_subsongs = read_32bitLE(0x08,streamFile);
alignment = (uint16_t)read_16bitLE(0x0c,streamFile);
subkey = (uint16_t)read_16bitLE(0x0e,streamFile);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
offset = 0x10;
/* id(?) table: skip */
offset += total_subsongs * 0x02;
/* offset table: find target
* offset are absolute but sometimes misaligned (specially first that just points to offset table end) */
{
off_t file_size = get_streamfile_size(streamFile);
offset += (target_subsong-1) * 0x04;
/* last offset is always file end, so table entries = total_subsongs+1 */
subfile_offset = read_32bitLE(offset+0x00,streamFile);
subfile_next = read_32bitLE(offset+0x04,streamFile);
subfile_offset += (subfile_offset % alignment) ?
alignment - (subfile_offset % alignment) : 0;
subfile_next += (subfile_next % alignment) && subfile_next < file_size ?
alignment - (subfile_next % alignment) : 0;
subfile_size = subfile_next - subfile_offset;
//todo: flags & 0x200 are uint16 offsets?
}
//;VGM_LOG("TXTH: subfile offset=%lx + %x\n", subfile_offset, subfile_size);
/* autodetect as there isn't anything, plus can mix types
* (waveid<>codec info is usually in the companion .acb) */
if ((uint16_t)read_16bitBE(subfile_offset, streamFile) == 0x8000) { /* ADX id */
type = ADX;
extension = "adx";
}
else if (((uint32_t)read_32bitBE(subfile_offset,streamFile) & 0x7f7f7f7f) == 0x48434100) { /* "HCA\0" */
type = HCA;
extension = "hca";
}
else if (read_32bitBE(subfile_offset,streamFile) == 0x52494646) { /* "RIFF" */
type = AT9;
extension = "at9";
}
else if (read_32bitBE(subfile_offset,streamFile) == 0x56414770) { /* "VAGp" */
type = VAG;
extension = "vag";
}
else {
goto fail;
}
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, extension);
if (!temp_streamFile) goto fail;
switch(type) {
case HCA: /* most common */
vgmstream = init_vgmstream_hca_subkey(temp_streamFile, subkey);
if (!vgmstream) goto fail;
break;
case ADX: /* Okami HD (PS4) */
vgmstream = init_vgmstream_adx(temp_streamFile);
if (!vgmstream) goto fail;
break;
case AT9: /* Ukiyo no Roushi (Vita) */
vgmstream = init_vgmstream_riff(temp_streamFile);
if (!vgmstream) goto fail;
break;
case VAG: /* Ukiyo no Roushi (Vita) */
vgmstream = init_vgmstream_vag(temp_streamFile);
if (!vgmstream) goto fail;
break;
default:
goto fail;
}
//todo: could try to get name in .acb for this waveid
vgmstream->num_streams = total_subsongs;
close_streamfile(temp_streamFile);
return vgmstream;
fail:
close_streamfile(temp_streamFile);
close_vgmstream(vgmstream);
return NULL;
}

+ 4
- 0
Frameworks/vgmstream/vgmstream/src/meta/genh.c Просмотреть файл

@@ -189,6 +189,10 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
}

/* to avoid problems with dual stereo files (_L+_R) for codecs with stereo modes */
if (coding == coding_YAMAHA && genh.channels == 1)
coding = coding_YAMAHA_int;

/* setup adpcm */
if (coding == coding_YAMAHA || coding == coding_YAMAHA_int) {
int ch;


+ 15
- 9
Frameworks/vgmstream/vgmstream/src/meta/hca.c Просмотреть файл

@@ -2,13 +2,18 @@
#include "hca_keys.h"
#include "../coding/coding.h"

static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_keycode);
static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_keycode, uint16_t subkey);

VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile) {
return init_vgmstream_hca_subkey(streamFile, 0x0000);
}

VGMSTREAM * init_vgmstream_hca_subkey(STREAMFILE *streamFile, uint16_t subkey) {
VGMSTREAM * vgmstream = NULL;
hca_codec_data * hca_data = NULL;
unsigned long long keycode = 0;


/* checks */
if ( !check_extensions(streamFile, "hca"))
return NULL;
@@ -34,7 +39,7 @@ VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile) {
keycode = key * ( ((uint64_t)sub << 16u) | ((uint16_t)~sub + 2u) );
}
else {
find_hca_key(hca_data, &keycode);
find_hca_key(hca_data, &keycode, subkey);
}

clHCA_SetKey(hca_data->handle, keycode); //maybe should be done through hca_decoder.c?
@@ -96,7 +101,7 @@ static inline void test_key(hca_codec_data * hca_data, uint64_t key, uint16_t su
}

/* Try to find the decryption key from a list. */
static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_keycode) {
static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_keycode, uint16_t subkey) {
const size_t keys_length = sizeof(hcakey_list) / sizeof(hcakey_info);
int best_score = -1;
int i,j;
@@ -109,18 +114,19 @@ static void find_hca_key(hca_codec_data * hca_data, unsigned long long * out_key
size_t subkeys_size = hcakey_list[i].subkeys_size;
const uint16_t *subkeys = hcakey_list[i].subkeys;

if (subkeys_size > 0) {
/* try once with external subkey, if any */
test_key(hca_data, key, subkey, &best_score, out_keycode);
if (best_score == 1) /* best possible score */
goto done;

/* try subkey list */
if (subkeys_size > 0 && subkey == 0) {
for (j = 0; j < subkeys_size; j++) {
test_key(hca_data, key, subkeys[j], &best_score, out_keycode);
if (best_score == 1) /* best possible score */
goto done;
}
}
else {
test_key(hca_data, key, 0, &best_score, out_keycode);
if (best_score == 1) /* best possible score */
goto done;
}
}

done:


+ 15
- 2
Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h Просмотреть файл

@@ -259,10 +259,10 @@ static const hcakey_info hcakey_list[] = {
{6667}, // 0000000000001A0B
/* Libra of Precatus (Android) */
{0x6D8EFB700870FCD4}, // 6D8EFB700870FCD4
{7894523655423589588}, // 6D8EFB700870FCD4
/* Mashiro Witch (Android) */
{0x55D11D3349495204}, // 55D11D3349495204
{6183755869466481156}, // 55D11D3349495204
/* Iris Mysteria! (Android) */
{62049655719861786}, // 00DC71D5479E1E1A
@@ -279,8 +279,21 @@ static const hcakey_info hcakey_list[] = {
/* Fantasy Life Online (Android) */
{123456789}, // 00000000075BCD15
/* Wonder Gravity (Android) */
{30623969886430861}, // 006CCC569EB1668D
/* Ryu ga Gotoku Online (Android) */
{59361939}, // 000000000389CA93
/* Sengoku BASARA Battle Party (Android) */
{836575858265}, // 000000C2C7CE8E59
/* DAME x PRINCE (Android) */
{217019410378917901}, // 030302010100080D
/* Dragalia Lost (Cygames) [iOS/Android] */
{2967411924141, subkeys_dgl, sizeof(subkeys_dgl) / sizeof(subkeys_dgl[0]) }, // 000002B2E7889CAD
};
#endif/*_HCA_KEYS_H_*/

+ 3
- 0
Frameworks/vgmstream/vgmstream/src/meta/meta.h Просмотреть файл

@@ -131,6 +131,7 @@ VGMSTREAM * init_vgmstream_ogg_vorbis_callbacks(STREAMFILE *streamFile, ov_callb
#endif

VGMSTREAM * init_vgmstream_hca(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_hca_subkey(STREAMFILE *streamFile, uint16_t subkey);

#ifdef VGM_USE_FFMPEG
VGMSTREAM * init_vgmstream_ffmpeg(STREAMFILE *streamFile);
@@ -858,4 +859,6 @@ VGMSTREAM * init_vgmstream_bwav(STREAMFILE * streamFile);

VGMSTREAM * init_vgmstream_opus_prototype(STREAMFILE * streamFile);

VGMSTREAM * init_vgmstream_awb(STREAMFILE * streamFile);

#endif /*_META_H*/

+ 75
- 1
Frameworks/vgmstream/vgmstream/src/meta/txth.c Просмотреть файл

@@ -296,6 +296,10 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
}
/* to avoid problems with dual stereo files (_L+_R) for codecs with stereo modes */
if (coding == coding_YAMAHA && txth.channels == 1)
coding = coding_YAMAHA_int;
/* setup adpcm */
if (coding == coding_YAMAHA || coding == coding_YAMAHA_int) {
int ch;
@@ -1241,6 +1245,76 @@ static int is_string_field(const char * val, const char * cmp) {
return is_substring(val, cmp, 1);
}
static uint16_t get_string_wchar(const char * val, int pos, int *csize) {
uint16_t wchar = 0;
if ((val[pos] & 0x80) && val[pos+1] != '\0') {
wchar = (((val[pos] << 8u) & 0xFF00) | (val[pos+1] & 0xFF));
//wchar = ((((uint16_t)val[pos] << 8u)) | ((uint16_t)val[pos+1]));
if (csize) *csize = 2;
if (wchar >= 0xc380 && wchar <= 0xc39f) /* ghetto lowercase for common letters */
wchar += 0x20;
} else {
wchar = val[pos];
if (csize) *csize = 1;
if (wchar >= 0x41 && wchar <= 0x5a)
wchar += 0x20;
}
return wchar;
}
static int is_string_match(const char * text, const char * pattern) {
int t_pos = 0, p_pos = 0;
int p_size, t_size;
uint16_t p_char, t_char;
;VGM_LOG("TXTH: match '%s' vs '%s'\n", text,pattern);
/* compares 2 strings (case insensitive, to a point) allowing wildcards
* ex. for "test": match = "Test*", "*est", "*teSt","T*ES*T"; fail = "tst", "teest"
*
* does some bleh UTF-8 handling, consuming dual bytes if needed (codepages set char's eighth bit).
* as such it's slower than standard funcs, but it's not like we need it to be ultra fast.
* */
while (text[t_pos] != '\0' && pattern[p_pos] != '\0') {
//;VGM_LOG("TXTH: compare '%s' vs '%s'\n", (text+t_pos), (pattern+p_pos));
if (pattern[p_pos] == '*') {
/* consume text wchars until one matches next pattern char */
p_pos++;
p_char = get_string_wchar(pattern, p_pos, NULL); /* stop char, or null */
while(text[t_pos] != '\0') {
t_char = get_string_wchar(text, t_pos, &t_size);
;VGM_LOG("TXTH: consume %i '%s'\n", t_size, (text+t_pos) );
if (t_char == p_char)
break;
t_pos += t_size;
}
}
else if (pattern[p_pos] == '?') {
/* skip next text wchar */
get_string_wchar(text, t_pos, &t_size);
p_pos++;
t_pos += t_size;
}
else { /* must match 1:1 */
t_char = get_string_wchar(text, t_pos, &t_size);
p_char = get_string_wchar(pattern, p_pos, &p_size);
if (p_char != t_char)
break;
p_pos += p_size;
t_pos += t_size;
}
}
//;VGM_LOG("TXTH: match '%s' vs '%s' = %s\n", text,pattern, (text[t_pos] == '\0' && pattern[p_pos] == '\0') ? "true" : "false");
/* either all chars consumed/matched and both pos point to null, or one didn't so string didn't match */
return text[t_pos] == '\0' && pattern[p_pos] == '\0';
}
static int parse_string(STREAMFILE * streamFile, txth_header * txth, const char * val, char * str) {
int n = 0;
@@ -1350,7 +1424,7 @@ static int parse_name_table(txth_header * txth, char * name_list) {
//;VGM_LOG("TXTH: compare name '%s'\n", key);
/* parse values if key (name) matches default ("") or filename with/without extension */
if (key[0]=='\0' || strcasecmp(key, filename)==0 || strcasecmp(key, basename)==0) {
if (key[0]=='\0' || is_string_match(filename, key) || is_string_match(basename, key)) {
int n;
char subval[TXT_LINE_MAX];
const char *current = val;


+ 1
- 0
Frameworks/vgmstream/vgmstream/src/vgmstream.c Просмотреть файл

@@ -482,6 +482,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_fsb5_fev_bank,
init_vgmstream_bwav,
init_vgmstream_opus_prototype,
init_vgmstream_awb,

/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */


Загрузка…
Отмена
Сохранить