From 474c15723a2eff245238713aa7938f8b00972501 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 22 Aug 2023 14:58:43 +0300 Subject: [PATCH 1/3] Ubi SB: Use more accurate var names --- src/meta/ubi_sb.c | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index 58e0de21..c7ddc43e 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -62,8 +62,8 @@ typedef struct { int has_rs_files; off_t sequence_extra_offset; - off_t sequence_sequence_loop; - off_t sequence_sequence_single; + off_t sequence_sequence_loop_start; + off_t sequence_sequence_num_loops; off_t sequence_sequence_count; off_t sequence_entry_number; size_t sequence_entry_size; @@ -188,8 +188,8 @@ typedef struct { int sequence_chain[SB_MAX_CHAIN_COUNT]; /* sequence of entry numbers */ int sequence_banks[SB_MAX_CHAIN_COUNT]; /* sequence of bnk bank numbers */ int sequence_multibank; /* info flag */ - int sequence_loop; /* chain index to loop */ - int sequence_single; /* if que sequence plays once (loops by default) */ + int sequence_loop_start; /* chain index to loop */ + int sequence_num_loops; /* if que sequence plays once (loops by default) */ float duration; /* silence duration */ @@ -1467,7 +1467,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_sequence(ubi_sb_header* sb, STREAMFILE* data->segments[i] = init_vgmstream_ubi_sb_header(&temp_sb, sf_bank, sf); if (!data->segments[i]) goto fail; - if (i == sb->sequence_loop) + if (i == sb->sequence_loop_start) sb->loop_start = sb->num_samples; sb->num_samples += data->segments[i]->num_samples; @@ -1483,7 +1483,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_sequence(ubi_sb_header* sb, STREAMFILE* goto fail; /* build the base VGMSTREAM */ - vgmstream = allocate_vgmstream(data->output_channels, !sb->sequence_single); + vgmstream = allocate_vgmstream(data->output_channels, !sb->sequence_num_loops); if (!vgmstream) goto fail; vgmstream->meta_type = meta_UBI_SB; @@ -1625,7 +1625,7 @@ static void build_readable_name(char * buf, size_t buf_size, ubi_sb_header* sb) index = sb->header_index; //-1 if (sb->type == UBI_SEQUENCE) { - if (sb->sequence_single) { + if (sb->sequence_num_loops) { if (sb->sequence_count == 1) res_name = "single"; else @@ -1635,7 +1635,7 @@ static void build_readable_name(char * buf, size_t buf_size, ubi_sb_header* sb) if (sb->sequence_count == 1) res_name = "single-loop"; else - res_name = (sb->sequence_loop == 0) ? "multi-loop" : "intro-loop"; + res_name = (sb->sequence_loop_start == 0) ? "multi-loop" : "intro-loop"; } } else { @@ -1917,10 +1917,10 @@ static int parse_type_sequence(ubi_sb_header* sb, off_t offset, STREAMFILE* sf) goto fail; } - sb->extra_offset = read_32bit(offset + sb->cfg.sequence_extra_offset, sf) + sb->sectionX_offset; - sb->sequence_loop = read_32bit(offset + sb->cfg.sequence_sequence_loop, sf); - sb->sequence_single = read_32bit(offset + sb->cfg.sequence_sequence_single, sf); - sb->sequence_count = read_32bit(offset + sb->cfg.sequence_sequence_count, sf); + sb->extra_offset = read_32bit(offset + sb->cfg.sequence_extra_offset, sf) + sb->sectionX_offset; + sb->sequence_loop_start = read_32bit(offset + sb->cfg.sequence_sequence_loop_start, sf); + sb->sequence_num_loops = read_32bit(offset + sb->cfg.sequence_sequence_num_loops, sf); + sb->sequence_count = read_32bit(offset + sb->cfg.sequence_sequence_count, sf); if (sb->sequence_count > SB_MAX_CHAIN_COUNT) { VGM_LOG("UBI SB: incorrect sequence count %i vs %i\n", sb->sequence_count, SB_MAX_CHAIN_COUNT); @@ -2705,17 +2705,17 @@ static void config_sb_audio_ps2_old(ubi_sb_header *sb, off_t flag_bits, int stre } static void config_sb_sequence(ubi_sb_header* sb, off_t sequence_count, off_t entry_size) { /* sequence header and chain table */ - sb->cfg.sequence_sequence_loop = sequence_count - 0x10; - sb->cfg.sequence_sequence_single= sequence_count - 0x0c; - sb->cfg.sequence_sequence_count = sequence_count; - sb->cfg.sequence_entry_size = entry_size; - sb->cfg.sequence_entry_number = 0x00; + sb->cfg.sequence_sequence_loop_start = sequence_count - 0x10; + sb->cfg.sequence_sequence_num_loops = sequence_count - 0x0c; + sb->cfg.sequence_sequence_count = sequence_count; + sb->cfg.sequence_entry_size = entry_size; + sb->cfg.sequence_entry_number = 0x00; if (sb->is_bnm || sb->is_dat || sb->is_ps2_bnm) { - sb->cfg.sequence_sequence_loop = sequence_count - 0x0c; - sb->cfg.sequence_sequence_single= sequence_count - 0x08; + sb->cfg.sequence_sequence_loop_start = sequence_count - 0x0c; + sb->cfg.sequence_sequence_num_loops = sequence_count - 0x08; } else if (sb->is_blk) { - sb->cfg.sequence_sequence_loop = sequence_count - 0x14; - sb->cfg.sequence_sequence_single= sequence_count - 0x0c; + sb->cfg.sequence_sequence_loop_start = sequence_count - 0x14; + sb->cfg.sequence_sequence_num_loops = sequence_count - 0x0c; } } static void config_sb_layer_hs(ubi_sb_header* sb, off_t layer_count, off_t stream_size, off_t stream_offset, off_t stream_name) { From c58b1650c91fdb868eb16ddcd77de6968b627d35 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 22 Aug 2023 15:00:20 +0300 Subject: [PATCH 2/3] Support extensionless in swap_extension --- src/util/sf_utils.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/util/sf_utils.c b/src/util/sf_utils.c index d0cd061e..03e1723a 100644 --- a/src/util/sf_utils.c +++ b/src/util/sf_utils.c @@ -9,11 +9,18 @@ static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const ch char* extension = (char*)filename_extension(pathname); //todo safeops if (extension[0] == '\0') { - strcat(pathname, "."); - strcat(pathname, swap); + if (swap[0] != '\0') { + strcat(pathname, "."); + strcat(pathname, swap); + } } else { - strcpy(extension, swap); + if (swap[0] != '\0') { + strcpy(extension, swap); + } else { + extension--; + extension[0] = '\0'; + } } } From a2d2bf77129f40a4765933a5119a78cce6e9f92f Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 22 Aug 2023 15:01:15 +0300 Subject: [PATCH 3/3] id BSNF: Extensionless data file, support languages --- src/meta/idtech.c | 126 +++++++++++++++++++++++----------------------- 1 file changed, 62 insertions(+), 64 deletions(-) diff --git a/src/meta/idtech.c b/src/meta/idtech.c index bae933ff..191515ae 100644 --- a/src/meta/idtech.c +++ b/src/meta/idtech.c @@ -303,90 +303,87 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset, offset, extra_offset; size_t stream_size; - int loop_flag, channels, codec, sample_rate; //, block_size = 0, bps = 0; + int target_subsong = sf->stream_index, num_languages, + loop_flag, channels, codec, sample_rate; //, block_size = 0, bps = 0; int32_t num_samples, loop_start = 0; + char language[0x10]; STREAMFILE* sb = NULL; - const char* suffix = NULL; - const char* extension = NULL; /* checks */ - if (!is_id32be(0x00,sf, "bsnf")) /* null-terminated string */ - goto fail; - if (read_u32be(0x05, sf) != 0x00000100) /* version */ + if (!is_id32be(0x00, sf, "bsnf")) goto fail; if (!check_extensions(sf, "bsnd")) goto fail; - offset = 0x18; + num_languages = read_u32be(0x04, sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > num_languages || num_languages < 1) + goto fail; - stream_size = read_u32be(offset + 0x00,sf); - offset = read_u32be(offset + 0x04,sf); /* absolute but typically right after this */ + offset = 0x08 + (target_subsong - 1) * 0x18; + + read_string(language, 0x10, offset + 0x00, sf); + stream_size = read_u32be(offset + 0x10, sf); + offset = read_u32be(offset + 0x14, sf); /* absolute but typically right after this */ /* 0x00: crc? */ /* 0x04: CBR samples or 0 if VBR */ - num_samples = read_s32be(offset + 0x08,sf); - loop_start = read_s32be(offset + 0x0c,sf); + num_samples = read_s32be(offset + 0x08, sf); + loop_start = read_s32be(offset + 0x0c, sf); /* 0x10: stream size? */ - codec = read_u16le(offset + 0x14,sf); + codec = read_u16le(offset + 0x14, sf); channels = read_u16le(offset + 0x16, sf); sample_rate = read_u32le(offset + 0x18, sf); //block_size = read_u16le(offset + 0x20, sf); //bps = read_u16le(offset + 0x22, sf); extra_offset = offset + 0x24; - extension = "ogg"; /* same for all codecs */ - switch(codec) { - case 0x0055: /* msf */ - /* 0x00: table entries */ - /* 0x04: seek table, format: frame size (16b) + frame samples (16b) */ - suffix = "_msf.bsnd"; - break; - case 0x0166: /* xma */ - /* 0x00: extra size */ - /* 0x02: xma config and block table */ - suffix = "_xma.bsnd"; - break; - - case 0x674F: /* vorbis */ - /* 0x00: extra size */ - /* 0x02: num samples */ - suffix = "_vorbis.bsnd"; - goto fail; //untested - //break; - - case 0x42D2: /* at9 */ - /* 0x00: extra size */ - /* 0x02: encoder delay */ - /* 0x04: channel config */ - /* 0x08: ATRAC9 GUID */ - /* 0x1c: ATRAC9 config */ - suffix = "_at9.bsnd"; - break; - - default: - goto fail; - } + /* extra data per codec */ + /* 0x0055 - msf */ + /* 0x00: table entries */ + /* 0x04: seek table, format: frame size (16b) + frame samples (16b) */ + /* 0x0166 - xma */ + /* 0x00: extra size */ + /* 0x02: xma config and block table */ + /* 0x674F - vorbis */ + /* 0x00: extra size */ + /* 0x02: num samples */ + /* 0x42D2 - at9 */ + /* 0x00: extra size */ + /* 0x02: encoder delay */ + /* 0x04: channel config */ + /* 0x08: ATRAC9 GUID */ + /* 0x1c: ATRAC9 config */ { - int suffix_len = strlen(suffix); - int filename_len; char filename[PATH_LIMIT]; + get_streamfile_basename(sf, filename, sizeof(filename)); - get_streamfile_filename(sf, filename, sizeof(filename)); - filename_len = strlen(filename); - - if (filename_len < suffix_len) - goto fail; - filename[filename_len - suffix_len + 0] = '.'; - filename[filename_len - suffix_len + 1] = '\0'; - strcat(filename, extension); + if (language[0] != '\0') { + strcat(filename, "_"); + strcat(filename, language); + } sb = open_streamfile_by_filename(sf, filename); - if (!sb) goto fail; + if (!sb) { + if (language[0] != '\0') { + // fill missing languages with blanks + vgmstream = init_vgmstream_silence(channels, sample_rate, num_samples); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_BSNF; + vgmstream->num_streams = num_languages; + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s (missing)", language); + + return vgmstream; + } + + goto fail; + } } if (stream_size != get_streamfile_size(sb)) @@ -395,7 +392,6 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) { loop_flag = (loop_start > 0); start_offset = 0x00; - /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; @@ -405,12 +401,14 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) { vgmstream->num_samples = num_samples; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = num_samples; + vgmstream->num_streams = num_languages; + strncpy(vgmstream->stream_name, language, STREAM_NAME_SIZE); - switch(codec) { + switch (codec) { #ifdef VGM_USE_MPEG case 0x0055: { - mpeg_custom_config cfg = {0}; + mpeg_custom_config cfg = { 0 }; cfg.skip_samples = 1152; /* seems ok */ @@ -427,14 +425,14 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) { #ifdef VGM_USE_FFMPEG case 0x0166: { - int block_size = 0x800; + int block_size = 0x800; - vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, stream_size, num_samples, channels, sample_rate, block_size, 0); + vgmstream->codec_data = init_ffmpeg_xma2_raw(sb, start_offset, stream_size, num_samples, channels, sample_rate, block_size, 0); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - xma_fix_raw_samples(vgmstream, sb, start_offset, stream_size, 0x00, 1,1); + xma_fix_raw_samples(vgmstream, sb, start_offset, stream_size, 0x00, 1, 1); break; } #endif @@ -451,11 +449,11 @@ VGMSTREAM* init_vgmstream_bsnf(STREAMFILE* sf) { #ifdef VGM_USE_ATRAC9 case 0x42D2: { - atrac9_config cfg = {0}; + atrac9_config cfg = { 0 }; cfg.channels = vgmstream->channels; - cfg.encoder_delay = read_u16le(extra_offset + 0x02,sf); - cfg.config_data = read_u32be(extra_offset + 0x1c,sf); + cfg.encoder_delay = read_u16le(extra_offset + 0x02, sf); + cfg.config_data = read_u32be(extra_offset + 0x1c, sf); vgmstream->codec_data = init_atrac9(&cfg); if (!vgmstream->codec_data) goto fail;