From 45accf38ae386542cd453e186d98447dfc9d5888 Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Sun, 7 Jul 2019 15:49:12 -0700 Subject: [PATCH] Updated VGMStream to r1050-2359-ge1184142 --- .../libvgmstream.xcodeproj/project.pbxproj | 4 + .../vgmstream/vgmstream/ext_libs/clHCA.c | 20 ++- Frameworks/vgmstream/vgmstream/src/formats.c | 4 + Frameworks/vgmstream/vgmstream/src/meta/awb.c | 119 ++++++++++++++++++ .../vgmstream/vgmstream/src/meta/genh.c | 4 + Frameworks/vgmstream/vgmstream/src/meta/hca.c | 24 ++-- .../vgmstream/vgmstream/src/meta/hca_keys.h | 17 ++- .../vgmstream/vgmstream/src/meta/meta.h | 3 + .../vgmstream/vgmstream/src/meta/txth.c | 76 ++++++++++- .../vgmstream/vgmstream/src/vgmstream.c | 1 + 10 files changed, 256 insertions(+), 16 deletions(-) create mode 100644 Frameworks/vgmstream/vgmstream/src/meta/awb.c diff --git a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj b/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj index e564b17c2..55e22ad15 100644 --- a/Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj +++ b/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 = ""; }; 839E21DF1F2EDAF000EE54D7 /* vorbis_custom_utils_sk.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vorbis_custom_utils_sk.c; sourceTree = ""; }; 839E21EA1F2EDB0500EE54D7 /* sk_aud.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sk_aud.c; sourceTree = ""; }; + 83A16D2722D2ADE700B90C4C /* awb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = awb.c; sourceTree = ""; }; 83A21F7A201D895B000F04B9 /* blocked_xvag.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = blocked_xvag.c; sourceTree = ""; }; 83A21F7C201D897F000F04B9 /* atx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = atx.c; sourceTree = ""; }; 83A21F7D201D8980000F04B9 /* xwc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xwc.c; sourceTree = ""; }; @@ -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 */, diff --git a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c b/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c index 5a7ae9623..1877d8127 100644 --- a/Frameworks/vgmstream/vgmstream/ext_libs/clHCA.c +++ b/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; } diff --git a/Frameworks/vgmstream/vgmstream/src/formats.c b/Frameworks/vgmstream/vgmstream/src/formats.c index bb47f437f..5d8015d50 100644 --- a/Frameworks/vgmstream/vgmstream/src/formats.c +++ b/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", diff --git a/Frameworks/vgmstream/vgmstream/src/meta/awb.c b/Frameworks/vgmstream/vgmstream/src/meta/awb.c new file mode 100644 index 000000000..a9e546a62 --- /dev/null +++ b/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; +} diff --git a/Frameworks/vgmstream/vgmstream/src/meta/genh.c b/Frameworks/vgmstream/vgmstream/src/meta/genh.c index 509ab1017..3fe328881 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/genh.c +++ b/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; diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca.c b/Frameworks/vgmstream/vgmstream/src/meta/hca.c index cfcd4f89f..fa87c62eb 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca.c +++ b/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: diff --git a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h b/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h index de11bcc69..8710a4335 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/hca_keys.h +++ b/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_*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/meta.h b/Frameworks/vgmstream/vgmstream/src/meta/meta.h index db8804058..512362813 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/meta.h +++ b/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*/ diff --git a/Frameworks/vgmstream/vgmstream/src/meta/txth.c b/Frameworks/vgmstream/vgmstream/src/meta/txth.c index 69a2e1cd9..fecb8b052 100644 --- a/Frameworks/vgmstream/vgmstream/src/meta/txth.c +++ b/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; diff --git a/Frameworks/vgmstream/vgmstream/src/vgmstream.c b/Frameworks/vgmstream/vgmstream/src/vgmstream.c index 97fac729e..669864b8c 100644 --- a/Frameworks/vgmstream/vgmstream/src/vgmstream.c +++ b/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 */