From cf36348b773b3601ed4784e19a07c7fd3d512e15 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 26 Aug 2021 19:39:58 +0200 Subject: [PATCH] add extra user logs --- src/meta/adx.c | 4 +-- src/meta/bnsf.c | 2 +- src/meta/fsb5.c | 10 +++---- src/meta/hca.c | 7 +++-- src/meta/riff.c | 6 ++++- src/meta/sqex_scd.c | 6 ++++- src/meta/sqex_sead.c | 6 +++-- src/meta/txth.c | 4 +-- src/meta/ubi_bao.c | 17 +++++++----- src/meta/ubi_sb.c | 13 ++++----- src/meta/wwise.c | 17 +++++++----- src/meta/xsh_xsd_xss.c | 4 +-- src/util/log.c | 13 +++++++++ src/util/log.h | 60 +++++++++++++++++++----------------------- 14 files changed, 100 insertions(+), 69 deletions(-) diff --git a/src/meta/adx.c b/src/meta/adx.c index 3d127145..62937b73 100644 --- a/src/meta/adx.c +++ b/src/meta/adx.c @@ -83,14 +83,14 @@ VGMSTREAM* init_vgmstream_adx_subkey(STREAMFILE* sf, uint16_t subkey) { coding_type = coding_CRI_ADX_enc_8; version = 0x0400; } - VGM_ASSERT(version != 0x0400, "ADX: keystring not found\n"); + vgm_asserti(version != 0x0400, "ADX: decryption keystring not found\n"); } else if (version == 0x0409) { if (find_adx_key(sf, 9, &xor_start, &xor_mult, &xor_add, subkey)) { coding_type = coding_CRI_ADX_enc_9; version = 0x0400; } - VGM_ASSERT(version != 0x0400, "ADX: keycode not found\n"); + vgm_asserti(version != 0x0400, "ADX: decryption keycode not found\n"); } /* version + extra data */ diff --git a/src/meta/bnsf.c b/src/meta/bnsf.c index 1805d106..b4693065 100644 --- a/src/meta/bnsf.c +++ b/src/meta/bnsf.c @@ -166,7 +166,7 @@ static void find_bnsf_key(STREAMFILE* sf, off_t start, g7221_codec_data* data, u } VGM_ASSERT(best_score > 0, "BNSF: best key=%.24s (score=%i)\n", best_key, best_score); - VGM_ASSERT(best_score < 0, "BNSF: key not found\n"); + vgm_asserti(best_score < 0 , "BNSF: decryption key not found\n"); } #define BNSF_MIN_KEY_LEN 3 diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index 430572a1..09d3ad85 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -72,7 +72,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { fsb5.base_header_size = (fsb5.version==0x00) ? 0x40 : 0x3C; if ((fsb5.sample_header_size + fsb5.name_table_size + fsb5.sample_data_size + fsb5.base_header_size) != get_streamfile_size(sf)) { - VGM_LOG("FSB5: bad size (%x + %x + %x + %x != %x)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(sf)); + vgm_logi("FSB5: wrong size, expected %x + %x + %x + %x vs %x (re-rip)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(sf)); goto fail; } @@ -217,7 +217,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { fsb5.channels = fsb5.channels * fsb5.layers; break; default: - VGM_LOG("FSB5: stream %i unknown flag 0x%x at %x + 0x04 (size 0x%x)\n", i, extraflag_type, (uint32_t)extraflag_offset, extraflag_size); + vgm_logi("FSB5: stream %i unknown flag 0x%x at %x + 0x04 + 0x%x (report)\n", i, extraflag_type, (uint32_t)extraflag_offset, extraflag_size); break; } } @@ -301,11 +301,11 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { break; case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */ - VGM_LOG("FSB5: FMOD_SOUND_FORMAT_PCM24 found\n"); + vgm_logi("FSB5: FMOD_SOUND_FORMAT_PCM24 found (report)\n"); goto fail; case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */ - VGM_LOG("FSB5: FMOD_SOUND_FORMAT_PCM32 found\n"); + vgm_logi("FSB5: FMOD_SOUND_FORMAT_PCM32 found (report)\n"); goto fail; case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima: Gate of Memories (PC)] */ @@ -494,7 +494,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { #endif #endif default: - VGM_LOG("FSB5: unknown codec %x found\n", fsb5.codec); + vgm_logi("FSB5: unknown codec 0x%x (report)\n", fsb5.codec); goto fail; } diff --git a/src/meta/hca.c b/src/meta/hca.c index f199872d..d7694ca9 100644 --- a/src/meta/hca.c +++ b/src/meta/hca.c @@ -30,7 +30,10 @@ VGMSTREAM* init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) { /* init vgmstream and library's context, will validate the HCA */ hca_data = init_hca(sf); - if (!hca_data) goto fail; + if (!hca_data) { + vgm_logi("HCA: unknown format (report)\n"); + goto fail; + } hca_info = hca_get_info(hca_data); @@ -184,7 +187,7 @@ static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t done: VGM_ASSERT(best_score > 1, "HCA: best key=%08x%08x (score=%i)\n", (uint32_t)((*p_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(*p_keycode & 0xFFFFFFFF), best_score); - VGM_ASSERT(best_score < 0, "HCA: key not found\n"); + vgm_asserti(best_score < 0, "HCA: decryption key not found\n"); } #ifdef HCA_BRUTEFORCE diff --git a/src/meta/riff.c b/src/meta/riff.c index e0b1fda6..c83c4802 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -279,6 +279,8 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk } default: + /* FFmpeg may play it */ + //vgm_logi("WWISE: unknown codec 0x%04x (report)\n", fmt->format); goto fail; } @@ -418,8 +420,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { } /* check for truncated RIFF */ - if (file_size != riff_size + 0x08) + if (file_size != riff_size + 0x08) { + vgm_logi("RIFF: wrong expected size (report/re-rip?)\n"); goto fail; + } /* read through chunks to verify format and find metadata */ { diff --git a/src/meta/sqex_scd.c b/src/meta/sqex_scd.c index acc012fd..83be3944 100644 --- a/src/meta/sqex_scd.c +++ b/src/meta/sqex_scd.c @@ -100,8 +100,12 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) { target_entry = i; } } - if (meta_offset == 0) goto fail; + /* SCD can contain 0 entries too */ + if (meta_offset == 0) { + vgm_logi("SQEX SCD: bank has no subsongs (ignore)\n"); + goto fail; + } } /** stream header **/ diff --git a/src/meta/sqex_sead.c b/src/meta/sqex_sead.c index 6a4a75c8..651b7cf3 100644 --- a/src/meta/sqex_sead.c +++ b/src/meta/sqex_sead.c @@ -765,7 +765,7 @@ static void parse_sead_sab_name(sead_header *sead, STREAMFILE *sf) { } -static int parse_sead(sead_header *sead, STREAMFILE *sf) { +static int parse_sead(sead_header* sead, STREAMFILE* sf) { uint32_t (*read_u32)(off_t,STREAMFILE*) = sead->big_endian ? read_u32be : read_u32le; uint16_t (*read_u16)(off_t,STREAMFILE*) = sead->big_endian ? read_u16be : read_u16le; @@ -856,8 +856,10 @@ static int parse_sead(sead_header *sead, STREAMFILE *sf) { } /* SAB can contain 0 entries too */ - if (sead->mtrl_offset == 0) + if (sead->mtrl_offset == 0) { + vgm_logi("SQEX SEAD: bank has no subsongs (ignore)\n"); goto fail; + } } /** stream header **/ diff --git a/src/meta/txth.c b/src/meta/txth.c index cfc1465d..668ad6ce 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -1391,7 +1391,7 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha return 1; fail: - VGM_LOG("TXTH: error parsing key=%s, val=%s\n", key, val); + vgm_logi("TXTH: error parsing key=%s, val=%s\n", key, val); return 0; } @@ -1843,7 +1843,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ offset += txth->base_offset; if (/*offset < 0 ||*/ offset > get_streamfile_size(sf)) { - VGM_LOG("TXTH: wrong offset %x + %x\n", offset - txth->base_offset, txth->base_offset); + vgm_logi("TXTH: wrong offset over file size (%x + %x)\n", offset - txth->base_offset, txth->base_offset); goto fail; } diff --git a/src/meta/ubi_bao.c b/src/meta/ubi_bao.c index 3268bab0..401a53ef 100644 --- a/src/meta/ubi_bao.c +++ b/src/meta/ubi_bao.c @@ -634,7 +634,7 @@ static VGMSTREAM* init_vgmstream_ubi_bao_header(ubi_bao_header* bao, STREAMFILE* VGMSTREAM* vgmstream = NULL; if (bao->total_subsongs <= 0) { - VGM_LOG("UBI BAO: no subsongs\n"); + vgm_logi("UBI BAO: bank has no subsongs (ignore)\n"); goto fail; /* not uncommon */ } @@ -1473,7 +1473,10 @@ static STREAMFILE* setup_bao_streamfile(ubi_bao_header* bao, STREAMFILE* sf) { if (bao->stream_size - bao->prefetch_size != 0) { new_sf = open_streamfile_by_filename(sf, bao->resource_name); - if (!new_sf) { VGM_LOG("UBI BAO: external stream '%s' not found\n", bao->resource_name); goto fail; } + if (!new_sf) { + vgm_logi("UBI BAO: external file '%s' not found (put together)\n", bao->resource_name); + goto fail; + } stream_segments[1] = new_sf; new_sf = open_clamp_streamfile(stream_segments[1], bao->stream_offset, (bao->stream_size - bao->prefetch_size)); @@ -1495,7 +1498,10 @@ static STREAMFILE* setup_bao_streamfile(ubi_bao_header* bao, STREAMFILE* sf) { } else if (bao->is_external) { new_sf = open_streamfile_by_filename(sf, bao->resource_name); - if (!new_sf) { VGM_LOG("UBI BAO: external stream '%s' not found\n", bao->resource_name); goto fail; } + if (!new_sf) { + vgm_logi("UBI BAO: external file '%s' not found (put together)\n", bao->resource_name); + goto fail; + } temp_sf = new_sf; new_sf = open_clamp_streamfile(temp_sf, bao->stream_offset, bao->stream_size); @@ -1884,11 +1890,10 @@ static int config_bao_version(ubi_bao_header* bao, STREAMFILE* sf) { * - 0x94: stream id? 0x9C: extra size */ case 0x002A0300: /* Watch Dogs (Wii U) */ /* similar to SC:B */ - default: /* others possibly using BAO: Just Dance, Watch_Dogs, Far Cry Primal, Far Cry 4 */ - VGM_LOG("UBI BAO: unknown BAO version %08x\n", bao->version); + default: /* others possibly using BAO: Watch_Dogs, Far Cry Primal, Far Cry 4 */ + vgm_logi("UBI BAO: unknown BAO version %08x\n", bao->version); return 0; } - VGM_LOG("UBI BAO: unknown BAO version %08x\n", bao->version); return 0; } diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index d63a0845..c3f4aa71 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -644,7 +644,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_ sf_data = open_streamfile_by_filename(sf, sb->resource_name); if (!sf_data) { /* play silence if external file is not found since Rayman 2 seems to rely on this behavior */ - VGM_LOG("UBI DAT: external stream '%s' not found\n", sb->resource_name); + vgm_logi("UBI DAT: external file '%s' not found (put together)\n", sb->resource_name); strncat(sb->readable_name, " (missing)", sizeof(sb->readable_name)); sb->duration = (float)pcm_bytes_to_samples(sb->stream_size, sb->channels, 16) / (float)sb->sample_rate; return init_vgmstream_ubi_sb_silence(sb); @@ -1301,10 +1301,11 @@ static VGMSTREAM* init_vgmstream_ubi_sb_audio(ubi_sb_header* sb, STREAMFILE* sf_ if (sb->is_external) { sf_data = open_streamfile_by_filename(sf, sb->resource_name); if (sf_data == NULL) { - VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name); + vgm_logi("UBI SB: external file '%s' not found (put together)\n", sb->resource_name); goto fail; } - } else { + } + else { sf_data = sf; } @@ -1341,7 +1342,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_layer(ubi_sb_header* sb, STREAMFILE* sf_ if (sb->is_external) { sf_data = open_streamfile_by_filename(sf,sb->resource_name); if (sf_data == NULL) { - VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name); + vgm_logi("UBI SB: external file '%s' not found (put together)\n", sb->resource_name); goto fail; } } @@ -1563,7 +1564,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf VGMSTREAM* vgmstream = NULL; if (sb->total_subsongs == 0) { - VGM_LOG("UBI SB: no subsongs\n"); + vgm_logi("UBI SB: bank has no subsongs (ignore)\n"); goto fail; } @@ -4042,6 +4043,6 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { return 1; } - VGM_LOG("UBI SB: unknown SB/SM version+platform %08x\n", sb->version); + vgm_logi("UBI SB: unknown SB/SM version+platform %08x (report)\n", sb->version); return 0; } diff --git a/src/meta/wwise.c b/src/meta/wwise.c index e41aa33d..f226d92b 100644 --- a/src/meta/wwise.c +++ b/src/meta/wwise.c @@ -592,8 +592,8 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) { vgmstream->layout_type = layout_none; break; } - #endif + case HEVAG: /* PSV */ /* changed values, another bizarre Wwise quirk */ //ww.block_align /* unknown (1ch=2, 2ch=4) */ @@ -644,6 +644,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) { break; } #endif + case PTADPCM: /* newer ADPCM [Bayonetta 2 (Switch), Genshin Impact (PC)] */ if (ww.bits_per_sample != 4) goto fail; if (ww.block_align != 0x24 * ww.channels && ww.block_align != 0x104 * ww.channels) goto fail; @@ -885,6 +886,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) { case 0x3041: ww->codec = OPUSWW; break; /* "OPUS_WEM", added on Wwise 2019.2.3, replaces OPUS */ case 0x8311: ww->codec = PTADPCM; break; /* added on Wwise 2019.1, replaces IMA */ default: + vgm_logi("WWISE: unknown codec 0x%04x (report)\n", ww->format); goto fail; } @@ -893,11 +895,14 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) { if (ww->extra_size == 0x0c + ww->channels * 0x2e) { /* newer Wwise DSP with coefs [Epic Mickey 2 (Wii), Batman Arkham Origins Blackgate (3DS)] */ ww->codec = DSP; - } else if (ww->extra_size == 0x0a && ww->wiih_offset) { /* WiiH */ + } + else if (ww->extra_size == 0x0a && ww->wiih_offset) { /* WiiH */ /* few older Wwise DSP with num_samples in extra_size [Tony Hawk: Shred (Wii)] */ ww->codec = DSP; - } else if (ww->block_align == 0x104 * ww->channels) { - ww->codec = PTADPCM; /* Bayonetta 2 (Switch) */ + } + else if (ww->block_align == 0x104 * ww->channels) { + /* Bayonetta 2 (Switch) */ + ww->codec = PTADPCM; } } @@ -911,7 +916,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) { /* catch wrong rips as truncated tracks' file_size should be much smaller than data_size, * but it's possible to pre-fetch small files too [Punch Out!! (Wii)] */ if (ww->data_offset + ww->data_size - ww->file_size < 0x5000 && ww->file_size > 0x10000) { - VGM_LOG("WWISE: wrong expected data_size\n"); + vgm_logi("WWISE: wrong expected size (re-rip?)\n"); goto fail; } @@ -919,7 +924,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) { ww->codec == OPUSNX || ww->codec == OPUS || ww->codec == OPUSWW || ww->codec == PTADPCM) { ww->truncated = 1; /* only seen those, probably all exist (XWMA, AAC, HEVAG, ATRAC9?) */ } else { - VGM_LOG("WWISE: wrong size, maybe truncated\n"); + vgm_logi("WWISE: wrong expected size, maybe truncated (report)\n"); goto fail; } } diff --git a/src/meta/xsh_xsd_xss.c b/src/meta/xsh_xsd_xss.c index 2c7dfc48..2f12b540 100644 --- a/src/meta/xsh_xsd_xss.c +++ b/src/meta/xsh_xsd_xss.c @@ -96,7 +96,7 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf) { sf_body = open_streamfile_by_filename(sf,filename); if (!sf_body) { - VGM_LOG("XSH: can't find %s\n", filename); + vgm_logi("XSH: external file '%s' not found (put together)\n", filename); goto fail; } @@ -116,7 +116,7 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf) { snprintf(filename, sizeof(filename), "%s", "STREAMS.XSS"); sf_body = open_streamfile_by_filename(sf,filename); if (!sf_body) { - VGM_LOG("XSH: can't find %s\n", filename); + vgm_logi("XSH: external file '%s' not found (put together)\n", filename); goto fail; } break; diff --git a/src/util/log.c b/src/util/log.c index e3420cb4..cd02c2da 100644 --- a/src/util/log.c +++ b/src/util/log.c @@ -75,3 +75,16 @@ void vgm_logi(const char* fmt, ...) { log_internal(NULL, LOG_LEVEL_INFO, fmt, args); va_end(args); } + +void vgm_asserti(int condition, const char* fmt, ...) { + if (!condition) + return; + + { + va_list args; + + va_start(args, fmt); + log_internal(NULL, LOG_LEVEL_INFO, fmt, args); + va_end(args); + } +} diff --git a/src/util/log.h b/src/util/log.h index 03f1e760..6bcbfa97 100644 --- a/src/util/log.h +++ b/src/util/log.h @@ -20,17 +20,21 @@ void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback); #if defined(VGM_LOG_OUTPUT) || defined(VGM_DEBUG_OUTPUT) void vgm_logi(/*void* ctx,*/ const char* fmt, ...); + void vgm_asserti(/*void* ctx,*/ int condition, const char* fmt, ...); //void vgm_logi_once(/*void* ctx, int* once_flag, */ const char* fmt, ...); #else #define vgm_logi(...) /* nothing */ + #define vgm_asserti(...) /* nothing */ #endif #ifdef VGM_DEBUG_OUTPUT void vgm_logd(/*void* ctx,*/ const char* fmt, ...); #define VGM_LOG(...) do { vgm_logd(__VA_ARGS__); } while (0) + #define VGM_ASSERT(condition, ...) do { if (condition) {vgm_logd(__VA_ARGS__);} } while (0) #else #define vgm_logd(...) /* nothing */ #define VGM_LOG(...) /* nothing */ + #define VGM_ASSERT(condition, ...) /* nothing */ #endif @@ -38,47 +42,37 @@ void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback); * Needs C99 variadic macros, uses do..while to force ";" as statement */ #ifdef VGM_DEBUG_OUTPUT -/* equivalent to printf when condition is true */ -#define VGM_ASSERT(condition, ...) \ - do { if (condition) {printf(__VA_ARGS__);} } while (0) + #define VGM_LOG_ONCE(...) \ + do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0) -#define VGM_ASSERT_ONCE(condition, ...) \ - do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0) + #define VGM_ASSERT_ONCE(condition, ...) \ + do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0) -/* equivalent to printf */ -//#define VGM_LOG(...) do { printf(__VA_ARGS__); } while (0) + /* prints to a file */ + #define VGM_LOGT(txt, ...) \ + do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0) -#define VGM_LOG_ONCE(...) \ - do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0) + /* prints a buffer/array */ + #define VGM_LOGB(buf, buf_size, bytes_per_line) \ + do { \ + int i; \ + for (i=0; i < buf_size; i++) { \ + printf("%02x",buf[i]); \ + if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \ + } \ + printf("\n"); \ + } while (0) -/* prints file/line/func */ -//#define VGM_LOGF() do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0) +#else /* VGM_DEBUG_OUTPUT */ -/* prints to a file */ -#define VGM_LOGT(txt, ...) \ - do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0) + #define VGM_LOG_ONCE(...) /* nothing */ -/* prints a buffer/array */ -#define VGM_LOGB(buf, buf_size, bytes_per_line) \ - do { \ - int i; \ - for (i=0; i < buf_size; i++) { \ - printf("%02x",buf[i]); \ - if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \ - } \ - printf("\n"); \ - } while (0) + #define VGM_ASSERT_ONCE(condition, ...) /* nothing */ -#else/*VGM_DEBUG_OUTPUT*/ + #define VGM_LOGT() /* nothing */ -#define VGM_ASSERT(condition, ...) /* nothing */ -#define VGM_ASSERT_ONCE(condition, ...) /* nothing */ -//#define VGM_LOG(...) /* nothing */ -#define VGM_LOG_ONCE(...) /* nothing */ -//#define VGM_LOGF() /* nothing */ -#define VGM_LOGT() /* nothing */ -#define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */ + #define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */ -#endif/*VGM_DEBUG_OUTPUT*/ +#endif /*VGM_DEBUG_OUTPUT*/ #endif