From 58f3a70c163340ad2fc235a0c6e3c2afb8b85f8d Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Dec 2023 23:45:06 +0100 Subject: [PATCH 1/5] Add Sony .bnk with MPEG [Last of Us demo (PS3)] --- src/meta/bnk_sony.c | 82 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 62 insertions(+), 20 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index ebc10416..e3885c07 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -3,7 +3,7 @@ #include "../coding/coding.h" #include "../util/endianness.h" -typedef enum { NONE, DUMMY, PSX, PCM16, ATRAC9, HEVAG, RIFF_ATRAC9 } bnk_codec; +typedef enum { NONE, DUMMY, PSX, PCM16, MPEG, ATRAC9, HEVAG, RIFF_ATRAC9 } bnk_codec; typedef struct { bnk_codec codec; @@ -41,6 +41,7 @@ typedef struct { int32_t num_samples; int32_t loop_start; int32_t loop_end; + int32_t encoder_delay; uint32_t start_offset; uint32_t stream_offset; @@ -81,7 +82,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { vgmstream->meta_type = meta_BNK_SONY; - if (!h.stream_name_size) + if (h.stream_name_size >= STREAM_NAME_SIZE || h.stream_name_size <= 0) h.stream_name_size = STREAM_NAME_SIZE; if (!h.bank_name_offset && h.stream_name_offset) { @@ -90,7 +91,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { else if (h.bank_name_offset && h.stream_name_offset) { read_string(bank_name, h.stream_name_size, h.bank_name_offset, sf); read_string(stream_name, h.stream_name_size, h.stream_name_offset, sf); - snprintf(vgmstream->stream_name, h.stream_name_size, "%s/%s", bank_name, stream_name); + snprintf(vgmstream->stream_name, h.stream_name_size, "%s%s%s", bank_name, bank_name[0] == '\0' ? "" : "/", stream_name); } @@ -147,6 +148,20 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { return temp_vs; } #endif +#ifdef VGM_USE_MPEG + case MPEG: { + mpeg_custom_config cfg = {0}; + cfg.skip_samples = h.encoder_delay; + + vgmstream->layout_type = layout_none; + vgmstream->codec_data = init_mpeg_custom(sf, h.start_offset, &vgmstream->coding_type, h.channels, MPEG_STANDARD, &cfg); + if (!vgmstream->codec_data) goto fail; + + vgmstream->num_samples = h.num_samples; + break; + } +#endif + case PCM16: vgmstream->coding_type = h.big_endian ? coding_PCM16BE : coding_PCM16LE; vgmstream->layout_type = layout_interleave; @@ -567,7 +582,7 @@ static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { goto fail; } - //;VGM_LOG("BNK: stream at %lx + %x\n", h->stream_offset, h->stream_size); + ;VGM_LOG("BNK: header %x, stream at %x + %x\n", sndh_offset, h->data_offset + h->stream_offset, h->stream_size); return true; fail: @@ -722,7 +737,7 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { break; } - //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", h->stream_offset, h->stream_size, h->stream_name_offset); + //;VGM_LOG("BNK: stream_offset=%x, stream_size=%x, stream_name_offset=%x\n", h->stream_offset, h->stream_size, h->stream_name_offset); return true; fail: @@ -813,8 +828,8 @@ static bool process_data(STREAMFILE* sf, bnk_header_t* h) { case 0x08: case 0x09: - subtype = read_u16(h->start_offset+0x00,sf); - extradata_size = 0x08 + read_u32(h->start_offset+0x04,sf); /* 0x14 for AT9 */ + subtype = read_u32(h->start_offset+0x00,sf); + extradata_size = 0x08 + read_u32(h->start_offset+0x04,sf); /* 0x14 for AT9, 0x10 for PCM, 0x90 for MPEG */ switch(subtype) { case 0x00: @@ -829,22 +844,49 @@ static bool process_data(STREAMFILE* sf, bnk_header_t* h) { h->interleave = 0x01; break; - - case 0x02: /* ATRAC9 mono */ - case 0x05: /* ATRAC9 stereo */ - if (read_u32(h->start_offset+0x08,sf) + 0x08 != extradata_size) { /* repeat? */ - VGM_LOG("BNK: unknown subtype\n"); - goto fail; - } + case 0x02: /* ATRAC9 / MPEG mono */ + case 0x05: /* ATRAC9 / MPEG stereo */ h->channels = (subtype == 0x02) ? 1 : 2; - h->atrac9_info = read_u32be(h->start_offset+0x0c,sf); - /* 0x10: null? */ - loop_length = read_u32(h->start_offset+0x14,sf); - h->loop_start = read_u32(h->start_offset+0x18,sf); - h->loop_end = h->loop_start + loop_length; /* loop_start is -1 if not set */ + if (h->big_endian) { + /* The Last of Us demo (PS3) */ - h->codec = ATRAC9; + /* 0x08: mpeg version? (1) */ + /* 0x0C: mpeg layer? (3) */ + /* 0x10: ? (related to frame size, 0xC0 > 0x40, 0x120 > 0x60) */ + /* 0x14: sample rate */ + /* 0x18: mpeg layer? (3) */ + /* 0x1c: mpeg version? (1) */ + /* 0x20: channels? */ + /* 0x24: frame size */ + /* 0x28: encoder delay */ + /* 0x2c: num samples */ + /* 0x30: ? */ + /* 0x34: ? */ + /* 0x38: 0? */ + /* 0x3c: data size */ + /* padding up to 0x90 */ + + h->encoder_delay = read_s32(h->start_offset+0x28,sf); + h->num_samples = read_s32(h->start_offset+0x2c,sf); + + h->codec = MPEG; + } + else { + /* Puyo Puyo Tetris (PS4) */ + if (read_u32(h->start_offset+0x08,sf) + 0x08 != extradata_size) { /* repeat? */ + VGM_LOG("BNK: unknown subtype\n"); + goto fail; + } + + h->atrac9_info = read_u32be(h->start_offset+0x0c,sf); + /* 0x10: null? */ + loop_length = read_u32(h->start_offset+0x14,sf); + h->loop_start = read_u32(h->start_offset+0x18,sf); + h->loop_end = h->loop_start + loop_length; /* loop_start is -1 if not set */ + + h->codec = ATRAC9; + } break; default: From 28cb13125f14c2b82a5fcad43260b3c06f53c447 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Dec 2023 23:45:14 +0100 Subject: [PATCH 2/5] Add HCA key --- src/meta/hca_keys.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 9761919f..0caca415 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -1265,10 +1265,13 @@ static const hcakey_info hcakey_list[] = { // Persona 5 Tactica (Switch) {48319776512953016}, // 00ABAA94AAAE4AB8 - - // THE IDOLM@STER Shiny Colors Song For Prism (Windows) + + // THE IDOLM@STER Shiny Colors Song For Prism (PC) {156967709847897761}, // 022DA94CEAB0C6A1 + // Dokapon Kingdom Connect (PC, Switch) + {104863924750642073}, // 01748d2f1883eb99 + }; #endif/*_HCA_KEYS_H_*/ From 9e3a9ba9014f278b7dad5c9152df2a5b8880bd80 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Dec 2023 23:45:26 +0100 Subject: [PATCH 3/5] foobar: don't downmix by default --- doc/USAGE.md | 6 +++--- fb2k/foo_prefs.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/USAGE.md b/doc/USAGE.md index 51d8d404..76238827 100644 --- a/doc/USAGE.md +++ b/doc/USAGE.md @@ -566,9 +566,9 @@ making impossible for vgmstream to play them properly. ### Channel issues Some games layer a huge number of channels, that are disabled or downmixed during gameplay. The player may be unable to play those files (for example -foobar can only play up to 8 channels, and Winamp depends on your sound -card). For those files you can set the "downmix" option in vgmstream, that -can reduce the number of channels to a playable amount. +older foobar versions can only play up to 8 channels, and Winamp depends on +your sound card). For those files you can set the "downmix" option in +vgmstream, that can reduce the number of channels to a playable amount. Note that this type of downmixing is very generic (not meant to be used when converting to other formats), channels are re-assigned and volumes modified diff --git a/fb2k/foo_prefs.h b/fb2k/foo_prefs.h index b75121cf..ecd2d5d3 100755 --- a/fb2k/foo_prefs.h +++ b/fb2k/foo_prefs.h @@ -13,7 +13,7 @@ #define DEFAULT_LOOP_FOREVER false #define DEFAULT_IGNORE_LOOP false #define DEFAULT_DISABLE_SUBSONGS false -#define DEFAULT_DOWNMIX_CHANNELS "8" +#define DEFAULT_DOWNMIX_CHANNELS "0" #define DEFAULT_TAGFILE_DISABLE false #define DEFAULT_OVERRIDE_TITLE false #define DEFAULT_EXTS_UNKNOWN_ON false From 5cae4cbaa98f4f978a5c84ab48d358abd7a7f1f1 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Dec 2023 23:45:48 +0100 Subject: [PATCH 4/5] awc: fixes --- src/meta/awc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/meta/awc.c b/src/meta/awc.c index 52035217..8f46adc9 100644 --- a/src/meta/awc.c +++ b/src/meta/awc.c @@ -24,6 +24,7 @@ typedef struct { uint32_t stream_size; uint32_t vorbis_offset[AWC_MAX_MUSIC_CHANNELS]; + /* stream+music only */ uint32_t channel_hash[AWC_MAX_MUSIC_CHANNELS]; struct { uint32_t hash_id; @@ -274,7 +275,7 @@ static int parse_awc_header(STREAMFILE* sf, awc_header* awc) { //if (flags % 0x00020000) // awc->is_unordered = 1; - /* stream/multichannel flag (GTA5 only) */ + /* stream/multichannel flag (rare, GTA5/RDR2) */ //if (flags % 0x00040000) // awc->is_multichannel = 1; @@ -322,6 +323,9 @@ static int parse_awc_header(STREAMFILE* sf, awc_header* awc) { if (awc->is_streamed) { /* music with N channels, other streams aren't used ignored */ awc->total_subsongs = 1; target_subsong = 1; + /* array access below */ + if (entries >= AWC_MAX_MUSIC_CHANNELS) + goto fail; } else { /* sfx pack, each stream is a sound */ awc->total_subsongs = entries; From e19e4158509439ab302eca60225a09e3a5705697 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 3 Dec 2023 23:45:56 +0100 Subject: [PATCH 5/5] txtp_maker: add cmd flag --- cli/tools/txtp_maker.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cli/tools/txtp_maker.py b/cli/tools/txtp_maker.py index 16e3d20b..d2f52ae0 100644 --- a/cli/tools/txtp_maker.py +++ b/cli/tools/txtp_maker.py @@ -73,6 +73,7 @@ class Cli(object): p.add_argument('-fni', dest='include_regex', help="Filter by REGEX including matches of subsong name") p.add_argument('-fne', dest='exclude_regex', help="Filter by REGEX excluding matches of subsong name") p.add_argument('-nsc',dest='no_semicolon', help="Remove semicolon names (for songs with multinames)", action='store_true') + p.add_argument("-cmd","--command", help="sets any command (free text)") p.add_argument('-v', dest='log_level', help="Verbose log level (off|debug|info, default: info)", default='info') args = p.parse_args() @@ -327,6 +328,11 @@ class TxtpMaker(object): with open(outname,"w+", encoding='utf-8') as ftxtp: if line: ftxtp.write(line) + if cfg.command: + cmd = cfg.command.replace("\\n", "\n") + "\n" + if not line.endswith('\n'): + cmd = "\n" + cmd + ftxtp.write(cmd) log.debug("created: " + outname) return