From 382bd4ba4e4e954fe5e8bc6a409cef26958451bb Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Mon, 8 Jun 2020 23:10:51 +0300 Subject: [PATCH 1/3] Ubi SB: Unified checking for project files --- src/meta/ubi_sb.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index cef0109e..0f350059 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -2742,13 +2742,32 @@ static void config_sb_silence_f(ubi_sb_header* sb, off_t duration) { /* silence headers in float value */ sb->cfg.silence_duration_float = duration; } - static void config_sb_random_old(ubi_sb_header* sb, off_t sequence_count, off_t entry_size) { sb->cfg.random_sequence_count = sequence_count; sb->cfg.random_entry_size = entry_size; sb->cfg.random_percent_int = 1; } +static int check_project_file(STREAMFILE *sf_header, const char *name, int has_localized_banks) { + STREAMFILE *sf_test = open_streamfile_by_filename(sf_header, name); + if (sf_test) { + close_streamfile(sf_test); + return 1; + } + + if (has_localized_banks) { /* try again for localized subfolders */ + char buf[PATH_LIMIT]; + snprintf(buf, PATH_LIMIT, "../%s", name); + sf_test = open_streamfile_by_filename(sf_header, name); + if (sf_test) { + close_streamfile(sf_test); + return 1; + } + } + + return 0; +} + static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { int is_ttse_pc = 0; int is_bia_ps2 = 0, is_biadd_psp = 0; @@ -2943,10 +2962,8 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* two configs with same id; use SND file as identifier */ if (sb->version == 0x00000000 && sb->platform == UBI_PC) { - STREAMFILE* test_sf = open_streamfile_by_filename(sf, "Dino.lcb"); - if (test_sf) { + if (check_project_file(sf, "Dino.lcb", 0)) { sb->version = 0x00000200; /* some files in Dinosaur use this, probably final version */ - close_streamfile(test_sf); } } @@ -2959,11 +2976,9 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* Tonic Touble beta has garbage instead of version */ if (sb->is_bnm && sb->version > 0x00000000 && sb->platform == UBI_PC) { - STREAMFILE* test_sf = open_streamfile_by_filename(sf, "ED_MAIN.LCB"); - if (test_sf) { + if (check_project_file(sf, "ED_MAIN.LCB", 0)) { is_ttse_pc = 1; sb->version = 0x00000000; - close_streamfile(test_sf); } } @@ -3297,12 +3312,8 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* two configs with same id; use project file as identifier */ if (sb->version == 0x000A0007 && sb->platform == UBI_PS2) { - STREAMFILE* test_sf = open_streamfile_by_filename(sf, "BIAAUDIO.SP1"); - if (!test_sf) /* try again for localized subfolders */ - test_sf = open_streamfile_by_filename(sf, "../BIAAUDIO.SP1"); - if (test_sf) { + if (check_project_file(sf, "BIAAUDIO.SP1", 1)) { is_bia_ps2 = 1; - close_streamfile(test_sf); } } @@ -3476,10 +3487,8 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* two configs with same id and both sb4/sm4; use project file as identifier */ if (sb->version == 0x0012000C && sb->platform == UBI_PSP) { - STREAMFILE* test_sf = open_streamfile_by_filename(sf, "BIAAUDIO.SP4"); - if (test_sf) { + if (check_project_file(sf, "BIAAUDIO.SP4", 1)) { is_biadd_psp = 1; - close_streamfile(test_sf); } } @@ -3743,10 +3752,8 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) { /* two configs with same id; use project file as identifier */ if (sb->version == 0x00180006 && sb->platform == UBI_PC) { - STREAMFILE* test_sf = open_streamfile_by_filename(sf, "Sc4_online_SoundProject.SP0"); - if (test_sf) { + if (check_project_file(sf, "Sc4_online_SoundProject.SP0", 1)) { is_sc4_pc_online = 1; - close_streamfile(test_sf); } } From 062ce3efed6c9c0255e10c31d93b0d9f2b66b0af Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 9 Jun 2020 21:13:57 +0300 Subject: [PATCH 2/3] Ubi DAT: Fixed data size for raw PCM --- src/meta/ubi_sb.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/meta/ubi_sb.c b/src/meta/ubi_sb.c index 0f350059..c400507b 100644 --- a/src/meta/ubi_sb.c +++ b/src/meta/ubi_sb.c @@ -709,17 +709,14 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_ goto fail; } } else { /* raw PCM */ - uint32_t data_size; - vgmstream = allocate_vgmstream(sb->channels, sb->loop_flag); if (!vgmstream) goto fail; - data_size = get_streamfile_size(sf_data) - sb->stream_offset; - + /* TODO: some WAVs pop at the end because of LIST chunk, doesn't happen in-game [Donald Duck (DC)] */ vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x02; - vgmstream->num_samples = pcm_bytes_to_samples(data_size, sb->channels, 16); + vgmstream->num_samples = pcm_bytes_to_samples(sb->stream_size, sb->channels, 16); vgmstream->loop_start_sample = sb->loop_start; vgmstream->loop_end_sample = vgmstream->num_samples; @@ -1025,7 +1022,6 @@ static VGMSTREAM* init_vgmstream_ubi_sb_base(ubi_sb_header* sb, STREAMFILE* sf_h vgmstream->interleave_block_size = 0x02; if (vgmstream->num_samples == 0) { /* happens in .bnm */ - //todo with external wav streams stream_size may be off? vgmstream->num_samples = pcm_bytes_to_samples(sb->stream_size, sb->channels, 16); vgmstream->loop_end_sample = vgmstream->num_samples; } From b456cb84c66a8ce2cc9aaa885aa73374b690e119 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 9 Jun 2020 21:32:18 +0300 Subject: [PATCH 3/3] TXTH: Added EA-XA support --- doc/TXTH.md | 4 +++- src/coding/coding.h | 5 +++-- src/coding/ea_xa_decoder.c | 5 +++++ src/meta/txth.c | 19 +++++++++++++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/doc/TXTH.md b/doc/TXTH.md index 516b55d1..a273a1a6 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -147,6 +147,8 @@ as explained below, but often will use default values. Accepted codec strings: # * For Tiger Game.com # - ASF Argonaut ASF ADPCM # * For rare Argonaut games [Croc (SAT)] +# - EAXA Electronis Arts EA-XA ADPCM +# * For rare EA games [Harry Potter and the Chamber of Secrets (PC)] codec = (codec string) ``` @@ -155,7 +157,7 @@ Changes the behavior of some codecs: ``` # - NGC_DSP: 0=normal interleave, 1=byte interleave, 2=no interleave # - XMA1|XMA2: 0=dual multichannel (2ch xN), 1=single multichannel (1ch xN) -# - XBOX: 0=standard (mono or stereo interleave), 1=force mono interleave mode +# - XBOX|EAXA: 0=standard (mono or stereo interleave), 1=force mono interleave mode # - PCFX: 0=standard, 1='buggy encoder' mode, 2/3=same as 0/1 but with double volume # - PCM4|PCM4_U: 0=low nibble first, 1=high nibble first # - others: ignored diff --git a/src/coding/coding.h b/src/coding/coding.h index f12fd89a..e09a0638 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -106,10 +106,11 @@ void decode_ea_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing void decode_ea_xa_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel); void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +int32_t ea_xa_bytes_to_samples(size_t bytes, int channels); /* ea_xas_decoder */ void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); -void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); +void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); /* sdx2_decoder */ void decode_sdx2(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); @@ -236,7 +237,7 @@ void free_relic(relic_codec_data* data); /* hca_decoder */ hca_codec_data *init_hca(STREAMFILE *streamFile); -void decode_hca(hca_codec_data * data, sample_t * outbuf, int32_t samples_to_do); +void decode_hca(hca_codec_data * data, sample * outbuf, int32_t samples_to_do); void reset_hca(hca_codec_data * data); void loop_hca(hca_codec_data * data, int32_t num_sample); void free_hca(hca_codec_data * data); diff --git a/src/coding/ea_xa_decoder.c b/src/coding/ea_xa_decoder.c index 9178d3ae..7e6080bc 100644 --- a/src/coding/ea_xa_decoder.c +++ b/src/coding/ea_xa_decoder.c @@ -303,3 +303,8 @@ void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac if (i == frame_samples) stream->offset += frame_size; } + +int32_t ea_xa_bytes_to_samples(size_t bytes, int channels) { + if (channels <= 0) return 0; + return bytes / channels / 0x0f * 28; +} diff --git a/src/meta/txth.c b/src/meta/txth.c index f98e6296..0dbad5e1 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -38,6 +38,7 @@ typedef enum { AAC = 28, /* Advanced Audio Coding (raw without .mp4) */ TGC = 29, /* Tiger Game.com 4-bit ADPCM */ ASF = 30, /* Argonaut ASF 4-bit ADPCM */ + EAXA = 31, /* Electronic Arts EA-XA 4-bit ADPCM v1 */ } txth_type; typedef struct { @@ -225,6 +226,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { case OKI16: coding = coding_OKI16; break; case TGC: coding = coding_TGC; break; case ASF: coding = coding_ASF; break; + case EAXA: coding = coding_EA_XA; break; default: goto fail; } @@ -341,6 +343,20 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) { vgmstream->interleave_block_size = 0x11; break; + case coding_EA_XA: + if (vgmstream->channels == 1 || txth.codec_mode == 1) { /* mono/interleave */ + coding = coding_EA_XA_int; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = txth.interleave; + vgmstream->interleave_last_block_size = txth.interleave_last; + } else { /* stereo */ + if (vgmstream->channels > 2) + goto fail; /* only 2ch is known */ + + vgmstream->layout_type = layout_none; + } + break; + case coding_MS_IMA: if (!txth.interleave) goto fail; /* creates garbage */ @@ -856,6 +872,7 @@ static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char else if (is_string(val,"TGC")) txth->codec = TGC; else if (is_string(val,"GCOM_ADPCM")) txth->codec = TGC; else if (is_string(val,"ASF")) txth->codec = ASF; + else if (is_string(val,"EAXA")) txth->codec = EAXA; else goto fail; /* set common interleaves to simplify usage @@ -1740,6 +1757,8 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) { return ac3_bytes_to_samples(bytes, txth->interleave, txth->channels); case ASF: return asf_bytes_to_samples(bytes, txth->channels); + case EAXA: + return ea_xa_bytes_to_samples(bytes, txth->channels); /* XMA bytes-to-samples is done at the end as the value meanings are a bit different */ case XMA1: