From ce295d4591d8ea3b9ffb06e14a8a2a8b56f76b7e Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 00:31:50 +0200 Subject: [PATCH 001/141] Add FSB Opus [LEGO 2K Drive (Switch)] --- src/meta/fsb5.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/meta/fsb5.c b/src/meta/fsb5.c index 1b893772e..909510b1e 100644 --- a/src/meta/fsb5.c +++ b/src/meta/fsb5.c @@ -488,10 +488,9 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { vgmstream->interleave_block_size = 0x8c; break; -#if 0 //disabled until some game is found, can be created in the GUI tool #ifdef VGM_USE_FFMPEG - case 0x11: { /* FMOD_SOUND_FORMAT_OPUS */ - int skip = 312; //fsb_opus_get_encoder_delay(fsb5.stream_offset, sb); /* returns 120 but this seems correct */ + case 0x11: { /* FMOD_SOUND_FORMAT_OPUS [LEGO 2K Drive (Switch)] */ + int skip = 312; //fsb_opus_get_encoder_delay(fsb5.stream_offset, sb); /* returns 120 but this seems correct in test files */ //vgmstream->num_samples -= skip; vgmstream->codec_data = init_ffmpeg_fsb_opus(sb, fsb5.stream_offset, fsb5.stream_size, vgmstream->channels, skip, vgmstream->sample_rate); @@ -500,7 +499,6 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) { vgmstream->layout_type = layout_none; break; } -#endif #endif default: vgm_logi("FSB5: unknown codec 0x%x (report)\n", fsb5.codec); From 372dfbffe5163fabc6931831c3bab1369a5a6ddd Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 00:37:37 +0200 Subject: [PATCH 002/141] Add TXTH experimental 'subsong_sum' feature --- doc/TXTH.md | 7 ++++--- src/meta/txth.c | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/doc/TXTH.md b/doc/TXTH.md index 27d617e9d..b52eb8108 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -53,8 +53,7 @@ The following can be used in place of `(value)` for `(key) = (value)` commands. * `:LE|BE`: value is little/big endian (optional, defaults to LE) * `$1|2|3|4`: value has size of 8/16/24/32 bit (optional, defaults to 4) * Example: `@0x10:BE$2` means `get big endian 16b value at 0x10` -- `(field)`: uses current value of some fields. Accepted strings: - - `interleave, interleave_last, channels, sample_rate, start_offset, data_size, num_samples, loop_start_sample, loop_end_sample, subsong_count, subsong_spacing, subfile_offset, subfile_size, base_offset, name_valueX` +- `(field)`: uses current value of some fields (`interleave`, `channels`, `start_offset`, `data_size`, `num_samples`, `subsong_count`, `subfile_size`, `base_offset`, `name_valueX`, etc) - `subsong` is a special field for current subsong - `(other)`: other special values for certain keys, described per key @@ -419,12 +418,14 @@ Sets the number of subsongs in the file, adjusting reads per subsong N: `value = Instead of `subsong_spacing` you can use `subsong_offset` (older alias). -Mainly for bigfiles with consecutive headers per subsong, set subsong_offset to 0 when done as it affects any reads. The current subsong number is handled externally by plugins or TXTP. +Mainly for bigfiles with consecutive headers per subsong, set `subsong_offset` to 0 when done as it affects any reads. The current subsong number is handled externally by plugins or TXTP. ``` subsong_count = (value) subsong_spacing = (value) ``` +A experimental field is `subsong_sum = (value)`, that sums all subsong values up to current subsong. Mainly meant when offsets are the sum of subsong sizes: if you have a table of sizes at 0x10 for 3 subsongs, each of size 0x1000, then `subsong_sum = @0x10` for first subsong sums 0x0000, 0x1000 for second, 0x2000 for third (can be used later as `start_offset = subsong_sum`). + #### NAMES Sets the name of the stream, most useful when used with subsongs. TXTH will read a string at `name_offset`, with `name_size characters`. diff --git a/src/meta/txth.c b/src/meta/txth.c index 1627c0505..a4a5d29e5 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -116,6 +116,7 @@ typedef struct { int target_subsong; uint32_t subsong_count; uint32_t subsong_spacing; + uint32_t subsong_sum; uint32_t name_offset_set; uint32_t name_offset; @@ -1300,6 +1301,23 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha else if (is_string(key,"subsong_spacing") || is_string(key,"subsong_offset")) { if (!parse_num(txth->sf_head,txth,val, &txth->subsong_spacing)) goto fail; } + else if (is_string(key,"subsong_sum")) { + /* add all values up to current subsong (for example, to add all sizes to get current offset, so get start_offset) + * doesn't include current (that is, reading size from fist subsong doesn't add anything) */ + int default_subsong = txth->target_subsong; + uint32_t subsong_sum = 0; + + for (int i = 0; i < default_subsong - 1; i++) { + txth->target_subsong = i + 1; + + if (!parse_num(txth->sf_head,txth,val, &subsong_sum)) goto fail; + + txth->subsong_sum += subsong_sum; + } + + txth->target_subsong = default_subsong; + } + else if (is_string(key,"name_offset")) { if (!parse_num(txth->sf_head,txth,val, &txth->name_offset)) goto fail; txth->name_offset_set = 1; @@ -2001,6 +2019,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ else if ((n = is_string_field(val,"subsong_count"))) value = txth->subsong_count; else if ((n = is_string_field(val,"subsong_spacing"))) value = txth->subsong_spacing; else if ((n = is_string_field(val,"subsong_offset"))) value = txth->subsong_spacing; + else if ((n = is_string_field(val,"subsong_sum"))) value = txth->subsong_sum; else if ((n = is_string_field(val,"subfile_offset"))) value = txth->subfile_offset; else if ((n = is_string_field(val,"subfile_size"))) value = txth->subfile_size; else if ((n = is_string_field(val,"base_offset"))) value = txth->base_offset; From 5978311143f609916b4f4ebea9988a1c8d6287de Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 00:38:01 +0200 Subject: [PATCH 003/141] Add .wvd extension [DK Barrel Blast (Wii)] --- src/formats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/formats.c b/src/formats.c index d1f006934..5133aa33d 100644 --- a/src/formats.c +++ b/src/formats.c @@ -639,6 +639,7 @@ static const char* extension_list[] = { "wua", "wv2", "wv6", + "wvd", //txth/reserved [Donkey Kong Barrel Blast (Wii)] "wve", "wvs", "wvx", From b121c14da6942f9da944cec33fb2c5ad0246dcb0 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 00:38:31 +0200 Subject: [PATCH 004/141] cli: extra debug seek flag --- cli/vgmstream_cli.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/cli/vgmstream_cli.c b/cli/vgmstream_cli.c index 5f47c71de..7fb2d3816 100644 --- a/cli/vgmstream_cli.c +++ b/cli/vgmstream_cli.c @@ -87,6 +87,7 @@ static void usage(const char* progname, int is_help) { " -v: validate extensions (for extension testing)\n" " -r: reset and output a second file (for reset testing)\n" " -k N: kills (seeks) N samples before decoding (for seek testing)\n" + " -2 seeks to loop start, -3 seeks to loop end\n" " -K N: kills (seeks) again to N samples before decoding (for seek testing)\n" " -t: print !tags found in !tags.m3u (for tag testing)\n" " -T: print title (for title testing)\n" @@ -736,15 +737,24 @@ static int convert_file(cli_config* cfg) { /* get final play config */ len_samples = vgmstream_get_samples(vgmstream); - if (len_samples <= 0) + if (len_samples <= 0) { + fprintf(stderr, "wrong time config\n"); goto fail; + } - if (cfg->seek_samples1 < -1) /* ex value for loop testing */ + /* special values for loop testing */ + if (cfg->seek_samples1 == -2) { /* loop start...end */ cfg->seek_samples1 = vgmstream->loop_start_sample; - if (cfg->seek_samples1 >= len_samples) - cfg->seek_samples1 = -1; - if (cfg->seek_samples2 >= len_samples) - cfg->seek_samples2 = -1; + } + if (cfg->seek_samples1 == -3) { /* loop end..end */ + cfg->seek_samples1 = vgmstream->loop_end_sample; + } + + /* would be ignored by seek code though (allowed for seek_samples2 to test this) */ + if (cfg->seek_samples1 < -1 || cfg->seek_samples1 >= len_samples) { + fprintf(stderr, "wrong seek config\n"); + goto fail; + } if (cfg->play_forever && !vgmstream_get_play_forever(vgmstream)) { fprintf(stderr, "file can't be played forever"); From 13f1cf1114321827d24aa762c018c0d32b4a4053 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 00:38:46 +0200 Subject: [PATCH 005/141] doc --- doc/FORMATS.md | 147 ++++++++++++++++++++++++++----------------------- 1 file changed, 79 insertions(+), 68 deletions(-) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 8b2e53d80..c1b0fdfa2 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -246,74 +246,85 @@ This list is not complete and many other files are supported. Quick list of most codecs vgmstream supports, including many obscure ones that are used in few games. -- PCM 16-bit -- PCM 8-bit (signed, unsigned) -- PCM 4-bit (signed, unsigned) -- PCM 32-bit float -- u-Law/a-LAW -- CRI ADX (standard, fixed, exponential, encrypted) -- Nintendo DSP ADPCM a.k.a GC ADPCM -- Nintendo DTK ADPCM -- Nintendo AFC ADPCM -- ITU-T G.721 -- CD-ROM XA ADPCM -- Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended) -- Sony HEVAG -- Electronic Arts EA-XA (stereo, mono, Maxis) -- Electronic Arts EA-XAS (v0, v1) -- DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc) -- Microsoft MS IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc) -- Microsoft MS ADPCM (standard, Cricket Audio) -- Westwood VBR ADPCM -- Yamaha ADPCM (AICA, Aska) -- Procyon Studio ADPCM -- Level-5 0x555 ADPCM -- lsf ADPCM -- Konami MTAF ADPCM -- Konami MTA2 ADPCM -- Paradigm MC3 ADPCM -- FMOD FADPCM 4-bit ADPCM -- Konami XMD 4-bit ADPCM -- Platinum 4-bit ADPCM -- Argonaut ASF 4-bit ADPCM -- Tantalus 4-bit ADPCM -- Ocean DSA 4-bit ADPCM -- Circus XPCM ADPCM -- Circus XPCM VQ -- OKI 4-bit ADPCM (16-bit output, 4-shift, PC-FX) -- Ubisoft 4/6-bit ADPCM -- Tiger Game.com ADPCM -- LucasArts iMUSE VBR ADPCM -- CompressWave (CWav) Huffman ADPCM -- SDX2 2:1 Squareroot-Delta-Exact compression DPCM -- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM -- Activision EXAKT SASSC DPCM -- Xilam DERF DPCM -- InterPlay ACM -- VisualArt's NWA -- Electronic Arts MicroTalk a.k.a. UTK or UMT -- Relic Codec -- CRI HCA -- tri-Ace PS2 Codec -- Xiph Vorbis (Ogg, FSB5, Wwise, OGL, Silicon Knights) -- MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc) -- ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco) -- ITU-T G.719 annex B a.k.a. Polycom Siren 22 -- Electronic Arts EASpeex -- Electronic Arts EALayer3 -- Electronic Arts EA-XMA -- Sony ATRAC3, ATRAC3plus -- Sony ATRAC9 -- Microsoft XMA1/2 -- Microsoft WMA v1, WMA v2, WMAPro -- AAC -- Bink -- AC3/SPDIF -- Xiph Opus (Ogg, Switch, EA, UE4, Exient) -- Xiph CELT (FSB) -- Musepack -- FLAC -- Inti Creates' Range / DCT codecs +- PCM + - PCM 16-bit (little endian, big endian) + - PCM 8-bit (signed, unsigned, sign bit) + - PCM 4-bit (signed, unsigned) + - PCM 24-bit (little endian, big endian) + - PCM 32-bit float + - u-Law/a-LAW +- ADPCM (BRR/XA-style) + - CD-ROM XA ADPCM + - Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended) + - CRI ADX (standard, fixed, exponential, encrypted) + - Silicon Graphics VADPCM + - Nintendo DSP ADPCM a.k.a GC ADPCM + - Nintendo DTK ADPCM + - Nintendo AFC ADPCM + - Microsoft MSADPCM (standard, mono, Cricket Audio) + - Electronic Arts EA-XA (stereo, mono, Maxis) + - Electronic Arts EA-XAS (v0, v1) + - Konami MTAF ADPCM + - Konami MTA2 ADPCM + - FMOD FADPCM ADPCM + - Procyon Studio ADPCM + - Level-5 0x555 ADPCM + - Konami XMD ADPCM + - Argonaut ASF ADPCM + - Tantalus ADPCM +- ADPCM (IMA-style) + - DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc) + - Microsoft MS-IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc) + - Yamaha ADPCM (AICA, Aska) + - Westwood VBR ADPCM + - OKI ADPCM (16-bit output, 4-shift, PC-FX) + - LucasArts iMUSE VBR ADPCM + - Tiger Game.com ADPCM +- ADPCM (others) + - Sony HEVAG + - Ubisoft 4/6-bit ADPCM + - Platinum ADPCM + - Paradigm MC3 ADPCM + - Ocean DSA ADPCM + - lsf ADPCM + - ITU-T G.721 + - CompressWave (CWav) Huffman ADPCM +- Perceptual/transform-based + - MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc) + - Xiph Vorbis (Ogg, FSB, Wwise, OGL, Silicon Knights) + - CRI HCA + - ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco) + - ITU-T G.719 annex B a.k.a. Polycom Siren 22 + - Xiph Opus (Ogg, Switch, EA, UE4, Exient, FSB) + - Xiph CELT (FSB) + - Microsoft XMA1/2 + - Microsoft WMA v1, WMA v2, WMAPro + - AAC + - Sony ATRAC3 + - Sony ATRAC3plus + - Sony ATRAC9 + - Relic Codec + - tri-Ace PS2 Codec + - Bink + - AC3/SPDIF + - Musepack + - Electronic Arts EASpeex + - Electronic Arts EALayer3 + - Electronic Arts EA-XMA + - Electronic Arts MicroTalk a.k.a. UTK or UMT + - Inti Creates DCT codec + - Circus XPCM VQ +- Misc + - SDX2 2:1 Squareroot-Delta-Exact compression DPCM + - CBD2 2:1 Cuberoot-Delta-Exact compression DPCM + - Activision EXAKT SASSC DPCM + - Xilam DERF DPCM + - Circus XPCM DPCM + - VisualArt's NWA PCM/DPCM + - Marble WADY PCM/DPCM + - InterPlay ACM + - Inti Creates Range codec + - FLAC - Others Sometimes standard codecs come in non-standard layouts that aren't normally From b158e8122384e174453ef526cd895411f7df80a2 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 29 May 2023 01:02:15 +0200 Subject: [PATCH 006/141] Update version.h --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index d2f3ab51b..ca1a766dd 100644 --- a/version.h +++ b/version.h @@ -32,7 +32,7 @@ * versions should return "rNNNN" without extra text commit number text */ -#define VGMSTREAM_VERSION "r1831" +#define VGMSTREAM_VERSION "r1843" #endif #endif From a9247228e516d07bb80850fabd90a1d02a91149d Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:03:21 -0500 Subject: [PATCH 007/141] Update ngc_adpdtk.c Add known extension [Bloody Roar: Primal Fury (GC)] --- src/meta/ngc_adpdtk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/meta/ngc_adpdtk.c b/src/meta/ngc_adpdtk.c index d57b30a3e..ba886c826 100644 --- a/src/meta/ngc_adpdtk.c +++ b/src/meta/ngc_adpdtk.c @@ -11,7 +11,8 @@ VGMSTREAM* init_vgmstream_dtk(STREAMFILE* sf) { /* checks */ /* .dtk: standard [XGRA (GC)] - * .adp: standard [Harvest Moon AWL (GC)] + * .adp: standard [Harvest Moon: AWL (GC)] + * .trk: standard [Bloody Roar: Primal Fury (GC)] * .wav/lwav: Alien Hominid (GC) */ if (!check_extensions(sf,"dtk,adp,wav,lwav")) goto fail; From bd92018b355f5c12981499c00c34040dd3317c05 Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:06:20 -0500 Subject: [PATCH 008/141] Update ngc_adpdtk.c --- src/meta/ngc_adpdtk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/ngc_adpdtk.c b/src/meta/ngc_adpdtk.c index ba886c826..b747edf6a 100644 --- a/src/meta/ngc_adpdtk.c +++ b/src/meta/ngc_adpdtk.c @@ -14,7 +14,7 @@ VGMSTREAM* init_vgmstream_dtk(STREAMFILE* sf) { * .adp: standard [Harvest Moon: AWL (GC)] * .trk: standard [Bloody Roar: Primal Fury (GC)] * .wav/lwav: Alien Hominid (GC) */ - if (!check_extensions(sf,"dtk,adp,wav,lwav")) + if (!check_extensions(sf,"dtk,adp,trk,wav,lwav")) goto fail; /* check valid frames as files have no header, and .adp/wav are common */ From 8f63eba6939cae41dc23a6a7c977045096f0d02e Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:08:54 -0500 Subject: [PATCH 009/141] Fix some few DSP. RSD [Hulk (GC)] 0x1c likely seems to be the proper coef offset. --- src/meta/rsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/rsd.c b/src/meta/rsd.c index 84651d88c..a8b22d077 100644 --- a/src/meta/rsd.c +++ b/src/meta/rsd.c @@ -104,7 +104,7 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x08; /* assumed, known files are mono */ - dsp_read_coefs_le(vgmstream,sf,0x14,0x2e); /* LE! */ + dsp_read_coefs_le(vgmstream,sf,0x1c,0x2e); /* LE! */ dsp_read_hist_le (vgmstream,sf,0x38,0x2e); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels); From 05604ffb82bc83d1f26722641610306daef8f544 Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:16:51 -0500 Subject: [PATCH 010/141] Fix some .str+wav [Big Bumpin (Xbox)] --- src/meta/str_wav.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/meta/str_wav.c b/src/meta/str_wav.c index 84e9117ca..0c915eda4 100644 --- a/src/meta/str_wav.c +++ b/src/meta/str_wav.c @@ -639,6 +639,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } /* SpongeBob SquarePants: Creature from the Krusty Krab (PS2)[2006] */ + /* Big Bumpin (Xbox)[2006] */ /* Sneak King (Xbox)[2006] */ if ( read_u32be(0x04,sf_h) == 0x00000800 && read_u32le(0x08,sf_h) == 0x00000000 && @@ -673,9 +674,9 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } else { strwav->codec = XBOX; - strwav->interleave = strwav->tracks > 1 ? 0xD800/2 : 0xD800; /* assumed for multitrack */ + strwav->interleave = strwav->tracks > 1 ? 0x9000 : 0xD800; /* assumed for multitrack */ } - ;VGM_LOG("STR+WAV: header SBCKK/SK (PS2)\n"); + ;VGM_LOG("STR+WAV: header SBCKK/BB/SK (PS2/Xbox)\n"); return 1; } From 404ea26d64ccde70bf7a43186c606cd13a72b35e Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:42:35 -0500 Subject: [PATCH 011/141] Add .PS3 extension [THPG (PS3)] --- src/meta/fsb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/meta/fsb.c b/src/meta/fsb.c index ab9961591..182b2da65 100644 --- a/src/meta/fsb.c +++ b/src/meta/fsb.c @@ -119,8 +119,9 @@ VGMSTREAM* init_vgmstream_fsb(STREAMFILE* sf) { /* .fsb: standard * .bnk: Hard Corps Uprising (PS3) * .sfx: Geon Cube (Wii) - * .xen: Guitar Hero: World Tour (PC) */ - if ( !check_extensions(sf, "fsb,bnk,sfx,xen") ) + * .ps3: Neversoft games (PS3) + * .xen: Neversoft games (X360/PC) */ + if ( !check_extensions(sf, "fsb,bnk,sfx,ps3,xen") ) goto fail; fsb.id = read_u32be(0x00,sf); From b7fe0217794887c1e95cd18ca600ae7fcf94de4f Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:44:46 -0500 Subject: [PATCH 012/141] Update ngc_adpdtk.c --- src/meta/ngc_adpdtk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meta/ngc_adpdtk.c b/src/meta/ngc_adpdtk.c index b747edf6a..80c67dae2 100644 --- a/src/meta/ngc_adpdtk.c +++ b/src/meta/ngc_adpdtk.c @@ -12,7 +12,7 @@ VGMSTREAM* init_vgmstream_dtk(STREAMFILE* sf) { /* checks */ /* .dtk: standard [XGRA (GC)] * .adp: standard [Harvest Moon: AWL (GC)] - * .trk: standard [Bloody Roar: Primal Fury (GC)] + * .trk: Bloody Roar: Primal Fury (GC) * .wav/lwav: Alien Hominid (GC) */ if (!check_extensions(sf,"dtk,adp,trk,wav,lwav")) goto fail; From 35bdda8c8c739f689e8aeac9c2a730c12005f5df Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:46:57 -0500 Subject: [PATCH 013/141] Add .MOV extension [Dora the Explorer JttPP (GC)] --- src/meta/thp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/meta/thp.c b/src/meta/thp.c index 006399566..7ee541b2e 100644 --- a/src/meta/thp.c +++ b/src/meta/thp.c @@ -14,8 +14,9 @@ VGMSTREAM* init_vgmstream_thp(STREAMFILE* sf) { /* checks */ /* .thp: actual extension * .dsp: fake extension? + * .mov: Dora the Explorer: JttPP (GC) * (extensionless): Fragile (Wii) */ - if (!check_extensions(sf, "thp,dsp,")) + if (!check_extensions(sf, "thp,dsp,mov,")) goto fail; if (!is_id32be(0x00,sf, "THP\0")) goto fail; From c076fc701ba61fda1727cfe594a852cc4bd4a426 Mon Sep 17 00:00:00 2001 From: Hexagon123 <112926080+Hexagon123@users.noreply.github.com> Date: Wed, 31 May 2023 22:52:23 -0500 Subject: [PATCH 014/141] Add a few known extensions --- src/formats.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/formats.c b/src/formats.c index 5133aa33d..2107a7977 100644 --- a/src/formats.c +++ b/src/formats.c @@ -338,6 +338,7 @@ static const char* extension_list[] = { "mogg", //"m4a", //common //"m4v", //common + //"mov", //common //"mp+", //common [Moonshine Runners (PC)] //"mp2", //common //"mp3", //common @@ -559,6 +560,7 @@ static const char* extension_list[] = { "tk5", "tmx", "tra", + "trk", "tun", "txth", "txtp", From 288d1e57d02ff5882dcbfdf3f0547a59c9ddf99f Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 3 Jun 2023 17:55:35 +0200 Subject: [PATCH 015/141] fixes for last pr --- src/formats.c | 1 + src/meta/rsd.c | 18 ++++++++++++------ src/meta/str_wav.c | 4 ++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/formats.c b/src/formats.c index 2107a7977..9db4e8d4b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -706,6 +706,7 @@ static const char* common_extension_list[] = { "flac", //common "m4a", //common "m4v", //common + "mov", //common "mp+", //common [Moonshine Runners (PC)] "mp2", //common "mp3", //common diff --git a/src/meta/rsd.c b/src/meta/rsd.c index a8b22d077..58547fb4d 100644 --- a/src/meta/rsd.c +++ b/src/meta/rsd.c @@ -5,7 +5,7 @@ /* RSD - from Radical Entertainment games */ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - off_t start_offset, name_offset; + uint32_t start_offset, name_offset, coef_offset; size_t data_size; int loop_flag, channels, sample_rate, interleave; uint32_t codec; @@ -14,9 +14,9 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { /* checks */ if ((read_u32be(0x00,sf) & 0xFFFFFF00) != get_id32be("RSD\00")) - goto fail; + return NULL; if (!check_extensions(sf,"rsd,rsp")) - goto fail; + return NULL; loop_flag = 0; @@ -32,14 +32,19 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { interleave = read_u32le(0x14,sf); /* VAG only, 0x04 otherwise */ start_offset = read_u32le(0x18,sf); name_offset = 0; + coef_offset = 0x1C; + + if ((codec == get_id32be("GADP"))) + start_offset = 0xA0; break; case '4': /* known codecs: VAG/PCM/RADP/PCMB [The Simpsons: Hit & Run, Tetris Worlds, Hulk] */ - /* 0x14: padding */ + /* 0x14: padding/coefs */ /* 0x18: padding */ interleave = 0; start_offset = 0x800; name_offset = 0; + coef_offset = 0x14; /* PCMB/PCM/GADP normally start early but sometimes have padding [The Simpsons: Hit & Run (GC/Xbox)] */ if ((codec == get_id32be("PCM ") || codec == get_id32be("PCMB") || codec == get_id32be("GADP")) @@ -52,6 +57,7 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { name_offset = 0x18; /* dev file path */ interleave = 0; start_offset = 0x800; + coef_offset = 0x00; break; default: @@ -104,8 +110,8 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x08; /* assumed, known files are mono */ - dsp_read_coefs_le(vgmstream,sf,0x1c,0x2e); /* LE! */ - dsp_read_hist_le (vgmstream,sf,0x38,0x2e); + dsp_read_coefs_le(vgmstream,sf,coef_offset,0x2e); /* LE! */ + dsp_read_hist_le (vgmstream,sf,coef_offset + 0x24, 0x2e); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels); break; diff --git a/src/meta/str_wav.c b/src/meta/str_wav.c index 0c915eda4..18fc59d9e 100644 --- a/src/meta/str_wav.c +++ b/src/meta/str_wav.c @@ -639,7 +639,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } /* SpongeBob SquarePants: Creature from the Krusty Krab (PS2)[2006] */ - /* Big Bumpin (Xbox)[2006] */ + /* Big Bumpin' (Xbox)[2006] */ /* Sneak King (Xbox)[2006] */ if ( read_u32be(0x04,sf_h) == 0x00000800 && read_u32le(0x08,sf_h) == 0x00000000 && @@ -674,7 +674,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } else { strwav->codec = XBOX; - strwav->interleave = strwav->tracks > 1 ? 0x9000 : 0xD800; /* assumed for multitrack */ + strwav->interleave = strwav->tracks > 1 ? 0x9000 : 0xD800; } ;VGM_LOG("STR+WAV: header SBCKK/BB/SK (PS2/Xbox)\n"); return 1; From d5e567072b3ca11491a96189eded65216a7ad2f2 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 3 Jun 2023 17:56:19 +0200 Subject: [PATCH 016/141] Fix some SFH/SSPR --- src/meta/sfh.c | 111 ++++++++++++++++++++++++++++-------------------- src/meta/sspr.c | 19 ++++----- 2 files changed, 74 insertions(+), 56 deletions(-) diff --git a/src/meta/sfh.c b/src/meta/sfh.c index b22a2205f..7ca7a902a 100644 --- a/src/meta/sfh.c +++ b/src/meta/sfh.c @@ -1,46 +1,65 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "sfh_streamfile.h" - - -/* .SFH - Capcom wrapper [Devil May Cry 4 Demo (PS3), Jojo's Bizarre Adventure HD (PS3)] */ -VGMSTREAM * init_vgmstream_sfh(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - uint32_t version; - size_t clean_size, block_size; - - /* check extensions */ - if ( !check_extensions(streamFile,"at3")) - goto fail; - - if (read_32bitBE(0x00, streamFile) != 0x00534648) /* "\0SFH" */ - goto fail; - if (read_32bitBE(0x10, streamFile) != 0x52494646) /* "RIFF" */ - goto fail; - - /* mini header */ - version = read_32bitBE(0x04,streamFile); - clean_size = read_32bitBE(0x08,streamFile); /* there is padding data at the end */ - /* 0x0c: always 0 */ - - switch(version) { - case 0x00010000: block_size = 0x10010; break; /* DMC4 Demo (not retail) */ - case 0x00010001: block_size = 0x20000; break; /* Jojo */ - default: goto fail; - } - - temp_streamFile = setup_sfh_streamfile(streamFile, 0x00, block_size, clean_size, "at3"); - if (!temp_streamFile) goto fail; - - vgmstream = init_vgmstream_riff(temp_streamFile); - if (!vgmstream) goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "sfh_streamfile.h" + +typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*); + + +/* .SFH - Capcom wrapper used with common audio extensions [Devil May Cry 4 Demo (PS3), Jojo's Bizarre Adventure HD (PS3), Sengoku Basara 4 Sumeragi (PS3)] */ +VGMSTREAM* init_vgmstream_sfh(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + init_vgmstream_t init_vgmstream = NULL; + + + /* checks */ + if (!is_id32be(0x00, sf, "\0SFH")) + return NULL; + if (!check_extensions(sf,"at3,sspr")) + return NULL; + + /* mini header */ + uint32_t version = read_u32be(0x04,sf); + uint32_t clean_size = read_u32be(0x08,sf); /* there is padding data at the end */ + /* 0x0c: always 0 */ + + char* extension; + uint32_t header_id = read_u32be(0x10,sf); + switch(header_id) { + case 0x52494646: // RIFF + init_vgmstream = init_vgmstream_riff; + extension = "at3"; + break; + + case 0x53535052: // SSPR + init_vgmstream = init_vgmstream_sspr; + extension = "sspr"; + break; + + case 0x00434C44: // \0CLD (.dlcp) + case 0x00435241: // \0CRA (.arc) + default: + goto fail; + } + + uint32_t block_size; + switch(version) { + case 0x00010000: block_size = 0x10010; break; /* DMC4 Demo (not retail) */ + case 0x00010001: block_size = 0x20000; break; /* Jojo, SB4 */ + default: goto fail; + } + + temp_sf = setup_sfh_streamfile(sf, 0x00, block_size, clean_size, extension); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream(temp_sf); + if (!vgmstream) goto fail; + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/sspr.c b/src/meta/sspr.c index c877be760..3a58b10ff 100644 --- a/src/meta/sspr.c +++ b/src/meta/sspr.c @@ -6,23 +6,22 @@ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; - uint32_t name_offset, subfile_offset, subfile_size, name_size; - int big_endian; - int total_subsongs, target_subsong = sf->stream_index; - char* extension; - uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL; - /* checks */ - if (!check_extensions(sf,"sspr")) - goto fail; if (!is_id32be(0x00,sf,"SSPR")) - goto fail; + return NULL; + if (!check_extensions(sf,"sspr")) + return NULL; + + uint32_t name_offset, subfile_offset, subfile_size, name_size; + int total_subsongs, target_subsong = sf->stream_index; + char* extension; + read_u32_t read_u32 = NULL; /* Simple (audio only) container used some Capcom games (common engine?). * Some files come with a .stqr with unknown data (cues?). */ - big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */ + int big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */ read_u32 = big_endian ? read_u32be : read_u32le; total_subsongs = read_u32(0x08,sf); From 392fa5c8f541077fd27b05d7cf5610579dab70d9 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 3 Jun 2023 17:57:01 +0200 Subject: [PATCH 017/141] build: fix compiling without ffmpeg --- src/meta/bwav.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/meta/bwav.c b/src/meta/bwav.c index 8cc39a368..b2f933cd8 100644 --- a/src/meta/bwav.c +++ b/src/meta/bwav.c @@ -75,13 +75,15 @@ VGMSTREAM* init_vgmstream_bwav(STREAMFILE* sf) { vgmstream->allow_dual_stereo = 1; /* Animal Crossing: Happy Home Paradise */ break; - case 0x0002: /* Zelda TOTK (Switch) */ +#ifdef VGM_USE_FFMPEG + case 0x0002: /* The Legend of Zelda: Tears of the Kingdom (Switch) */ vgmstream->layout_data = build_layered_data(sf, channels); if (!vgmstream->layout_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_layered; break; +#endif default: goto fail; } From 8b02afba85ee1172c130bfbcc5388c58bef006f3 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 3 Jun 2023 17:57:46 +0200 Subject: [PATCH 018/141] Fix FSB key --- src/meta/fsb_keys.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/meta/fsb_keys.h b/src/meta/fsb_keys.h index 384ef26fe..b852a04ec 100644 --- a/src/meta/fsb_keys.h +++ b/src/meta/fsb_keys.h @@ -25,7 +25,7 @@ typedef struct { #define MODE_FSB4_STD (FLAG_FSB4 | FLAG_STD) #define MODE_FSB4_ALT (FLAG_FSB4 | FLAG_ALT) -#define MODE_FSB4_ALL (FLAG_FSB4 | FLAG_ALT) +#define MODE_FSB4_ALL (FLAG_FSB4 | FLAG_STD | FLAG_ALT) #define MODE_FSB5_STD (FLAG_FSB5 | FLAG_STD) #define MODE_FSB5_ALT (FLAG_FSB5 | FLAG_STD) #define MODE_FSB5_ALL (FLAG_FSB5 | FLAG_STD | FLAG_ALT) @@ -42,8 +42,8 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSB5_STD, FSBKEY_ADD("sTOoeJXI2LjK8jBMOk8h5IDRNZl3jq3I") }, // Slightly Mad Studios: Project CARS (PC?), World of Speed (PC) { MODE_FSB5_STD, FSBKEY_ADD("%lAn2{Pi*Lhw3T}@7*!kV=?qS$@iNlJ") }, // Ghost in the Shell: First Assault (PC) { MODE_FSB5_STD, FSBKEY_ADD("1^7%82#&5$~/8sz") }, // RevHeadz Engine Sounds (Mobile) - { MODE_FSB5_ALL, FSBKEY_ADD("FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg") }, // Dark Souls 3 (PC) [untested] - { MODE_FSB4_ALL, FSBKEY_ADD("p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj") }, // Need for Speed Shift 2 Unleashed (PC demo?)[untested] + { MODE_FSB5_STD, FSBKEY_ADD("FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg") }, // Dark Souls 3 (PC) + { MODE_FSB4_STD, FSBKEY_ADD("p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj") }, // Need for Speed Shift 2 Unleashed (PC) { MODE_FSB5_STD, FSBKEY_ADD("996164B5FC0F402983F61F220BB51DC6") }, // Mortal Kombat X/XL (PC) { MODE_FSB5_STD, FSBKEY_ADD("logicsounddesignmwsdev") }, // Mirror War: Reincarnation of Holiness (PC) { MODE_FSBS_ALL, FSBKEY_ADD("gat@tcqs2010") }, // Xian Xia Chuan (PC) [untested] @@ -56,8 +56,8 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSBS_ALL, FSBKEY_ADD("B2A7BB00") }, // Supreme Commander 2 [untested] { MODE_FSB4_STD, FSBKEY_ADD("ghfxhslrghfxhslr") }, // Cookie Run: Ovenbreak { MODE_FSB4_ALT, FSBKEY_ADD("truck/impact/carbody") },// Monster Jam (PS2) [FSB3] - { MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") }, - { MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") }, + { MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") }, // Guitar Hero 5 (X360) + { MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") }, // Guitar Hero: Metallica (X360) { MODE_FSB5_STD, FSBKEY_ADD("G0KTrWjS9syqF7vVD6RaVXlFD91gMgkC") }, // Sekiro: Shadows Die Twice (PC) { MODE_FSB5_STD, FSBKEY_ADD("BasicEncryptionKey") }, // SCP: Unity (PC) { MODE_FSB5_STD, FSBKEY_ADD("FXnTffGJ9LS855Gc") }, // Worms Rumble Beta (PC) From 7e632a5cf7c2ad4b6c93048f5bdfd3e97b4a9ef7 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 3 Jun 2023 18:07:20 +0200 Subject: [PATCH 019/141] doc --- README.md | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 15aca1983..99ec73827 100644 --- a/README.md +++ b/README.md @@ -39,52 +39,58 @@ There are multiple end-user components: The main library (plain *vgmstream*) is the code that handles the internal conversion, while the above components are what you use to get sound. -If you just want to convert game audio to `.wav`, easiest would be getting *vgmstream-cli* (see -below) then drag-and-drop one or more files to the executable. This should create `(file.extension).wav`, -if the format is supported. More usable would be installing a music player like *foobar2000* (for -Windows) or *Audacious* (for Linux) then the appropriate component, so you can listen to VGM without -converting and set options like infinite looping. +If you want to convert game audio to `.wav`, try getting *vgmstream-cli* (see below) then +drag-and-drop one or more files to the executable (support may vary per O.S. or distro). +This should create `(file.extension).wav`, if the format is supported. More user-friendly +would be installing a player like *foobar2000* (for Windows) or *Audacious* (for Linux) +and the vgmstream plugin. Then you can directly listen your files and set options like infinite +looping, or convert to `.wav` with the player's options (also easier if your file has multiple +"subsongs"). See [components](doc/USAGE.md#components) in the *usage guide* for full install instructions and explanations. The aim is feature parity, but there are a few differences between them due to -missing implementation on vgmstream's side or lack of support in target player or API. +missing parts on vgmstream's side or lack of support in the player. -Note vgmstream cannot *encode* (convert from `.wav` to some video game format), it only *decodes* +Note that vgmstream cannot *encode* (convert from `.wav` to a video game format), it only *decodes* (plays game audio). ### Windows -You should get `vgmstream-win.zip`, which also bundles various components, or -`foo_input_vgmstream.fb2k-component` for the installable foobar2000 plugin from the -latest prebuilt binaries on our website: +Get the latest prebuilt binaries (CLI/plugins/etc) on our website: - https://vgmstream.org -You can also get them from the less frequently updated releases on GitHub: +Or the less frequent "official" releases on GitHub: - https://github.com/vgmstream/vgmstream/releases -If the above links fail, you may also try the alternative, somewhat recent versions built by +The foobar2000 component is also available on https://www.foobar2000.org based on current +release. + +If the above links fail, you may also try the alternative versions built by [bnnm](https://github.com/bnnm): - https://github.com/bnnm/vgmstream-builds/raw/master/bin/vgmstream-latest-test-u.zip -If you prefer, you may compile the components from source as well, see the -[build guide](doc/BUILD.md) for more information. +You may compile from source as well, see the [build guide](doc/BUILD.md). ### Linux -For convenience, releases distribute a command-line decoder in `vgmstream-cli.zip`. It is -statically linked and should work on all systems running Linux kernel v3.2 and above. +A prebuilt CLI binary is available. It's statically linked and should work on systems running +Linux kernel v3.2 and above: - https://vgmstream.org - https://github.com/vgmstream/vgmstream/releases -Building from source will also give you *vgmstream.so*, an Audacious plugin, and *vgmstream123*, -a command-line player. +Building from source will also give you *vgmstream.so* (Audacious plugin), and *vgmstream123* +(command-line player). -When building from source code, many components have to be installed or compiled separately. The -[build guide](doc/BUILD.md) describes this process in more detail. For a quick build on Debian and -Ubuntu-style distributions, run `./make-build-cmake.sh`. The script will be installing various -dependencies, so you may prefer to copy the commands from the file and run them one by one. +When building, many extra components have to be installed or compiled separately, which the +[build guide](doc/BUILD.md) describes in detail. For a quick build on Debian and Ubuntu-style +distributions run `./make-build-cmake.sh`. The script will need to install various dependencies, +so you may prefer to copy commands and run them manually. ### macOS -Please follow the [build guide](doc/BUILD.md). +A prebuilt CLI binary is available as well: +- https://vgmstream.org +- https://github.com/vgmstream/vgmstream/releases + +Otherwise follow the [build guide](doc/BUILD.md). ## More info From 2e62b638c6e380c431ad4a5b172cf775c31812e2 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:15:58 +0200 Subject: [PATCH 020/141] Add HCA key --- src/meta/hca_keys.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index c50f1cc01..555f47a43 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -13,8 +13,8 @@ typedef struct { /** - * List of known keys, extracted from the game files (several found in 2ch.net, others from data analisys). - * CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form. + * List of known keys, extracted from the game files (most from data analisys, some from 2ch.net/forums). + * CRI's tools expect an unsigned 64 bit numberic string, but keys are commonly found online in hex form. * Keys only use 56 bits though, so the upper 8 bits can be ignored. * * Some ACB+AWB after mid 2018 use a user seed key + a scramble subkey in the AWB (normally 16b LE at 0x0e) @@ -1181,9 +1181,12 @@ static const hcakey_info hcakey_list[] = { // Love Live! School Idol Festival 2 MIRACLE LIVE (Android) {5067530812966687744}, // 46537c6ceb39d400 - // 404 Game RE:SET Prologue Demo (Android) + // 404 Game RE:SET (Android) {21588207721978971}, // 004CB25C4C9B1C5B + // Disney Star Smash (Android) + {3941111674189632}, // 000E006B915C3740 + }; #endif/*_HCA_KEYS_H_*/ From 35433e66501a2993cb1a07d3147d5fa9df648590 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:16:32 +0200 Subject: [PATCH 021/141] Add TXTH ULAW/ALAW codecs --- doc/TXTH.md | 7 +++++++ src/formats.c | 6 +++--- src/meta/txth.c | 14 +++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/doc/TXTH.md b/doc/TXTH.md index b52eb8108..bc8e4365a 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -107,6 +107,13 @@ as explained below, but often will use default values. Accepted codec strings: # * For few rare games [Ikinari Maou (Switch)] # * Interleave is multiple of 0x4 (default) # +# - ULAW mu-Law 8-bit PCM +# * For few rare games [Burnout (GC)] +# * Interleave is multiple of 0x1 (default) +# - ALAW A-Law 8-bit PCM +# * For few rare games [Conquest of Elysium 3 (PC), Dominions 3/4 (PC)] +# * Interleave is multiple of 0x1 (default) +# # - IMA IMA ADPCM (mono/stereo) # * For some PC games, and rarely consoles # * Special interleave is multiple of 0x1, often +0x80 diff --git a/src/formats.c b/src/formats.c index 9db4e8d4b..793d799b0 100644 --- a/src/formats.c +++ b/src/formats.c @@ -61,8 +61,8 @@ static const char* extension_list[] = { //"aiff", //common "aix", "akb", - "al", - "al2", + "al", //txth/raw [Dominions 3 - The Awakening (PC)] + "al2", //txth/raw [Conquest of Elysium 3 (PC)] "ams", //txth/reserved [Super Dragon Ball Z (PS2) ELF names] "amts", //fake extension/header id for .stm (renamed? to be removed?) "an2", @@ -568,7 +568,7 @@ static const char* extension_list[] = { "u0", "ue4opus", - "ulw", + "ulw", //txth/raw [Burnout (GC)] "um3", "utk", "uv", diff --git a/src/meta/txth.c b/src/meta/txth.c index a4a5d29e5..73995bf8c 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -55,8 +55,10 @@ typedef enum { PCM8_SB, HEVAG, YMZ, + ULAW, + ALAW, - UNKNOWN = 99, + UNKNOWN = 255, } txth_codec_t; typedef enum { DEFAULT, NEGATIVE, POSITIVE, INVERTED } txth_loop_t; @@ -238,6 +240,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { case PCM8_U: case PCM8_SB: interleave = 0x01; break; case PCM_FLOAT_LE: interleave = 0x04; break; + case ULAW: + case ALAW: interleave = 0x01; break; default: break; } @@ -260,6 +264,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { case PCM8_U: coding = coding_PCM8_U; break; case PCM8_U_int: coding = coding_PCM8_U_int; break; case PCM8_SB: coding = coding_PCM8_SB; break; + case ULAW: coding = coding_ULAW; break; + case ALAW: coding = coding_ALAW; break; case PCM_FLOAT_LE: coding = coding_PCMFLOAT; break; case SDX2: coding = coding_SDX2; break; case DVI_IMA: coding = coding_DVI_IMA; break; @@ -333,6 +339,8 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { case coding_PCM8: case coding_PCM8_U: case coding_PCM8_SB: + case coding_ULAW: + case coding_ALAW: case coding_PCMFLOAT: case coding_PCM4: case coding_PCM4_U: @@ -993,6 +1001,8 @@ static txth_codec_t parse_codec(txth_header* txth, const char* val) { else if (is_string(val,"PCM_FLOAT_LE")) return PCM_FLOAT_LE; else if (is_string(val,"IMA_HV")) return IMA_HV; else if (is_string(val,"HEVAG")) return HEVAG; + else if (is_string(val,"ULAW")) return ULAW; + else if (is_string(val,"ALAW")) return ALAW; /* special handling */ else if (is_string(val,"name_value")) return txth->name_values[0]; else if (is_string(val,"name_value1")) return txth->name_values[0]; @@ -2132,6 +2142,8 @@ static int get_bytes_to_samples(txth_header* txth, uint32_t bytes) { case PCM8_U_int: case PCM8_U: case PCM8_SB: + case ULAW: + case ALAW: return pcm8_bytes_to_samples(bytes, txth->channels); case PCM_FLOAT_LE: return pcm_bytes_to_samples(bytes, txth->channels, 32); From 627e2310ade6f104308c2e89f01ef48e9654fd74 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:34:53 +0200 Subject: [PATCH 022/141] Remove .amts/smta/ps2stm fake ext (use .stm/lstm) --- doc/FORMATS.md | 2 +- src/formats.c | 3 - src/meta/stm.c | 237 +++++++++++++++++++++++++------------------------ 3 files changed, 120 insertions(+), 122 deletions(-) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index c1b0fdfa2..438327d00 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -215,7 +215,7 @@ This list is not complete and many other files are supported. - .sd9 (MS ADPCM) - .smp (MS ADPCM) - .spw (PSX configurable ADPCM) - - .stm/lstm [amts/ps2stm/stma] (16 bit PCM, DVI IMA ADPCM, GC DSP ADPCM) + - .stm/lstm (16 bit PCM, DVI IMA ADPCM, GC DSP ADPCM) - .str (SDX2 DPCM) - .stx (GC AFC ADPCM) - .ulw (u-Law PCM) diff --git a/src/formats.c b/src/formats.c index 793d799b0..7275b90c4 100644 --- a/src/formats.c +++ b/src/formats.c @@ -64,7 +64,6 @@ static const char* extension_list[] = { "al", //txth/raw [Dominions 3 - The Awakening (PC)] "al2", //txth/raw [Conquest of Elysium 3 (PC)] "ams", //txth/reserved [Super Dragon Ball Z (PS2) ELF names] - "amts", //fake extension/header id for .stm (renamed? to be removed?) "an2", "ao", "ap", @@ -415,7 +414,6 @@ static const char* extension_list[] = { "pona", "pos", "ps3", - "ps2stm", //fake extension for .stm (renamed? to be removed?) "psb", "psf", "psh", //fake extension for .vsv (to be removed) @@ -530,7 +528,6 @@ static const char* extension_list[] = { "ster", "sth", "stm", - "stma", //fake extension/header id for .stm "str", "stream", "strm", diff --git a/src/meta/stm.c b/src/meta/stm.c index 54146b5aa..d766deef9 100644 --- a/src/meta/stm.c +++ b/src/meta/stm.c @@ -1,118 +1,119 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* STM - from Angel Studios/Rockstar San Diego games (Red Dead Revolver, Midnight Club 2, TransWorld Surf) */ -VGMSTREAM * init_vgmstream_stm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count; - int big_endian, bps, interleave, data_size, loop_start = 0, loop_end = 0; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; - int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; - - /* check extension, case insensitive - * .stm is the real ext but common, rename to .lstm or .stma/amts/ps2stm (older) */ - if ( !check_extensions(streamFile,"stm,lstm,stma,amts,ps2stm")) - goto fail; - - /* check header */ - if ((read_32bitBE(0x00,streamFile) != 0x53544d41) && /* "SMTA" (LE) */ - (read_32bitBE(0x00,streamFile) != 0x414D5453)) /* "AMTS" (BE) */ - goto fail; - /* 0x04: revision (696F/696B/696A/6969) */ - - big_endian = (read_32bitBE(0x00,streamFile) == 0x414D5453); - if (big_endian) { - read_32bit = read_32bitBE; - read_16bit = read_16bitBE; - } else { - read_32bit = read_32bitLE; - read_16bit = read_16bitLE; - } - - start_offset = 0x800; - - interleave = read_32bit(0x08,streamFile); - bps = read_32bit(0x10,streamFile); - channel_count = read_32bit(0x14,streamFile); - data_size = read_32bit(0x18,streamFile); - loop_end = read_32bit(0x1c,streamFile); /* absolute offset */ - if (data_size + start_offset != get_streamfile_size(streamFile)) goto fail; - - if (big_endian) { - /* GC AMTS have a regular DSP header beyond 0x20, just use what we need, no point on validating all fields */ - loop_flag = read_16bit(0x2c,streamFile); - } - else { - /* PS2/Xbox STMA have either loop info or padding beyond 0x20 */ - if (read_32bit(0x20,streamFile) == 1) { /* may contain 0xCCCCCCCC garbage */ - loop_flag = 1; - loop_start = read_32bit(0x24,streamFile); - /* 0x28 (32b * ch): loop start hist+step per channel */ //todo setup - } -#if 0 - /* this works for some files that do full repeats, but also repeats many SFX */ - else if (data_size != loop_end && data_size != loop_end - 0x100) { /* data_size vs adjusted loop_end */ - loop_flag = 1; - } -#endif - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bit(0xc,streamFile); - vgmstream->meta_type = meta_STM; - vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none; - - switch(bps) { - case 4: - if (big_endian) { /* GC DSP ADPCM (TransWorld Surf GC) */ - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->interleave_block_size = interleave; - - vgmstream->num_samples = read_32bit(0x20,streamFile); - vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(0x30,streamFile)); - vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(0x34,streamFile))+1; - - dsp_read_coefs_be(vgmstream, streamFile, 0x3c, 0x60); - dsp_read_hist_be(vgmstream, streamFile, 0x60, 0x60); - } - else { /* DVI IMA ADPCM (Red Dead Revolver, Midnight Club 2) */ - vgmstream->coding_type = coding_DVI_IMA_int; - /* 'interleave not' reliable, strange values and rarely needs 0x80 */ - vgmstream->interleave_block_size = (interleave == 0xc000) ? 0x80 : 0x40; - - vgmstream->num_samples = ima_bytes_to_samples(data_size, vgmstream->channels); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = ima_bytes_to_samples(loop_end - start_offset, vgmstream->channels); - } - - break; - - case 16: /* PCM (Spy Hunter 2 PS2, rare) */ - vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; - vgmstream->interleave_block_size = 0x02; /* interleave not always reliable */ - - vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, bps); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end - start_offset, vgmstream->channels, bps); - - break; - - default: - VGM_LOG("STM: unknown bps %i\n", bps); - goto fail; - } - - - if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* STM - from Angel Studios/Rockstar San Diego games [Red Dead Revolver (PS2), Spy Hunter 2 (PS2/Xbox)] */ +VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + off_t start_offset; + int loop_flag = 0, channel_count; + int big_endian, bps, interleave, data_size, loop_start = 0, loop_end = 0; + int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL; + + + /* checks */ + if (!is_id32be(0x00,sf, "STMA") && /* LE */ + !is_id32be(0x00,sf, "AMTS")) /* BE */ + goto fail; + /* .stm: real extension + * .lstm: for plugins */ + if (!check_extensions(sf,"stm,lstm")) + goto fail; + + /* 0x04: revision (696F/696B/696A/6969) */ + + big_endian = is_id32be(0x00,sf, "AMTS"); + if (big_endian) { + read_32bit = read_32bitBE; + read_16bit = read_16bitBE; + } else { + read_32bit = read_32bitLE; + read_16bit = read_16bitLE; + } + + start_offset = 0x800; + + interleave = read_32bit(0x08,sf); + bps = read_32bit(0x10,sf); + channel_count = read_32bit(0x14,sf); + data_size = read_32bit(0x18,sf); + loop_end = read_32bit(0x1c,sf); /* absolute offset */ + if (data_size + start_offset != get_streamfile_size(sf)) goto fail; + + if (big_endian) { + /* GC AMTS have a regular DSP header beyond 0x20, just use what we need, no point on validating all fields */ + loop_flag = read_16bit(0x2c,sf); + } + else { + /* PS2/Xbox STMA have either loop info or padding beyond 0x20 */ + if (read_32bit(0x20,sf) == 1) { /* may contain 0xCCCCCCCC garbage */ + loop_flag = 1; + loop_start = read_32bit(0x24,sf); + /* 0x28 (32b * ch): loop start hist+step per channel */ //todo setup + } +#if 0 + /* this works for some files that do full repeats, but also repeats many SFX */ + else if (data_size != loop_end && data_size != loop_end - 0x100) { /* data_size vs adjusted loop_end */ + loop_flag = 1; + } +#endif + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channel_count,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_32bit(0xc,sf); + vgmstream->meta_type = meta_STM; + vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none; + + switch(bps) { + case 4: + if (big_endian) { /* GC DSP ADPCM (TransWorld Surf GC) */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->interleave_block_size = interleave; + + vgmstream->num_samples = read_32bit(0x20,sf); + vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(0x30,sf)); + vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(0x34,sf))+1; + + dsp_read_coefs_be(vgmstream, sf, 0x3c, 0x60); + dsp_read_hist_be(vgmstream, sf, 0x60, 0x60); + } + else { /* DVI IMA ADPCM (Red Dead Revolver, Midnight Club 2) */ + vgmstream->coding_type = coding_DVI_IMA_int; + /* 'interleave not' reliable, strange values and rarely needs 0x80 */ + vgmstream->interleave_block_size = (interleave == 0xc000) ? 0x80 : 0x40; + + vgmstream->num_samples = ima_bytes_to_samples(data_size, vgmstream->channels); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = ima_bytes_to_samples(loop_end - start_offset, vgmstream->channels); + } + + break; + + case 16: /* PCM (Spy Hunter 2 PS2, rare) */ + vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + vgmstream->interleave_block_size = 0x02; /* interleave not always reliable */ + + vgmstream->num_samples = pcm_bytes_to_samples(data_size, vgmstream->channels, bps); + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = pcm_bytes_to_samples(loop_end - start_offset, vgmstream->channels, bps); + + break; + + default: + VGM_LOG("STM: unknown bps %i\n", bps); + goto fail; + } + + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} From 4e40b8d73c5339684d39fb56544f326591d2d267 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:35:08 +0200 Subject: [PATCH 023/141] doc --- src/util/cri_utf.c | 4 ++-- src/util/cri_utf.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/util/cri_utf.c b/src/util/cri_utf.c index 36fb74da6..f2c5672d7 100644 --- a/src/util/cri_utf.c +++ b/src/util/cri_utf.c @@ -245,14 +245,14 @@ void utf_close(utf_context* utf) { } -int utf_get_column(utf_context* utf, const char* column) { +int utf_get_column(utf_context* utf, const char* column_name) { int i; /* find target column */ for (i = 0; i < utf->columns; i++) { struct utf_column_t* col = &utf->schema[i]; - if (col->name == NULL || strcmp(col->name, column) != 0) + if (col->name == NULL || strcmp(col->name, column_name) != 0) continue; return i; } diff --git a/src/util/cri_utf.h b/src/util/cri_utf.h index 3f73afc3c..798e52351 100644 --- a/src/util/cri_utf.h +++ b/src/util/cri_utf.h @@ -24,7 +24,7 @@ typedef struct utf_context utf_context; utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const char** p_row_name); void utf_close(utf_context* utf); -int utf_get_column(utf_context* utf, const char* column); +int utf_get_column(utf_context* utf, const char* column_name); /* query calls (passing column index is faster, when you have to read lots of rows) */ int utf_query_col_s8(utf_context* utf, int row, int column, int8_t* value); From f25905f7a95cf62546e1689e9d19b90d42323c14 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:37:20 +0200 Subject: [PATCH 024/141] Remove .al/al2 raw format (use TXTH + ALAW) --- src/formats.c | 1 - src/meta/raw_al.c | 42 ------------------------------------------ src/vgmstream.c | 1 - src/vgmstream_types.h | 1 - 4 files changed, 45 deletions(-) delete mode 100644 src/meta/raw_al.c diff --git a/src/formats.c b/src/formats.c index 7275b90c4..106539b6e 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1270,7 +1270,6 @@ static const meta_info meta_info_list[] = { {meta_EA_SNU, "Electronic Arts SNU header"}, {meta_AWC, "Rockstar AWC header"}, {meta_OPUS, "Nintendo Switch OPUS header"}, - {meta_RAW_AL, "Illwinter Game Design .AL raw header"}, {meta_PC_AST, "Capcom AST (PC) header"}, {meta_UBI_SB, "Ubisoft SBx header"}, {meta_NAAC, "Namco NAAC header"}, diff --git a/src/meta/raw_al.c b/src/meta/raw_al.c deleted file mode 100644 index 717940df1..000000000 --- a/src/meta/raw_al.c +++ /dev/null @@ -1,42 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* AL/AL2 - headerless a-law, from Illwinter Game Design games */ -VGMSTREAM * init_vgmstream_raw_al(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count; - - /* checks */ - /* .al: Dominions 3 - The Awakening (PC) - * .al2: Conquest of Elysium 3 (PC) */ - if ( !check_extensions(streamFile,"al,al2")) - goto fail; - - channel_count = check_extensions(streamFile,"al") ? 1 : 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = 22050; - vgmstream->coding_type = coding_ALAW; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - vgmstream->meta_type = meta_RAW_AL; - vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), channel_count, 8); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - start_offset = 0; - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index c9b8a3997..22d941c79 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -553,7 +553,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_raw_wavm, /* .wavm raw xbox */ init_vgmstream_raw_pcm, /* .raw raw PCM */ init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ - init_vgmstream_raw_al, /* .al/al2 raw A-LAW */ init_vgmstream_ngc_ulw, /* .ulw raw u-Law */ init_vgmstream_exakt_sc, /* .sc raw PCM */ init_vgmstream_zwdsp, /* fake format */ diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 22180fb44..d79e73159 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -560,7 +560,6 @@ typedef enum { meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */ meta_AWC, /* Rockstar AWC (GTA5, RDR) */ meta_OPUS, /* Nintendo Opus [Lego City Undercover (Switch)] */ - meta_RAW_AL, meta_PC_AST, /* Dead Rising (PC) */ meta_NAAC, /* Namco AAC (3DS) */ meta_UBI_SB, /* Ubisoft banks */ From 321321e9b6bdb6cf2f95068c28fa33bab5d98081 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:39:54 +0200 Subject: [PATCH 025/141] Remove .ulw raw format (use TXTH + ULAW) --- doc/TXTH.md | 2 +- src/formats.c | 1 - src/meta/meta.h | 6 +---- src/meta/ngc_ulw.c | 60 ------------------------------------------- src/vgmstream.c | 1 - src/vgmstream_types.h | 1 - 6 files changed, 2 insertions(+), 69 deletions(-) delete mode 100644 src/meta/ngc_ulw.c diff --git a/doc/TXTH.md b/doc/TXTH.md index bc8e4365a..397a27e47 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -111,7 +111,7 @@ as explained below, but often will use default values. Accepted codec strings: # * For few rare games [Burnout (GC)] # * Interleave is multiple of 0x1 (default) # - ALAW A-Law 8-bit PCM -# * For few rare games [Conquest of Elysium 3 (PC), Dominions 3/4 (PC)] +# * For few rare games [Illwinter Game Design games: Conquest of Elysium 3 (PC), Dominions 3/4 (PC)] # * Interleave is multiple of 0x1 (default) # # - IMA IMA ADPCM (mono/stereo) diff --git a/src/formats.c b/src/formats.c index 106539b6e..7937bb32b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1258,7 +1258,6 @@ static const meta_info meta_info_list[] = { {meta_GHS, "Hexadrive GHS/S_P_STH header"}, {meta_AAC_TRIACE, "tri-Ace AAC header"}, {meta_MTA2, "Konami MTA2 header"}, - {meta_NGC_ULW, "Criterion ULW raw header"}, {meta_XA_XA30, "Reflections XA30 header"}, {meta_XA_04SW, "Reflections 04SW header"}, {meta_TXTH, "TXTH generic header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index c0d9c08ca..d48b30b05 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -606,8 +606,6 @@ VGMSTREAM * init_vgmstream_va3(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_mta2(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_mta2_container(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ngc_ulw(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_xa_04sw(STREAMFILE * streamFile); @@ -627,7 +625,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_stm(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf); VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); @@ -646,8 +644,6 @@ VGMSTREAM* init_vgmstream_opus_nsopus(STREAMFILE* sf); VGMSTREAM* init_vgmstream_opus_sqex(STREAMFILE* sf); VGMSTREAM* init_vgmstream_opus_rsnd(STREAMFILE* sf); -VGMSTREAM * init_vgmstream_raw_al(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_pc_ast(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_naac(STREAMFILE * streamFile); diff --git a/src/meta/ngc_ulw.c b/src/meta/ngc_ulw.c deleted file mode 100644 index e873ac1d6..000000000 --- a/src/meta/ngc_ulw.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* ULW - headerless U-law, found in Burnout (GC) */ -VGMSTREAM * init_vgmstream_ngc_ulw(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count; - - - /* check extension, case insensitive */ - if ( !check_extensions(streamFile,"ulw")) - goto fail; - - /* raw data, the info is in the filename (really!) */ - { - char filename[PATH_LIMIT] = {0}; - - get_streamfile_filename(streamFile, filename,PATH_LIMIT); - - /* first letter gives the channels */ - if (filename[0]=='M') /* Mono */ - channel_count = 1; - else if (filename[0]=='S' || filename[0]=='D') /* Stereo/Dolby */ - channel_count = 2; - else - goto fail; - - /* not very robust but meh (other tracks don't loop) */ - if (strcmp(filename,"MMenu.ulw")==0 || strcmp(filename,"DMenu.ulw")==0) { - loop_flag = 1; - } - } - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = 32000; - vgmstream->coding_type = coding_ULAW; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x01; - vgmstream->meta_type = meta_NGC_ULW; - vgmstream->num_samples = pcm_bytes_to_samples(get_streamfile_size(streamFile), channel_count, 8); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - start_offset = 0; - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index 22d941c79..2c8d79d7f 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -553,7 +553,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_raw_wavm, /* .wavm raw xbox */ init_vgmstream_raw_pcm, /* .raw raw PCM */ init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ - init_vgmstream_ngc_ulw, /* .ulw raw u-Law */ init_vgmstream_exakt_sc, /* .sc raw PCM */ init_vgmstream_zwdsp, /* fake format */ init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */ diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index d79e73159..6e37e24eb 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -549,7 +549,6 @@ typedef enum { meta_GHS, meta_AAC_TRIACE, meta_MTA2, - meta_NGC_ULW, /* Burnout 1 (GC only) */ meta_XA_XA30, meta_XA_04SW, meta_TXTH, /* generic text header */ From 03d09e930843b63fd855259c46c84b7d6b908ddc Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 10 Jun 2023 16:40:05 +0200 Subject: [PATCH 026/141] build tweak --- make-build.sh | 53 ++++++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/make-build.sh b/make-build.sh index c201f4640..9f90abc85 100755 --- a/make-build.sh +++ b/make-build.sh @@ -28,54 +28,53 @@ sudo apt-get install -y libao-dev ############################################################################### # vorbis deps sudo apt-get install -y libvorbis-dev -FLAGS+=" VGM_VORBIS=1" +FLAGS="${FLAGS} VGM_VORBIS=1" ############################################################################### # mpeg deps sudo apt-get install -y libmpg123-dev -FLAGS+=" VGM_MPEG=1" +FLAGS="${FLAGS} VGM_MPEG=1" ############################################################################### # speex deps sudo apt-get install -y libspeex-dev -FLAGS+=" VGM_SPEEX=1" +FLAGS="${FLAGS} VGM_SPEEX=1" ############################################################################### # ffmpeg deps sudo apt-get install -y libavformat-dev libavcodec-dev libavutil-dev libswresample-dev -FLAGS+=" VGM_FFMPEG=1" +FLAGS="${FLAGS} VGM_FFMPEG=1" ############################################################################### # atrac9 deps (compile) -mkdir dependencies +mkdir -p dependencies cd dependencies + git clone https://github.com/Thealexbarney/LibAtrac9 cd LibAtrac9/C make cd ../../../ -FLAGS+=" VGM_ATRAC9=2" -#INCS+=" -I../dependencies/LibAtrac9/C/src" -LIBS+=" -L../dependencies/LibAtrac9/C/bin" +FLAGS="${FLAGS} VGM_ATRAC9=2" +#INCS="${INCS} -I../dependencies/LibAtrac9/C/src" +LIBS="${LIBS} -L../dependencies/LibAtrac9/C/bin" ############################################################################### # celt deps (compile x2) -mkdir dependencies -cd dependencies # used renames followed by unused renamed (but seems needed to avoid clashes) CELT0061_RENAMES=" \ - -Dcelt_decode=celt_0061_decode \ - -Dcelt_decoder_create=celt_0061_decoder_create \ - -Dcelt_decoder_destroy=celt_0061_decoder_destroy \ - -Dcelt_mode_create=celt_0061_mode_create \ - -Dcelt_mode_destroy=celt_0061_mode_destroy \ - -Dcelt_mode_info=celt_0061_mode_info \ + -Dcelt_decode=celt_decode_0061 \ + -Dcelt_decoder_create=celt_decoder_create_0061 \ + -Dcelt_decoder_destroy=celt_decoder_destroy_0061 \ + -Dcelt_mode_create=celt_mode_create_0061 \ + -Dcelt_mode_destroy=celt_mode_destroy_0061 \ + -Dcelt_mode_info=celt_mode_info_0061 \ \ -Dalg_quant=alg_quant_0061 \ -Dalg_unquant=alg_unquant_0061 \ @@ -113,12 +112,12 @@ CELT0061_RENAMES=" \ " # same as the above but I don't know sh enough to normalize CELT0110_RENAMES=" \ - -Dcelt_decode=celt_0110_decode \ - -Dcelt_decoder_create_custom=celt_0110_decoder_create_custom \ - -Dcelt_decoder_destroy=celt_0110_decoder_destroy \ - -Dcelt_mode_create=celt_0110_mode_create \ - -Dcelt_mode_destroy=celt_0110_mode_destroy \ - -Dcelt_mode_info=celt_0110_mode_info \ + -Dcelt_decode=celt_decode_0110 \ + -Dcelt_decoder_create_custom=celt_decoder_create_custom_0110 \ + -Dcelt_decoder_destroy=celt_decoder_destroy_0110 \ + -Dcelt_mode_create=celt_mode_create_0110 \ + -Dcelt_mode_destroy=celt_mode_destroy_0110 \ + -Dcelt_mode_info=celt_mode_info_0110 \ \ -Dalg_quant=alg_quant_0110 \ -Dalg_unquant=alg_unquant_0110 \ @@ -154,6 +153,8 @@ CELT0110_RENAMES=" \ -Dunquant_fine_energy=unquant_fine_energy_0110 \ " +mkdir -p dependencies +cd dependencies git clone --depth 1 --branch v0.6.1 https://gitlab.xiph.org/xiph/celt.git celt-0061 cd celt-0061 @@ -174,12 +175,12 @@ cd .. cd .. -FLAGS+="VGM_CELT=2" -#INCS+=" -I../dependencies/celt-0061/libcelt/.libs/" -LIBS+=" -L../dependencies/celt-0061/libcelt/.libs/ -L../dependencies/celt-0110/libcelt/.libs/" +FLAGS="${FLAGS} VGM_CELT=2" +#INCS="${INCS} -I../dependencies/celt-0061/libcelt/.libs/" +LIBS="${LIBS} -L../dependencies/celt-0061/libcelt/.libs/ -L../dependencies/celt-0110/libcelt/.libs/" ############################################################################### # vgmstream -make vgmstream_cli $FLAGS EXTRA_CFLAGS=$INCS EXTRA_LDFLAGS=$LIBS +make vgmstream-cli $FLAGS EXTRA_CFLAGS=$INCS EXTRA_LDFLAGS=$LIBS make vgmstream123 $FLAGS EXTRA_CFLAGS=$INCS EXTRA_LDFLAGS=$LIBS From 47feac9eb6218da7293d0b4c564c3e85ca56b1fa Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 11 Jun 2023 19:41:06 +0200 Subject: [PATCH 027/141] Add Codemasters .DIC [DiRT (PC), F1 2011 (PC)] --- src/formats.c | 2 + src/libvgmstream.vcxproj | 3 +- src/libvgmstream.vcxproj.filters | 9 +- src/meta/ego_dic.c | 156 +++++++++++++++++++++++++++++++ src/meta/meta.h | 2 + src/vgmstream.c | 1 + src/vgmstream_types.h | 1 + 7 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 src/meta/ego_dic.c diff --git a/src/formats.c b/src/formats.c index 7937bb32b..a51c3d85a 100644 --- a/src/formats.c +++ b/src/formats.c @@ -162,6 +162,7 @@ static const char* extension_list[] = { "ddsp", "de2", "dec", + "dic", "diva", "dmsg", //fake extension/header id for .sgt (to be removed) "ds2", //txth/reserved [Star Wars Bounty Hunter (GC)] @@ -1418,6 +1419,7 @@ static const meta_info meta_info_list[] = { {meta_SNDZ, "Sony SNDZ header"}, {meta_VAB, "Sony VAB header"}, {meta_BIGRP, "Inti Creates .BIGRP header"}, + {meta_DIC1, "Codemasters DIC1 header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 90ce90dad..a4f990cc4 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -411,6 +411,7 @@ + @@ -517,7 +518,6 @@ - @@ -593,7 +593,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index bbe5335ea..f80325d43 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1054,6 +1054,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1372,9 +1375,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1600,9 +1600,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/ego_dic.c b/src/meta/ego_dic.c new file mode 100644 index 000000000..ad79c5702 --- /dev/null +++ b/src/meta/ego_dic.c @@ -0,0 +1,156 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/reader_text.h" + + +/* DIC1 - from Codemaster's Ego engine 'dictionaries' [DiRT (PC), F1 2011 (PC), Race Driver Grid (PC)] */ +VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + uint32_t stream_offset = 0, stream_size = 0, codec = 0; + int channels = 0, loop_flag = 0, sample_rate = 0; + + + /* checks */ + if (!is_id32be(0x00, sf, "DIC1")) + return NULL; + if (!check_extensions(sf, "dic")) + return NULL; + + /* 0x04: hash/info? */ + /* 0x08: version ("0.46": DiRT, "2.00": DiRT 2+ (no diffs?) */ + int containers = read_s32le(0x0c,sf); + + int total_subsongs = 0; + int target_subsong = sf->stream_index; + if (target_subsong == 0) target_subsong = 1; + + char container_name[0x10+1]; + char track_name[0x10+1]; + char ext[0x04+1]; + { + /* N containers (external files) that may have N tracks, so we'll map all to subsongs */ + + bool track_found = false; + uint32_t offset = 0x10; + for (int i = 0; i < containers; i++) { + uint32_t header_offset = read_u32le(offset + 0x00,sf); + int tracks = read_s32le(offset + 0x04,sf); + + /* target in container */ + if (!track_found && target_subsong >= total_subsongs + 1 && target_subsong < total_subsongs + 1 + tracks) { + read_string(container_name, 0x10, offset + 0x08, sf); + + int track_pos = target_subsong - total_subsongs - 1; + uint32_t track_offset = header_offset + track_pos * 0x18; + uint32_t curr_offset, flags, next_offset; + + curr_offset = read_u32le(track_offset + 0x00, sf); + sample_rate = read_u16le(track_offset + 0x04, sf); + flags = read_u16le(track_offset + 0x06, sf); + read_string(track_name, 0x10, track_offset + 0x08, sf); + next_offset = read_u32le(track_offset + 0x18, sf); /* always exists as even after last track */ + + /* 8ch seen in Race Driver Grid music*.WIM, 2ch in other music tracks */ + channels = ((flags >> 5) & 0x7) + 1; + loop_flag = flags & (1<<4); + /* flag 0x8000: ? (common) */ + /* others: not seen */ + + stream_offset = curr_offset; + stream_size = next_offset - curr_offset; + + /* after all tracks comes container size + extension/codec */ + uint32_t ext_offset = header_offset + tracks * 0x18 + 0x04; + codec = read_u32be(ext_offset + 0x00, sf); + read_string(ext, 0x04, ext_offset + 0x00, sf); + + track_found = true; + } + + total_subsongs += tracks; + offset += 0x18; + } + + if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail; + if (!track_found) goto fail; + } + + { + char resource_name[255]; + snprintf(resource_name, sizeof(resource_name), "%s.%s", container_name, ext); + + sb = open_streamfile_by_filename(sf, resource_name); + if (sb == NULL) { + vgm_logi("DIC1: external file '%s' not found (put together)\n", resource_name); + goto fail; + } + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_DIC1; + vgmstream->sample_rate = sample_rate; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + + switch(codec) { + case 0x57495000: //WIP\0 + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x02; + + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + break; + + case 0x57494D00: //WIM\0 + vgmstream->coding_type = coding_ULAW; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x01; + + vgmstream->num_samples = pcm8_bytes_to_samples(stream_size, channels); + break; + + case 0x57494100: //WIA\0 + vgmstream->coding_type = coding_XBOX_IMA; + vgmstream->layout_type = layout_none; + + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channels); + stream_offset += 0x04; /* all streams start with 0xFFFFFFFF, may be some delimiter */ + break; + +#ifdef VGM_USE_VORBIS + case 0x57494F00: //WIO\0 + vgmstream->codec_data = init_ogg_vorbis(sb, stream_offset, stream_size, NULL); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_OGG_VORBIS; + vgmstream->layout_type = layout_none; + + ogg_vorbis_get_samples(vgmstream->codec_data, &vgmstream->num_samples); + break; +#endif + + default: + VGM_LOG("DIC1: unknown codec\n"); + goto fail; + } + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s.%s/%s", container_name, ext, track_name); + + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + if (!vgmstream_open_stream(vgmstream, sb, stream_offset)) + goto fail; + + close_streamfile(sb); + return vgmstream; + +fail: + close_vgmstream(vgmstream); + close_streamfile(sb); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index d48b30b05..cf20adec4 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -986,4 +986,6 @@ VGMSTREAM* init_vgmstream_bigrp(STREAMFILE* sf); VGMSTREAM* init_vgmstream_sscf_encrypted(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/vgmstream.c b/src/vgmstream.c index 2c8d79d7f..dbfbe0f05 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -527,6 +527,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_sscf_encrypted, init_vgmstream_s_p_sth, init_vgmstream_utf_ahx, + init_vgmstream_ego_dic, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 6e37e24eb..84cb27e29 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -710,6 +710,7 @@ typedef enum { meta_SNDZ, meta_VAB, meta_BIGRP, + meta_DIC1, } meta_t; From 0e453b26542776f237e1c977db793f5bd24b6d0d Mon Sep 17 00:00:00 2001 From: Adam Gashlin Date: Mon, 12 Jun 2023 00:18:18 -0700 Subject: [PATCH 028/141] Fallthrough in LZ4 state machine for a MSVC bug This works around an issue in "Microsoft (R) C/C++ Optimizing Compiler Version 19.36.32532 for x64" with /O2. It seems to have trouble tying together the states, this perhaps links the data and control flow more simply. --- src/meta/xnb_lz4mg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meta/xnb_lz4mg.h b/src/meta/xnb_lz4mg.h index dc61510d0..9a2e98aa5 100644 --- a/src/meta/xnb_lz4mg.h +++ b/src/meta/xnb_lz4mg.h @@ -154,7 +154,7 @@ static int lz4mg_decompress(lz4mg_stream_t* strm) { } while (next_len == LZ4MG_VARLEN_CONTINUE); ctx->state = SET_MATCH; - break; + // Falthrough for MSVC case SET_MATCH: ctx->match_len += LZ4MG_MIN_MATCH_LEN; @@ -164,7 +164,7 @@ static int lz4mg_decompress(lz4mg_stream_t* strm) { ctx->match_pos = LZ4MG_WINDOW_SIZE + ctx->match_pos; ctx->state = COPY_MATCH; - break; + // Fallthrough for MSVC case COPY_MATCH: while (ctx->match_len > 0) { From 16a791c41d7b43e31df9c51bc40098a944f18049 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Mon, 12 Jun 2023 21:15:16 +0300 Subject: [PATCH 029/141] AWD: RenderWare Audio Wave Dictionary --- src/formats.c | 4 + src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 6 ++ src/meta/awd.c | 143 +++++++++++++++++++++++++++++++ src/meta/meta.h | 2 + src/vgmstream.c | 1 + src/vgmstream_types.h | 1 + 7 files changed, 158 insertions(+) create mode 100644 src/meta/awd.c diff --git a/src/formats.c b/src/formats.c index a51c3d85a..ac8324dd7 100644 --- a/src/formats.c +++ b/src/formats.c @@ -89,6 +89,7 @@ static const char* extension_list[] = { "awa", //txth/reserved [Missing Parts Side A (PS2)] "awb", "awc", + "awd", "b1s", "baf", @@ -230,6 +231,7 @@ static const char* extension_list[] = { "hxg", "hxx", "hwas", + "hwd", "iab", "iadp", @@ -316,6 +318,7 @@ static const char* extension_list[] = { "lsf", "lstm", //fake extension for .stm "lwav", //fake extension for .wav + "lwd", "lwma", //fake extension for .wma, FFmpeg/not parsed "mab", @@ -1420,6 +1423,7 @@ static const meta_info meta_info_list[] = { {meta_VAB, "Sony VAB header"}, {meta_BIGRP, "Inti Creates .BIGRP header"}, {meta_DIC1, "Codemasters DIC1 header"}, + {meta_AWD, "RenderWare Audio Wave Dictionary header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index a4f990cc4..d4cadd407 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -358,6 +358,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f80325d43..8b565ebf0 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -910,6 +910,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -2068,5 +2071,8 @@ util\Source Files + + meta\Source Files + \ No newline at end of file diff --git a/src/meta/awd.c b/src/meta/awd.c new file mode 100644 index 000000000..d9c3871c5 --- /dev/null +++ b/src/meta/awd.c @@ -0,0 +1,143 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/endianness.h" + + +/* AWD - Audio Wave Dictionary (RenderWare) */ +VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; + int bit_depth = 0, channels = 0, sample_rate = 0, stream_codec = -1, total_subsongs = 0, target_subsong = sf->stream_index; + int interleave, loop_flag; + off_t data_offset, data_offset_2, header_name_offset, misc_data_offset, linked_list_offset, wavedict_offset; + off_t entry_info_offset, entry_name_offset, entry_uuid_offset, next_dict_entry, prev_dict_entry, stream_offset; + read_u32_t read_u32; + size_t misc_data_size, stream_size = 0; + + /* checks */ + if ((read_u32le(0x00, sf) != 0x809) && (read_u32be(0x00, sf) != 0x809)) + goto fail; + + /* .awd: standard (Black, Burnout series, Call of Duty: Finest Hour) + * .hwd/lwd: high/low vehicle engine sounds (Burnout series) */ + if (!check_extensions(sf, "awd,hwd,lwd")) + goto fail; + + read_u32 = guess_endian32(0x00, sf) ? read_u32be : read_u32le; + + data_offset = read_u32(0x08, sf); + wavedict_offset = read_u32(0x0C, sf); + /* Platform UUIDs in big endian + * {FD9D32D3-E179-426A-8424-14720AC7F648}: GameCube + * {ACC9EAAA-38FC-1749-AE81-64EADBC79353}: PlayStation 2 + * {042D3A45-5FE4-C84B-81F0-DF758B01F273}: Xbox */ + //platf_uuid_1 = read_u64be(0x18, sf); + //platf_uuid_2 = read_u64be(0x20, sf); + data_offset_2 = read_u32(0x28, sf); + + if (data_offset != data_offset_2) + goto fail; + + header_name_offset = wavedict_offset + 0x04; + linked_list_offset = wavedict_offset + 0x0C; + + if (header_name_offset) /* not used in Black */ + read_string(header_name, STREAM_NAME_SIZE, header_name_offset, sf); + + if (target_subsong == 0) + target_subsong = 1; + + /* Linked lists have no total subsong count; instead iterating + * through all of them, until it returns to the 1st song again */ + prev_dict_entry = read_u32(linked_list_offset + 0x00, sf); + next_dict_entry = read_u32(linked_list_offset + 0x04, sf); + + while (next_dict_entry != linked_list_offset) { + total_subsongs++; + + entry_info_offset = read_u32(next_dict_entry + 0x08, sf); + + prev_dict_entry = read_u32(next_dict_entry + 0x00, sf); + next_dict_entry = read_u32(next_dict_entry + 0x04, sf); + + /* is at the correct target song index */ + if (total_subsongs == target_subsong) { + entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ + entry_name_offset = read_u32(entry_info_offset + 0x04, sf); + + sample_rate = read_u32(entry_info_offset + 0x10, sf); + stream_codec = read_u32(entry_info_offset + 0x14, sf); + stream_size = read_u32(entry_info_offset + 0x18, sf); + bit_depth = read_8bit(entry_info_offset + 0x1C, sf); + channels = read_8bit(entry_info_offset + 0x1D, sf); /* always 1, haven't seen any stereo entries */ + if (channels != 1) + goto fail; + + /* stores a "00: GCN ADPCM Header" section, otherwise empty */ + misc_data_offset = read_u32(entry_info_offset + 0x20, sf); + misc_data_size = read_u32(entry_info_offset + 0x24, sf); + + stream_offset = read_u32(entry_info_offset + 0x4C, sf) + data_offset; + + read_string(stream_name, STREAM_NAME_SIZE, entry_name_offset, sf); + } + } + + if (total_subsongs < 1 || target_subsong > total_subsongs) + goto fail; + + interleave = 0; + loop_flag = 0; + + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) + goto fail; + + vgmstream->meta_type = meta_AWD; + vgmstream->layout_type = layout_none; + vgmstream->sample_rate = sample_rate; + vgmstream->stream_size = stream_size; + vgmstream->num_streams = total_subsongs; + vgmstream->interleave_block_size = interleave; + + if (header_name_offset) + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", header_name, stream_name); + else + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s", stream_name); + + switch (stream_codec) { + case 0x00: /* PS2 (All Games) */ + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_PSX; + break; + + case 0x01: /* Xbox (Black, Burnout) */ + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_PCM16LE; + break; + + case 0x03: /* GCN (Call of Duty: Finest Hour) */ + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channels); + dsp_read_coefs_be(vgmstream, sf, misc_data_offset + 0x1C, 0); + vgmstream->coding_type = coding_NGC_DSP; + break; + + case 0x04: /* Xbox (Black, Call of Duty: Finest Hour) */ + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_XBOX_IMA; + break; + + default: + VGM_LOG("AWD: unknown codec type %d\n", stream_codec); + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, sf, stream_offset)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index cf20adec4..7bee9ea97 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -21,6 +21,8 @@ VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_awd(STREAMFILE *sf); + VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index dbfbe0f05..495c4ba38 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -28,6 +28,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_nds_strm, init_vgmstream_afc, init_vgmstream_ast, + init_vgmstream_awd, init_vgmstream_halpst, init_vgmstream_rs03, init_vgmstream_ngc_dsp_std, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 84cb27e29..596daa1cd 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -711,6 +711,7 @@ typedef enum { meta_VAB, meta_BIGRP, meta_DIC1, + meta_AWD, } meta_t; From a04988589c14e5136324a8b1e81b5a99f6cbb762 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Mon, 12 Jun 2023 21:37:25 +0300 Subject: [PATCH 030/141] AWD: RenderWare Audio Wave Dictionary --- src/formats.c | 4 + src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 6 ++ src/meta/awd.c | 143 +++++++++++++++++++++++++++++++ src/meta/meta.h | 2 + src/vgmstream.c | 1 + src/vgmstream_types.h | 1 + 7 files changed, 158 insertions(+) create mode 100644 src/meta/awd.c diff --git a/src/formats.c b/src/formats.c index a51c3d85a..ac8324dd7 100644 --- a/src/formats.c +++ b/src/formats.c @@ -89,6 +89,7 @@ static const char* extension_list[] = { "awa", //txth/reserved [Missing Parts Side A (PS2)] "awb", "awc", + "awd", "b1s", "baf", @@ -230,6 +231,7 @@ static const char* extension_list[] = { "hxg", "hxx", "hwas", + "hwd", "iab", "iadp", @@ -316,6 +318,7 @@ static const char* extension_list[] = { "lsf", "lstm", //fake extension for .stm "lwav", //fake extension for .wav + "lwd", "lwma", //fake extension for .wma, FFmpeg/not parsed "mab", @@ -1420,6 +1423,7 @@ static const meta_info meta_info_list[] = { {meta_VAB, "Sony VAB header"}, {meta_BIGRP, "Inti Creates .BIGRP header"}, {meta_DIC1, "Codemasters DIC1 header"}, + {meta_AWD, "RenderWare Audio Wave Dictionary header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index a4f990cc4..d4cadd407 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -358,6 +358,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f80325d43..8b565ebf0 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -910,6 +910,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -2068,5 +2071,8 @@ util\Source Files + + meta\Source Files + \ No newline at end of file diff --git a/src/meta/awd.c b/src/meta/awd.c new file mode 100644 index 000000000..d9c3871c5 --- /dev/null +++ b/src/meta/awd.c @@ -0,0 +1,143 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/endianness.h" + + +/* AWD - Audio Wave Dictionary (RenderWare) */ +VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; + int bit_depth = 0, channels = 0, sample_rate = 0, stream_codec = -1, total_subsongs = 0, target_subsong = sf->stream_index; + int interleave, loop_flag; + off_t data_offset, data_offset_2, header_name_offset, misc_data_offset, linked_list_offset, wavedict_offset; + off_t entry_info_offset, entry_name_offset, entry_uuid_offset, next_dict_entry, prev_dict_entry, stream_offset; + read_u32_t read_u32; + size_t misc_data_size, stream_size = 0; + + /* checks */ + if ((read_u32le(0x00, sf) != 0x809) && (read_u32be(0x00, sf) != 0x809)) + goto fail; + + /* .awd: standard (Black, Burnout series, Call of Duty: Finest Hour) + * .hwd/lwd: high/low vehicle engine sounds (Burnout series) */ + if (!check_extensions(sf, "awd,hwd,lwd")) + goto fail; + + read_u32 = guess_endian32(0x00, sf) ? read_u32be : read_u32le; + + data_offset = read_u32(0x08, sf); + wavedict_offset = read_u32(0x0C, sf); + /* Platform UUIDs in big endian + * {FD9D32D3-E179-426A-8424-14720AC7F648}: GameCube + * {ACC9EAAA-38FC-1749-AE81-64EADBC79353}: PlayStation 2 + * {042D3A45-5FE4-C84B-81F0-DF758B01F273}: Xbox */ + //platf_uuid_1 = read_u64be(0x18, sf); + //platf_uuid_2 = read_u64be(0x20, sf); + data_offset_2 = read_u32(0x28, sf); + + if (data_offset != data_offset_2) + goto fail; + + header_name_offset = wavedict_offset + 0x04; + linked_list_offset = wavedict_offset + 0x0C; + + if (header_name_offset) /* not used in Black */ + read_string(header_name, STREAM_NAME_SIZE, header_name_offset, sf); + + if (target_subsong == 0) + target_subsong = 1; + + /* Linked lists have no total subsong count; instead iterating + * through all of them, until it returns to the 1st song again */ + prev_dict_entry = read_u32(linked_list_offset + 0x00, sf); + next_dict_entry = read_u32(linked_list_offset + 0x04, sf); + + while (next_dict_entry != linked_list_offset) { + total_subsongs++; + + entry_info_offset = read_u32(next_dict_entry + 0x08, sf); + + prev_dict_entry = read_u32(next_dict_entry + 0x00, sf); + next_dict_entry = read_u32(next_dict_entry + 0x04, sf); + + /* is at the correct target song index */ + if (total_subsongs == target_subsong) { + entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ + entry_name_offset = read_u32(entry_info_offset + 0x04, sf); + + sample_rate = read_u32(entry_info_offset + 0x10, sf); + stream_codec = read_u32(entry_info_offset + 0x14, sf); + stream_size = read_u32(entry_info_offset + 0x18, sf); + bit_depth = read_8bit(entry_info_offset + 0x1C, sf); + channels = read_8bit(entry_info_offset + 0x1D, sf); /* always 1, haven't seen any stereo entries */ + if (channels != 1) + goto fail; + + /* stores a "00: GCN ADPCM Header" section, otherwise empty */ + misc_data_offset = read_u32(entry_info_offset + 0x20, sf); + misc_data_size = read_u32(entry_info_offset + 0x24, sf); + + stream_offset = read_u32(entry_info_offset + 0x4C, sf) + data_offset; + + read_string(stream_name, STREAM_NAME_SIZE, entry_name_offset, sf); + } + } + + if (total_subsongs < 1 || target_subsong > total_subsongs) + goto fail; + + interleave = 0; + loop_flag = 0; + + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) + goto fail; + + vgmstream->meta_type = meta_AWD; + vgmstream->layout_type = layout_none; + vgmstream->sample_rate = sample_rate; + vgmstream->stream_size = stream_size; + vgmstream->num_streams = total_subsongs; + vgmstream->interleave_block_size = interleave; + + if (header_name_offset) + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", header_name, stream_name); + else + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s", stream_name); + + switch (stream_codec) { + case 0x00: /* PS2 (All Games) */ + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_PSX; + break; + + case 0x01: /* Xbox (Black, Burnout) */ + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_PCM16LE; + break; + + case 0x03: /* GCN (Call of Duty: Finest Hour) */ + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channels); + dsp_read_coefs_be(vgmstream, sf, misc_data_offset + 0x1C, 0); + vgmstream->coding_type = coding_NGC_DSP; + break; + + case 0x04: /* Xbox (Black, Call of Duty: Finest Hour) */ + vgmstream->num_samples = xbox_ima_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_XBOX_IMA; + break; + + default: + VGM_LOG("AWD: unknown codec type %d\n", stream_codec); + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, sf, stream_offset)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/meta.h b/src/meta/meta.h index cf20adec4..7bee9ea97 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -21,6 +21,8 @@ VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_awd(STREAMFILE *sf); + VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index dbfbe0f05..495c4ba38 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -28,6 +28,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_nds_strm, init_vgmstream_afc, init_vgmstream_ast, + init_vgmstream_awd, init_vgmstream_halpst, init_vgmstream_rs03, init_vgmstream_ngc_dsp_std, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 84cb27e29..596daa1cd 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -711,6 +711,7 @@ typedef enum { meta_VAB, meta_BIGRP, meta_DIC1, + meta_AWD, } meta_t; From 254c9f6eb1888928d5ebfeb5f57be316ad6bd45e Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Mon, 12 Jun 2023 22:54:39 +0300 Subject: [PATCH 031/141] Fix filename paths + Burnout's H/L vehicle sounds for other platforms --- src/formats.c | 3 +++ src/meta/awd.c | 22 ++++++++++++++-------- src/meta/ea_schl.c | 5 +++-- src/meta/xwb.c | 5 +++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/formats.c b/src/formats.c index ac8324dd7..2ed761138 100644 --- a/src/formats.c +++ b/src/formats.c @@ -218,6 +218,7 @@ static const char* extension_list[] = { "hab", "hca", "hdr", + "hdt", "hgc1", "his", "hps", @@ -231,6 +232,7 @@ static const char* extension_list[] = { "hxg", "hxx", "hwas", + "hwb", "hwd", "iab", @@ -291,6 +293,7 @@ static const char* extension_list[] = { "lasf", //fake extension for .asf (various) "lbin", //fake extension for .bin (various) "ldat", //fake extension for .dat + "ldt", "leg", "lep", "lflac", //fake extension for .flac, FFmpeg/not parsed diff --git a/src/meta/awd.c b/src/meta/awd.c index d9c3871c5..94b91404b 100644 --- a/src/meta/awd.c +++ b/src/meta/awd.c @@ -19,7 +19,8 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { goto fail; /* .awd: standard (Black, Burnout series, Call of Duty: Finest Hour) - * .hwd/lwd: high/low vehicle engine sounds (Burnout series) */ + * .hwd/lwd: high/low vehicle engine sounds (Burnout series) + * (Burnout 3: Takedown, Burnout Revenge, Burnout Dominator) */ if (!check_extensions(sf, "awd,hwd,lwd")) goto fail; @@ -38,17 +39,18 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { if (data_offset != data_offset_2) goto fail; - header_name_offset = wavedict_offset + 0x04; - linked_list_offset = wavedict_offset + 0x0C; + header_name_offset = read_u32(wavedict_offset + 0x04, sf); if (header_name_offset) /* not used in Black */ read_string(header_name, STREAM_NAME_SIZE, header_name_offset, sf); - if (target_subsong == 0) + if (!target_subsong) target_subsong = 1; /* Linked lists have no total subsong count; instead iterating * through all of them, until it returns to the 1st song again */ + linked_list_offset = wavedict_offset + 0x0C; + prev_dict_entry = read_u32(linked_list_offset + 0x00, sf); next_dict_entry = read_u32(linked_list_offset + 0x04, sf); @@ -69,14 +71,18 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { stream_codec = read_u32(entry_info_offset + 0x14, sf); stream_size = read_u32(entry_info_offset + 0x18, sf); bit_depth = read_8bit(entry_info_offset + 0x1C, sf); - channels = read_8bit(entry_info_offset + 0x1D, sf); /* always 1, haven't seen any stereo entries */ + channels = read_8bit(entry_info_offset + 0x1D, sf); /* always 1, don't think stereo entries exist */ if (channels != 1) goto fail; - /* stores a "00: GCN ADPCM Header" section, otherwise empty */ + /* stores a "00: GCN ADPCM Header" chunk, otherwise empty */ misc_data_offset = read_u32(entry_info_offset + 0x20, sf); misc_data_size = read_u32(entry_info_offset + 0x24, sf); + /* entry_info_offset + 0x2C to +0x44 has the target format information, + * which in most cases would probably be identical to the input format + * variables (from sample_rate to misc_data_size) */ + stream_offset = read_u32(entry_info_offset + 0x4C, sf) + data_offset; read_string(stream_name, STREAM_NAME_SIZE, entry_name_offset, sf); @@ -106,12 +112,12 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s", stream_name); switch (stream_codec) { - case 0x00: /* PS2 (All Games) */ + case 0x00: /* PS2 (Black, Burnout series, Call of Duty: Finest Hour) */ vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); vgmstream->coding_type = coding_PSX; break; - case 0x01: /* Xbox (Black, Burnout) */ + case 0x01: /* Xbox (Black, Burnout series) */ vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); vgmstream->coding_type = coding_PCM16LE; break; diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index eddd9abbf..a64f15fd1 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -294,10 +294,11 @@ VGMSTREAM* init_vgmstream_ea_bnk(STREAMFILE* sf) { /* check extension */ /* .bnk: common - * .sdt: Harry Potter games + * .sdt: Harry Potter games, Burnout games (PSP) + * .hdt/ldt: Burnout games (PSP) * .abk: GoldenEye - Rogue Agent * .ast: FIFA 2004 (inside .big) */ - if (!check_extensions(sf,"bnk,sdt,abk,ast")) + if (!check_extensions(sf,"bnk,sdt,hdt,ldt,abk,ast")) goto fail; if (target_stream == 0) target_stream = 1; diff --git a/src/meta/xwb.c b/src/meta/xwb.c index 307719daf..9bd6da6cc 100644 --- a/src/meta/xwb.c +++ b/src/meta/xwb.c @@ -95,9 +95,10 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) { /* .xwb: standard * .xna: Touhou Makukasai ~ Fantasy Danmaku Festival (PC) - * (extensionless): Ikaruga (X360/PC), Grabbed by the Ghoulies (Xbox) + * (extensionless): Ikaruga (X360/PC), Grabbed by the Ghoulies (Xbox) + * .hwb: Burnout Revenge (X360) * .bd: Fatal Frame 2 (Xbox) */ - if (!check_extensions(sf,"xwb,xna,bd,")) + if (!check_extensions(sf,"xwb,xna,hwb,bd,")) goto fail; xwb.little_endian = is_id32be(0x00,sf, "WBND"); /* Xbox/PC */ From 2198224c4f0071081d0b8f2dce0ff9fd397cb89c Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Tue, 13 Jun 2023 10:15:46 +0300 Subject: [PATCH 032/141] Small fixes + FORMATS.md --- doc/FORMATS.md | 1 + src/libvgmstream.vcxproj.filters | 5 +---- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 438327d00..0ce1f25cc 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -156,6 +156,7 @@ This list is not complete and many other files are supported. - .ast (GC AFC ADPCM, 16 bit PCM) - .aud (IMA ADPCM, WS DPCM) - .aus (PSX ADPCM, Xbox IMA ADPCM) + - .awd/.hwd/.lwd (PSX ADPCM, XBOX IMA ADPCM, GC DSP ADPCM, 16 bit PCM) - .brstm (GC DSP ADPCM, 8/16 bit PCM) - .emff (PSX APDCM, GC DSP ADPCM) - .fsb/wii (PSX ADPCM, GC DSP ADPCM, Xbox IMA ADPCM, MPEG audio, FSB Vorbis, MS XMA) diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 8b565ebf0..01de1365e 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -2071,8 +2071,5 @@ util\Source Files - - meta\Source Files - - \ No newline at end of file + From 74df0254b15146d45b67aa242d7a96482cef082a Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Tue, 13 Jun 2023 23:38:52 +0300 Subject: [PATCH 033/141] Some safety checks in the linked list loop --- src/libvgmstream.vcxproj | 2 +- src/meta/awd.c | 29 +++++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index d4cadd407..d08efabe8 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -358,12 +358,12 @@ - + diff --git a/src/meta/awd.c b/src/meta/awd.c index 94b91404b..88aaf2a78 100644 --- a/src/meta/awd.c +++ b/src/meta/awd.c @@ -9,10 +9,10 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; int bit_depth = 0, channels = 0, sample_rate = 0, stream_codec = -1, total_subsongs = 0, target_subsong = sf->stream_index; int interleave, loop_flag; - off_t data_offset, data_offset_2, header_name_offset, misc_data_offset, linked_list_offset, wavedict_offset; - off_t entry_info_offset, entry_name_offset, entry_uuid_offset, next_dict_entry, prev_dict_entry, stream_offset; + off_t data_offset, header_name_offset, misc_data_offset, linked_list_offset, wavedict_offset; + off_t entry_info_offset, entry_name_offset, entry_uuid_offset, next_entry_offset, prev_entry_offset, stream_offset; read_u32_t read_u32; - size_t misc_data_size, stream_size = 0; + size_t data_size, header_size, misc_data_size, stream_size = 0; /* checks */ if ((read_u32le(0x00, sf) != 0x809) && (read_u32be(0x00, sf) != 0x809)) @@ -28,15 +28,16 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { data_offset = read_u32(0x08, sf); wavedict_offset = read_u32(0x0C, sf); + data_size = read_u32(0x14, sf); /* Platform UUIDs in big endian * {FD9D32D3-E179-426A-8424-14720AC7F648}: GameCube * {ACC9EAAA-38FC-1749-AE81-64EADBC79353}: PlayStation 2 * {042D3A45-5FE4-C84B-81F0-DF758B01F273}: Xbox */ //platf_uuid_1 = read_u64be(0x18, sf); //platf_uuid_2 = read_u64be(0x20, sf); - data_offset_2 = read_u32(0x28, sf); + header_size = read_u32(0x28, sf); - if (data_offset != data_offset_2) + if (data_offset != header_size) goto fail; header_name_offset = read_u32(wavedict_offset + 0x04, sf); @@ -48,19 +49,22 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { target_subsong = 1; /* Linked lists have no total subsong count; instead iterating - * through all of them, until it returns to the 1st song again */ + * through all of them until it returns to the 1st entry again */ linked_list_offset = wavedict_offset + 0x0C; - prev_dict_entry = read_u32(linked_list_offset + 0x00, sf); - next_dict_entry = read_u32(linked_list_offset + 0x04, sf); + prev_entry_offset = read_u32(linked_list_offset + 0x00, sf); + next_entry_offset = read_u32(linked_list_offset + 0x04, sf); - while (next_dict_entry != linked_list_offset) { + while (next_entry_offset != linked_list_offset) { total_subsongs++; - entry_info_offset = read_u32(next_dict_entry + 0x08, sf); + if (total_subsongs > 1024 || prev_entry_offset > header_size || next_entry_offset > header_size) + goto fail; + + entry_info_offset = read_u32(next_entry_offset + 0x08, sf); - prev_dict_entry = read_u32(next_dict_entry + 0x00, sf); - next_dict_entry = read_u32(next_dict_entry + 0x04, sf); + prev_entry_offset = read_u32(next_entry_offset + 0x00, sf); + next_entry_offset = read_u32(next_entry_offset + 0x04, sf); /* is at the correct target song index */ if (total_subsongs == target_subsong) { @@ -95,6 +99,7 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { interleave = 0; loop_flag = 0; + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; From 66f10a811fdad23fe858e302d07e015997cf13b3 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Fri, 16 Jun 2023 21:29:35 +0300 Subject: [PATCH 034/141] AWD: read DSP hist + stricter linked list pointer boundary checks --- src/meta/awd.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/meta/awd.c b/src/meta/awd.c index 88aaf2a78..23593fbe3 100644 --- a/src/meta/awd.c +++ b/src/meta/awd.c @@ -15,16 +15,17 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { size_t data_size, header_size, misc_data_size, stream_size = 0; /* checks */ - if ((read_u32le(0x00, sf) != 0x809) && (read_u32be(0x00, sf) != 0x809)) + if (read_u32le(0x00, sf) != 0x809 && read_u32be(0x00, sf) != 0x809) goto fail; - /* .awd: standard (Black, Burnout series, Call of Duty: Finest Hour) - * .hwd/lwd: high/low vehicle engine sounds (Burnout series) + /* .awd: standard (Burnout series, Black, Call of Duty: Finest Hour) + * .hwd/lwd: high/low vehicle engine sounds (Burnout series) * (Burnout 3: Takedown, Burnout Revenge, Burnout Dominator) */ if (!check_extensions(sf, "awd,hwd,lwd")) goto fail; - read_u32 = guess_endian32(0x00, sf) ? read_u32be : read_u32le; + read_u32 = read_u8(0x04, sf) ? read_u32be : read_u32le; + //read_u32 = guess_endian32(0x00, sf) ? read_u32be : read_u32le; data_offset = read_u32(0x08, sf); wavedict_offset = read_u32(0x0C, sf); @@ -44,10 +45,10 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { if (header_name_offset) /* not used in Black */ read_string(header_name, STREAM_NAME_SIZE, header_name_offset, sf); - + if (!target_subsong) target_subsong = 1; - + /* Linked lists have no total subsong count; instead iterating * through all of them until it returns to the 1st entry again */ linked_list_offset = wavedict_offset + 0x0C; @@ -58,11 +59,14 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { while (next_entry_offset != linked_list_offset) { total_subsongs++; - if (total_subsongs > 1024 || prev_entry_offset > header_size || next_entry_offset > header_size) - goto fail; - entry_info_offset = read_u32(next_entry_offset + 0x08, sf); + if (total_subsongs > 1024 || /* in case it gets stuck in an infinite loop */ + entry_info_offset < wavedict_offset || entry_info_offset > header_size || + prev_entry_offset < wavedict_offset || prev_entry_offset > header_size || + next_entry_offset < wavedict_offset || next_entry_offset > header_size) + goto fail; + prev_entry_offset = read_u32(next_entry_offset + 0x00, sf); next_entry_offset = read_u32(next_entry_offset + 0x04, sf); @@ -74,8 +78,8 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { sample_rate = read_u32(entry_info_offset + 0x10, sf); stream_codec = read_u32(entry_info_offset + 0x14, sf); stream_size = read_u32(entry_info_offset + 0x18, sf); - bit_depth = read_8bit(entry_info_offset + 0x1C, sf); - channels = read_8bit(entry_info_offset + 0x1D, sf); /* always 1, don't think stereo entries exist */ + bit_depth = read_u8(entry_info_offset + 0x1C, sf); + channels = read_u8(entry_info_offset + 0x1D, sf); /* always 1, don't think stereo entries exist */ if (channels != 1) goto fail; @@ -117,12 +121,12 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s", stream_name); switch (stream_codec) { - case 0x00: /* PS2 (Black, Burnout series, Call of Duty: Finest Hour) */ + case 0x00: /* PS2 (Burnout series, Black, Call of Duty: Finest Hour) */ vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); vgmstream->coding_type = coding_PSX; break; - case 0x01: /* Xbox (Black, Burnout series) */ + case 0x01: /* Xbox (Burnout series, Black) */ vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); vgmstream->coding_type = coding_PCM16LE; break; @@ -130,6 +134,7 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { case 0x03: /* GCN (Call of Duty: Finest Hour) */ vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channels); dsp_read_coefs_be(vgmstream, sf, misc_data_offset + 0x1C, 0); + dsp_read_hist_be(vgmstream, sf, misc_data_offset + 0x40, 0); vgmstream->coding_type = coding_NGC_DSP; break; From 909a3e32ef34f8a7d9e5d02b8cf496413b06b5fd Mon Sep 17 00:00:00 2001 From: Matti Niemenmaa Date: Thu, 22 Jun 2023 13:08:15 +0300 Subject: [PATCH 035/141] cmake: Fix celt cache variables The FetchDependency calls in cmake/dependencies/celt.cmake use the names CELT_0061 and CELT_0110. The underscores after CELT are needed here to match, otherwise it's not possible to override the paths and the CELT0* variables end up being unused. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9b60f21cd..f34fe1278 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,8 +75,8 @@ if(NOT WIN32) set(G719_PATH CACHE PATH "Path to G.719 decoder") set(ATRAC9_PATH CACHE PATH "Path to LibAtrac9") set(SPEEX_PATH CACHE PATH "Path to SPEEX") - set(CELT0061_PATH CACHE PATH "Path to CELT version 0.6.1") - set(CELT0110_PATH CACHE PATH "Path to CELT version 0.11.0") + set(CELT_0061_PATH CACHE PATH "Path to CELT version 0.6.1") + set(CELT_0110_PATH CACHE PATH "Path to CELT version 0.11.0") set(LIBAO_PATH CACHE PATH "Path to libao") set(JANSSON_PATH CACHE PATH "Path to jansson") endif() From 3123541c7f75875fcf444ea997a3de0f58024616 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 14:53:16 +0200 Subject: [PATCH 036/141] Workaround for Mac fread issue in rare cases --- src/streamfile.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/streamfile.c b/src/streamfile.c index 77ec2bf88..ef1c5e707 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -10,6 +10,17 @@ #include #endif +/* Enables a minor optimization when reopening file descriptors. + * Some systems/compilers have issues though, and dupe'd FILEs may fread garbage data in rare cases, + * possibly due to underlying buffers that get shared/thrashed by dup(). Seen for example in some .HPS and Ubi + * bigfiles (some later MSVC versions) or PS2 .RSD (Mac), where 2nd channel = 2nd SF reads garbage at some points. + * + * Keep it for other systems since this is (probably) kinda useful, though a more sensible approach would be + * redoing SF/FILE/buffer handling to avoid re-opening as much. */ +#if !defined (_MSC_VER) && !defined (__ANDROID__) && !defined (__APPLE__) + #define USE_STDIO_FDUP 1 +#endif + /* For (rarely needed) +2GB file support we use fseek64/ftell64. Those are usually available * but may depend on compiler. * - MSVC: +VS2008 should work @@ -138,13 +149,9 @@ static size_t stdio_read(STDIO_STREAMFILE* sf, uint8_t* dst, offv_t offset, size break; /* this shouldn't happen in our code */ } -#ifdef _MSC_VER - /* Workaround a bug that appears when compiling with MSVC (later versions). - * This bug is deterministic and seemingly appears randomly after seeking. - * It results in fread returning data from the wrong area of the file. - * HPS is one format that is almost always affected by this. - * May be related/same as stdio_open's fixed bug when using dup(), try disabling */ - fseek_v(sf->infile, ftell_v(sf->infile), SEEK_SET); +#if 0 + /* old workaround for USE_STDIO_FDUP bug, keep it here for a while as a reminder just in case */ + //fseek_v(sf->infile, ftell_v(sf->infile), SEEK_SET); #endif /* fill the buffer (offset now is beyond buf_offset) */ @@ -199,11 +206,8 @@ static STREAMFILE* stdio_open(STDIO_STREAMFILE* sf, const char* const filename, if (!filename) return NULL; -#if !defined (__ANDROID__) && !defined (_MSC_VER) - /* when enabling this for MSVC it'll seemingly work, but there are issues possibly related to underlying - * IO buffers when using dup(), noticeable by re-opening the same streamfile with small buffer sizes - * (reads garbage). fseek bug in line 81 may be related/same thing and may be removed. - * this reportedly this causes issues in Android too */ +#ifdef USE_STDIO_FDUP + /* minor optimization when reopening files, see comment in #define above */ /* if same name, duplicate the file descriptor we already have open */ if (sf->infile && !strcmp(sf->name,filename)) { From e9df576d5173bd9d0fd38d7331047e72d817343f Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 14:54:08 +0200 Subject: [PATCH 037/141] Allow missing files for .dic [DiRT (PC)] --- src/meta/ego_dic.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/meta/ego_dic.c b/src/meta/ego_dic.c index ad79c5702..deabfcb9d 100644 --- a/src/meta/ego_dic.c +++ b/src/meta/ego_dic.c @@ -83,7 +83,8 @@ VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf) { sb = open_streamfile_by_filename(sf, resource_name); if (sb == NULL) { vgm_logi("DIC1: external file '%s' not found (put together)\n", resource_name); - goto fail; + /* allow missing as silence since some game use huge .dic that is a bit hard to get */ + //goto fail; } } @@ -138,10 +139,14 @@ VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf) { VGM_LOG("DIC1: unknown codec\n"); goto fail; } - snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s.%s/%s", container_name, ext, track_name); + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s.%s%s/%s", container_name, ext, sb ? "" : "[MISSING]", track_name); vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = vgmstream->num_samples; + if (!sb) { + vgmstream->coding_type = coding_SILENCE; + vgmstream->layout_type = layout_none; + } if (!vgmstream_open_stream(vgmstream, sb, stream_offset)) goto fail; From 46efa7c0445f981d72ee2f9ee6c3fef5b80801de Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 14:55:25 +0200 Subject: [PATCH 038/141] doc --- src/meta/bnk_sony.c | 1 + src/meta/ogg_vorbis.c | 2 +- src/meta/ogv_3rdeye.c | 2 +- src/meta/riff.c | 6 +++--- src/meta/xnb_lz4mg.h | 6 ++++-- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 4f83ddb9c..052a54f51 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -146,6 +146,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { break; case 0x1a: /* Demon's Souls (PS5) */ + case 0x23: /* The Last of Us (PC) */ default: vgm_logi("BNK: unknown version %x (report)\n", sblk_version); diff --git a/src/meta/ogg_vorbis.c b/src/meta/ogg_vorbis.c index 4141b5332..d9e242895 100644 --- a/src/meta/ogg_vorbis.c +++ b/src/meta/ogg_vorbis.c @@ -479,7 +479,7 @@ static int _init_vgmstream_ogg_vorbis_tests(STREAMFILE* sf, ogg_vorbis_io_config } } - /* "Ultramarine3" (???) */ + /* .um3: Ultramarine / Bruns Engine files */ if (check_extensions(sf,"um3")) { if (!is_id32be(0x00,sf, "OggS")) { ovmi->decryption_callback = um3_ogg_decryption_callback; diff --git a/src/meta/ogv_3rdeye.c b/src/meta/ogv_3rdeye.c index 20f3be375..579124688 100644 --- a/src/meta/ogv_3rdeye.c +++ b/src/meta/ogv_3rdeye.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -/* OGV - .ogg container (not related to ogv video) [Bloody Rondo (PC)] */ +/* OGV - .ogg container (not related to ogv video) [Bloody Rondo (PC), Shinigami no Testament (PC)] */ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf) { uint32_t subfile_offset, subfile_size; diff --git a/src/meta/riff.c b/src/meta/riff.c index 8f7ffe813..2e5a73fde 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -191,11 +191,11 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk break; #ifdef VGM_USE_MPEG - case 0x0055: /* MP3 [Bear in the Big Blue House: Bear's Imagine That! (PC)] (official) */ + case 0x0055: /* MP3 [Bear in the Big Blue House: Bear's Imagine That! (PC), Eclipse (PC)] (official) */ fmt->coding_type = coding_MPEG_custom; - /* some oddities, unsure if part of standard: + /* some oddities, unsure if part of standard: * - block size is 1 (in mono) - * - bps is 16 + * - bps is 16 for some games * - extra size 0x0c, has channels? and (possibly) approx frame size */ break; #endif diff --git a/src/meta/xnb_lz4mg.h b/src/meta/xnb_lz4mg.h index 9a2e98aa5..e6833472a 100644 --- a/src/meta/xnb_lz4mg.h +++ b/src/meta/xnb_lz4mg.h @@ -79,6 +79,8 @@ static int lz4mg_decompress(lz4mg_stream_t* strm) { int src_pos = 0; uint8_t next_len, next_val; + /* MSVC 64 19.30+ has a /O2 bug where some states aren't handled properly unless a fallthrough is used. + * Seems related to src_pos and doesn't seem fixed by using sub-functions or avoiding gotos. */ while (1) { /* mostly linear state machine, but it may break anytime when reaching dst or src @@ -154,7 +156,7 @@ static int lz4mg_decompress(lz4mg_stream_t* strm) { } while (next_len == LZ4MG_VARLEN_CONTINUE); ctx->state = SET_MATCH; - // Falthrough for MSVC + //break; // Falthrough for MSVC case SET_MATCH: ctx->match_len += LZ4MG_MIN_MATCH_LEN; @@ -164,7 +166,7 @@ static int lz4mg_decompress(lz4mg_stream_t* strm) { ctx->match_pos = LZ4MG_WINDOW_SIZE + ctx->match_pos; ctx->state = COPY_MATCH; - // Fallthrough for MSVC + //break; // Fallthrough for MSVC case COPY_MATCH: while (ctx->match_len > 0) { From 4da2c9ef380e001239d160dd52fa9c9307c0338f Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 14:55:43 +0200 Subject: [PATCH 039/141] vspf: ignore "hidden" files --- vspf.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vspf.py b/vspf.py index c48e338ee..407d24b04 100644 --- a/vspf.py +++ b/vspf.py @@ -55,6 +55,10 @@ def get_files(self, ext): if '\\' in basefile: pos = basefile.rindex('\\') path = basefile[0 : pos + 1] + basename = os.path.basename(basefile) + if basename.startswith('.'): #hidden .c + continue + items.append( (basefile, path) ) return items From 7b9f1609ba4a3397788434ebaa30a5a1333cd799 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:06:01 +0200 Subject: [PATCH 040/141] awd: warning cleanup, tweak priority --- src/meta/awd.c | 14 +++++++------- src/vgmstream.c | 5 ++++- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/meta/awd.c b/src/meta/awd.c index 23593fbe3..f20f75e6d 100644 --- a/src/meta/awd.c +++ b/src/meta/awd.c @@ -7,12 +7,12 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; - int bit_depth = 0, channels = 0, sample_rate = 0, stream_codec = -1, total_subsongs = 0, target_subsong = sf->stream_index; + int /*bit_depth = 0,*/ channels = 0, sample_rate = 0, stream_codec = -1, total_subsongs = 0, target_subsong = sf->stream_index; int interleave, loop_flag; off_t data_offset, header_name_offset, misc_data_offset, linked_list_offset, wavedict_offset; - off_t entry_info_offset, entry_name_offset, entry_uuid_offset, next_entry_offset, prev_entry_offset, stream_offset; + off_t entry_info_offset, entry_name_offset, /*entry_uuid_offset,*/ next_entry_offset, prev_entry_offset, stream_offset = 0; read_u32_t read_u32; - size_t data_size, header_size, misc_data_size, stream_size = 0; + size_t /*data_size,*/ header_size, /*misc_data_size,*/ stream_size = 0; /* checks */ if (read_u32le(0x00, sf) != 0x809 && read_u32be(0x00, sf) != 0x809) @@ -29,7 +29,7 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { data_offset = read_u32(0x08, sf); wavedict_offset = read_u32(0x0C, sf); - data_size = read_u32(0x14, sf); + //data_size = read_u32(0x14, sf); /* Platform UUIDs in big endian * {FD9D32D3-E179-426A-8424-14720AC7F648}: GameCube * {ACC9EAAA-38FC-1749-AE81-64EADBC79353}: PlayStation 2 @@ -72,20 +72,20 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { /* is at the correct target song index */ if (total_subsongs == target_subsong) { - entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ + //entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ entry_name_offset = read_u32(entry_info_offset + 0x04, sf); sample_rate = read_u32(entry_info_offset + 0x10, sf); stream_codec = read_u32(entry_info_offset + 0x14, sf); stream_size = read_u32(entry_info_offset + 0x18, sf); - bit_depth = read_u8(entry_info_offset + 0x1C, sf); + //bit_depth = read_u8(entry_info_offset + 0x1C, sf); channels = read_u8(entry_info_offset + 0x1D, sf); /* always 1, don't think stereo entries exist */ if (channels != 1) goto fail; /* stores a "00: GCN ADPCM Header" chunk, otherwise empty */ misc_data_offset = read_u32(entry_info_offset + 0x20, sf); - misc_data_size = read_u32(entry_info_offset + 0x24, sf); + //misc_data_size = read_u32(entry_info_offset + 0x24, sf); /* entry_info_offset + 0x2C to +0x44 has the target format information, * which in most cases would probably be identical to the input format diff --git a/src/vgmstream.c b/src/vgmstream.c index 495c4ba38..d8e1ec6a5 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -28,7 +28,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_nds_strm, init_vgmstream_afc, init_vgmstream_ast, - init_vgmstream_awd, init_vgmstream_halpst, init_vgmstream_rs03, init_vgmstream_ngc_dsp_std, @@ -529,6 +528,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_s_p_sth, init_vgmstream_utf_ahx, init_vgmstream_ego_dic, + init_vgmstream_awd, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, @@ -1124,6 +1124,9 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o goto fail; } + /* no need to open anything */ + if (vgmstream->coding_type == coding_SILENCE) + return 1; /* stream/offsets not needed, managed by layout */ if (vgmstream->layout_type == layout_segmented || From 8ffae9f070a40a42d6c1168a76a45e6fd256f500 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:24:01 +0200 Subject: [PATCH 041/141] vag: extra validations and remove Jak 3 hack --- src/meta/vag.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/meta/vag.c b/src/meta/vag.c index aed923c02..a00daeacc 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -5,8 +5,7 @@ /* VAGp - Sony SDK format, created by various official tools */ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - off_t start_offset; - size_t file_size, channel_size, interleave, interleave_first = 0, interleave_first_skip = 0; + uint32_t start_offset, file_size, channel_size, interleave, interleave_first = 0, interleave_first_skip = 0; meta_t meta_type; int channels = 0, loop_flag, sample_rate; uint32_t vag_id, version, reserved; @@ -17,7 +16,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { /* checks */ if (((read_u32be(0x00,sf) & 0xFFFFFF00) != get_id32be("VAG\0")) && ((read_u32le(0x00,sf) & 0xFFFFFF00) != get_id32be("VAG\0"))) - goto fail; + return NULL; /* .vag: standard * .swag: Frantix (PSP) @@ -28,7 +27,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { * .xa2: Shikigami no Shiro (PS2) * .snd: Alien Breed (Vita) */ if (!check_extensions(sf,"vag,swag,str,vig,l,r,vas,xa2,snd")) - goto fail; + return NULL; file_size = get_streamfile_size(sf); @@ -94,7 +93,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { else if (is_id32be(0x1000,sf, "pGAV")) interleave = 0x1000; /* Jak X interleave, includes header */ else - interleave = 0x2000; /* Jak 3 interleave in rare files, no header */ + goto fail; interleave_first = interleave - start_offset; /* interleave includes header */ interleave_first_skip = start_offset; } @@ -289,6 +288,14 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { goto fail; } + /* ignore bigfiles and bad extractions (approximate) */ + if (channel_size * channels + interleave * channels + start_offset * channels + 0x8000 < get_streamfile_size(sf) || + channel_size * channels > get_streamfile_size(sf)) { + vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n", + channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf)); + goto fail; + } + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels, loop_flag); From bb9b20238cdb6332e5728a49918a5f1c897ef9e6 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:28:42 +0200 Subject: [PATCH 042/141] Remove .tk5 fake extension (use TXTH + .ovb) --- src/formats.c | 5 +- src/libvgmstream.vcxproj | 1 - src/libvgmstream.vcxproj.filters | 3 - src/meta/meta.h | 3 - src/meta/ps2_tk5.c | 108 ------------------------------- src/vgmstream.c | 2 - src/vgmstream_types.h | 2 - 7 files changed, 1 insertion(+), 123 deletions(-) delete mode 100644 src/meta/ps2_tk5.c diff --git a/src/formats.c b/src/formats.c index 2ed761138..d156cef08 100644 --- a/src/formats.c +++ b/src/formats.c @@ -405,7 +405,7 @@ static const char* extension_list[] = { "opusx", "otm", "oto", //txth/reserved [Vampire Savior (SAT)] - "ovb", + "ovb", //txth/semi [namCollection: Tekken (PS2), Tekken 5: Tekken 1-3 (PS2)] "p04", //txth/reserved [Psychic Force 2012 (DC), Skies of Arcadia (DC)] "p16", //txth/reserved [Astal (SAT)] @@ -561,7 +561,6 @@ static const char* extension_list[] = { "tgq", "tgv", "thp", - "tk5", "tmx", "tra", "trk", @@ -1138,7 +1137,6 @@ static const meta_info meta_info_list[] = { {meta_SWAV, "Nintendo SWAV header"}, {meta_VSF, "Square-Enix VSF header"}, {meta_NDS_RRDS, "Ridger Racer DS Header"}, - {meta_PS2_TK5, "Tekken 5 Stream Header"}, {meta_PS2_SND, "Might and Magic SSND Header"}, {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, {meta_ADS_MIDWAY, "Midway ADS header"}, @@ -1187,7 +1185,6 @@ static const meta_info meta_info_list[] = { {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, {meta_DSP_DDSP, ".DDSP header"}, {meta_P3D, "Radical P3D header"}, - {meta_PS2_TK1, "Tekken TK5STRM1 Header"}, {meta_NGC_DSP_MPDS, "MPDS DSP header"}, {meta_DSP_STR_IG, "Infogrames .DSP header"}, {meta_EA_SWVR, "Electronic Arts SWVR header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index d08efabe8..96764d658 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -575,7 +575,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 01de1365e..fd2339ecb 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1546,9 +1546,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 7bee9ea97..1832e7503 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -373,9 +373,6 @@ VGMSTREAM * init_vgmstream_vsf(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_nds_rrds(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ps2_vsf_tta(STREAMFILE *streamFile); VGMSTREAM* init_vgmstream_ads_midway(STREAMFILE* sf); diff --git a/src/meta/ps2_tk5.c b/src/meta/ps2_tk5.c deleted file mode 100644 index aefb4f8e2..000000000 --- a/src/meta/ps2_tk5.c +++ /dev/null @@ -1,108 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* TK5 (Tekken 5 Streams) */ -VGMSTREAM * init_vgmstream_ps2_tk5(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("tk5",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x544B3553) - goto fail; - - loop_flag = (read_32bitLE(0x0C,streamFile)!=0); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 48000; - vgmstream->coding_type = coding_PSX_badflags; - vgmstream->num_samples = ((get_streamfile_size(streamFile)-0x800))/16*28/2; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS2_TK5; - - if (vgmstream->loop_flag) - { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; - vgmstream->loop_end_sample = vgmstream->loop_start_sample + (read_32bitLE(0x0C,streamFile)/16*28); - } - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} - -/* OVB - Tekken 5 Streams from Tekken (NamCollection) */ -VGMSTREAM * init_vgmstream_ps2_tk1(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag = 0, channel_count; - - /* checks */ - if (!check_extensions(streamFile, "ovb")) - goto fail; - - if (read_32bitBE(0x00,streamFile) != 0x544B3553) - goto fail; - - loop_flag = (read_32bitLE(0x0C,streamFile)!=0); - channel_count = 2; - start_offset = 0x800; - /* NamCollection uses 44100 while Tekken 5 48000, no apparent way to tell them apart */ - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = 44100; - vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x08,streamFile)*channel_count, channel_count); - if (vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile)/16*28; - vgmstream->loop_end_sample = vgmstream->loop_start_sample + ps_bytes_to_samples(read_32bitLE(0x0c,streamFile)*channel_count, channel_count); - } - - vgmstream->coding_type = coding_PSX_badflags; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS2_TK1; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index d8e1ec6a5..329eea776 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -167,7 +167,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_swav, init_vgmstream_vsf, init_vgmstream_nds_rrds, - init_vgmstream_ps2_tk5, init_vgmstream_ps2_vsf_tta, init_vgmstream_ads_midway, init_vgmstream_ps2_mcg, @@ -214,7 +213,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ngc_rkv, init_vgmstream_dsp_ddsp, init_vgmstream_p3d, - init_vgmstream_ps2_tk1, init_vgmstream_ngc_dsp_mpds, init_vgmstream_dsp_str_ig, init_vgmstream_ea_swvr, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 596daa1cd..282abf20a 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -438,7 +438,6 @@ typedef enum { meta_PS2_P2BT, /* Pop'n'Music 7 Audio File */ meta_PS2_GBTS, /* Pop'n'Music 9 Audio File */ meta_NGC_DSP_IADP, /* Gamecube Interleave DSP */ - meta_PS2_TK5, /* Tekken 5 Stream Files */ meta_PS2_MCG, /* Gunvari MCG Files (was name .GCM on disk) */ meta_ZSD, /* Dragon Booster ZSD */ meta_REDSPARK, /* "RedSpark" RSD (MadWorld) */ @@ -470,7 +469,6 @@ typedef enum { meta_PS2_MSA, /* Psyvariar -Complete Edition- */ meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */ meta_P3D, /* Prototype P3D */ - meta_PS2_TK1, /* Tekken (NamCollection) */ meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */ meta_DSP_DDSP, /* Various (2 dsp files stuck together */ meta_NGC_DSP_MPDS, /* Big Air Freestyle, Terminator 3 */ From d362fe92a4daf99fd0836ff4f1e28456a8edb72b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:35:54 +0200 Subject: [PATCH 043/141] Remove .smpl fake extension [Homura (PS2)] --- src/formats.c | 3 +- src/meta/meta.h | 2 +- src/meta/ps2_smpl.c | 95 ++++++++++++++++++++++--------------------- src/vgmstream.c | 4 +- src/vgmstream_types.h | 2 +- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/src/formats.c b/src/formats.c index d156cef08..e0dd4491e 100644 --- a/src/formats.c +++ b/src/formats.c @@ -508,7 +508,6 @@ static const char* extension_list[] = { "smc", "smk", "smp", - "smpl", //fake extension/header id for .v0/v1 (renamed, to be removed) "smv", "snb", "snd", @@ -1179,7 +1178,7 @@ static const meta_info meta_info_list[] = { {meta_S14, "Namco .S14 raw header"}, {meta_SSS, "Namco .SSS raw header"}, {meta_PS2_GCM, "Namco GCM header"}, - {meta_PS2_SMPL, "Homura SMPL header"}, + {meta_SMPL, "Skonec SMPL header"}, {meta_PS2_MSA, "Success .MSA header"}, {meta_NGC_PDT, "Hudson .PDT header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index 1832e7503..1db642292 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -448,7 +448,7 @@ VGMSTREAM * init_vgmstream_s14_sss(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_smpl(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_smpl(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile); diff --git a/src/meta/ps2_smpl.c b/src/meta/ps2_smpl.c index b4a03712e..359ef481b 100644 --- a/src/meta/ps2_smpl.c +++ b/src/meta/ps2_smpl.c @@ -1,47 +1,48 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* SMPL - from Homura (PS2) */ -VGMSTREAM * init_vgmstream_ps2_smpl(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t channel_size; - - /* checks*/ - /* .v0: left channel, .v1: right channel - * .smpl: header id */ - if ( !check_extensions(streamFile,"v0,v1,smpl") ) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x534D504C) /* "SMPL" */ - goto fail; - - channel_count = 1; - loop_flag = (read_32bitLE(0x30,streamFile) != 0); /* .v1 doesn't have loop points */ - start_offset = 0x40; - channel_size = read_32bitBE(0x0c,streamFile) - 0x10; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitBE(0x10,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count); - vgmstream->loop_start_sample = read_32bitLE(0x30,streamFile); - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->meta_type = meta_PS2_SMPL; - vgmstream->allow_dual_stereo = 1; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_none; - - read_string(vgmstream->stream_name,0x10+1, 0x20,streamFile); - - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* SMPL - from Homura (PS2) */ +VGMSTREAM* init_vgmstream_smpl(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, channel_size; + int loop_flag, channels; + + /* checks*/ + if (!is_id32be(0x00,sf, "SMPL")) + return NULL; + + /* .v0: left channel, .v1: right channel + * .smpl: header id */ + if (!check_extensions(sf,"v0,v1") ) + return NULL; + + /* 0x04: version (VAG-clone) */ + channels = 1; + loop_flag = (read_s32le(0x30,sf) != 0); /* .v1 doesn't have loop points */ + start_offset = 0x40; + channel_size = read_u32be(0x0c,sf) - 0x10; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_s32be(0x10,sf); + vgmstream->num_samples = ps_bytes_to_samples(channel_size*channels, channels); + vgmstream->loop_start_sample = read_s32le(0x30,sf); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->meta_type = meta_SMPL; + vgmstream->allow_dual_stereo = 1; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + + read_string(vgmstream->stream_name,0x10+1, 0x20,sf); + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 329eea776..2ecaf6b0e 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -207,7 +207,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_wb, init_vgmstream_bnsf, init_vgmstream_ps2_gcm, - init_vgmstream_ps2_smpl, + init_vgmstream_smpl, init_vgmstream_ps2_msa, init_vgmstream_ps2_voi, init_vgmstream_ngc_rkv, @@ -1024,7 +1024,7 @@ static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, in /* check these even if there is no loop, because they should then be zero in both * (Homura PS2 right channel doesn't have loop points so this check is ignored) */ - if (new_vgmstream->meta_type != meta_PS2_SMPL && + if (new_vgmstream->meta_type != meta_SMPL && !(new_vgmstream->loop_flag == opened_vgmstream->loop_flag && new_vgmstream->loop_start_sample== opened_vgmstream->loop_start_sample && new_vgmstream->loop_end_sample == opened_vgmstream->loop_end_sample)) { diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 282abf20a..2e647d702 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -465,7 +465,7 @@ typedef enum { meta_S14, /* raw Siren 14, 24kbit mono */ meta_SSS, /* raw Siren 14, 48kbit stereo */ meta_PS2_GCM, /* NamCollection */ - meta_PS2_SMPL, /* Homura */ + meta_SMPL, meta_PS2_MSA, /* Psyvariar -Complete Edition- */ meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */ meta_P3D, /* Prototype P3D */ From be8b74da89fb7c8c9264bf3d3b01b441ae58d002 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:39:37 +0200 Subject: [PATCH 044/141] cleanup: ps2_smpl.c to smpl.c --- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 8 ++++---- src/meta/{ps2_smpl.c => smpl.c} | 0 3 files changed, 5 insertions(+), 5 deletions(-) rename src/meta/{ps2_smpl.c => smpl.c} (100%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 96764d658..672a5ffe2 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -572,7 +572,6 @@ - @@ -633,6 +632,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index fd2339ecb..dff604784 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1537,9 +1537,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1720,6 +1717,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -2069,4 +2069,4 @@ util\Source Files - + \ No newline at end of file diff --git a/src/meta/ps2_smpl.c b/src/meta/smpl.c similarity index 100% rename from src/meta/ps2_smpl.c rename to src/meta/smpl.c From 64318e24d4f5dfa9e681ae8272ac208f1d7996e0 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:41:59 +0200 Subject: [PATCH 045/141] cleanup: lp_ap_lep --- src/formats.c | 2 +- src/meta/meta.h | 2 +- src/meta/ps2_enth.c | 9 ++++++--- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 5 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/formats.c b/src/formats.c index e0dd4491e..e819e3b3b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1080,7 +1080,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_PCM, "Konami KCEJ East .PCM header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"}, {meta_PS2_VAS, "Konami .VAS header"}, - {meta_PS2_ENTH, ".enth Header"}, + {meta_LP_AP_LEP, "Konami LP/AP/LEP header"}, {meta_SDT, "High Voltage .sdt header"}, {meta_NGC_TYDSP, ".tydsp Header"}, {meta_WVS, "Swingin' Ape .WVS header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index 1db642292..a350ddd16 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -256,7 +256,7 @@ VGMSTREAM * init_vgmstream_ps2_rkv(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_vas(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ps2_vas_container(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ps2_enth(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_lp_ap_lep(STREAMFILE* sf); VGMSTREAM * init_vgmstream_sdt(STREAMFILE * streamFile); diff --git a/src/meta/ps2_enth.c b/src/meta/ps2_enth.c index 4501a1f54..449cf533f 100644 --- a/src/meta/ps2_enth.c +++ b/src/meta/ps2_enth.c @@ -3,7 +3,7 @@ #include "ps2_enth_streamfile.h" /* LP/AP/LEP - from Konami (KCES)'s Enthusia: Professional Racing (PS2) */ -VGMSTREAM* init_vgmstream_ps2_enth(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_lp_ap_lep(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; off_t start_offset; @@ -13,10 +13,13 @@ VGMSTREAM* init_vgmstream_ps2_enth(STREAMFILE* sf) { /* checks */ + if (!is_id32be(0x00,sf,"LP ") && !is_id32be(0x00,sf,"AP ") && !is_id32be(0x00,sf,"LEP ")) + return NULL; + /* .bin/lbin: internal (no names in bigfiles but exes mention "bgm%05d.bin" and "LEP data") * .lp/lep/ap: header ID */ if (!check_extensions(sf, "bin,lbin,lp,lep,ap")) - goto fail; + return NULL; id = read_u32be(0x00,sf); switch (id) { @@ -49,7 +52,7 @@ VGMSTREAM* init_vgmstream_ps2_enth(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_PS2_ENTH; + vgmstream->meta_type = meta_LP_AP_LEP; vgmstream->sample_rate = sample_rate; switch (id) { diff --git a/src/vgmstream.c b/src/vgmstream.c index 2ecaf6b0e..a8605ee54 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -101,7 +101,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_rkv, init_vgmstream_ps2_vas, init_vgmstream_ps2_vas_container, - init_vgmstream_ps2_enth, + init_vgmstream_lp_ap_lep, init_vgmstream_sdt, init_vgmstream_aix, init_vgmstream_ngc_tydsp, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 2e647d702..2560820eb 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -346,7 +346,7 @@ typedef enum { meta_PS2_PCM, /* Konami KCEJ East: Ephemeral Fantasia, Yu-Gi-Oh! The Duelists of the Roses, 7 Blades */ meta_PS2_RKV, /* Legacy of Kain - Blood Omen 2 (PS2) */ meta_PS2_VAS, /* Pro Baseball Spirits 5 */ - meta_PS2_ENTH, /* Enthusia */ + meta_LP_AP_LEP, meta_SDT, /* Baldur's Gate - Dark Alliance */ meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ meta_DC_STR, /* SEGA Stream Asset Builder */ From 4e9b6cd6eca13a0db55c7e067f9206a878ec314b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:42:42 +0200 Subject: [PATCH 046/141] cleanup: ps2_enth.c to lp_ap_lep.c --- src/libvgmstream.vcxproj | 4 ++-- src/libvgmstream.vcxproj.filters | 12 ++++++------ src/meta/{ps2_enth.c => lp_ap_lep.c} | 2 +- ...{ps2_enth_streamfile.h => lp_ap_lep_streamfile.h} | 0 4 files changed, 9 insertions(+), 9 deletions(-) rename src/meta/{ps2_enth.c => lp_ap_lep.c} (98%) rename src/meta/{ps2_enth_streamfile.h => lp_ap_lep_streamfile.h} (100%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 672a5ffe2..91b7e4ba1 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -138,6 +138,7 @@ + @@ -147,7 +148,6 @@ - @@ -470,6 +470,7 @@ + @@ -551,7 +552,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index dff604784..76e570c60 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -239,6 +239,9 @@ meta\Header Files + + meta\Header Files + meta\Header Files @@ -266,9 +269,6 @@ meta\Header Files - - meta\Header Files - meta\Header Files @@ -1231,6 +1231,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1474,9 +1477,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/ps2_enth.c b/src/meta/lp_ap_lep.c similarity index 98% rename from src/meta/ps2_enth.c rename to src/meta/lp_ap_lep.c index 449cf533f..bf5231735 100644 --- a/src/meta/ps2_enth.c +++ b/src/meta/lp_ap_lep.c @@ -1,6 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -#include "ps2_enth_streamfile.h" +#include "lp_ap_lep_streamfile.h" /* LP/AP/LEP - from Konami (KCES)'s Enthusia: Professional Racing (PS2) */ VGMSTREAM* init_vgmstream_lp_ap_lep(STREAMFILE* sf) { diff --git a/src/meta/ps2_enth_streamfile.h b/src/meta/lp_ap_lep_streamfile.h similarity index 100% rename from src/meta/ps2_enth_streamfile.h rename to src/meta/lp_ap_lep_streamfile.h From 716aea3369e49d864df5c285b44e1c2bb08db280 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:45:39 +0200 Subject: [PATCH 047/141] Remove fake .pos+.ogg (use TXTP), cleanup --- src/meta/pos.c | 96 ++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 54 deletions(-) diff --git a/src/meta/pos.c b/src/meta/pos.c index 5e499ce66..6e9a24271 100644 --- a/src/meta/pos.c +++ b/src/meta/pos.c @@ -1,55 +1,43 @@ -#include "meta.h" - -/* .pos - loop points for .wav [Ys I Complete (PC); reused for manual looping] */ -VGMSTREAM * init_vgmstream_pos(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamData = NULL; - int32_t loop_start, loop_end; - - - /* checks */ - if (!check_extensions(streamFile, "pos")) - goto fail; - if (get_streamfile_size(streamFile) != 0x08) - goto fail; - - streamData = open_streamfile_by_ext(streamFile, "wav"); - if (streamData) { - vgmstream = init_vgmstream_riff(streamData); - if (!vgmstream) goto fail; - vgmstream->meta_type = meta_RIFF_WAVE_POS; - } - else { -#ifdef VGM_USE_VORBIS - /* hack for Ogg with external loops */ - streamData = open_streamfile_by_ext(streamFile, "ogg"); - if (streamData) { - vgmstream = init_vgmstream_ogg_vorbis(streamData); - if (!vgmstream) goto fail; - } - else { - goto fail; - } -#else - goto fail; -#endif - } - - close_streamfile(streamData); - streamData = NULL; - - /* install loops (wrong values are validated later) */ - loop_start = read_32bitLE(0x00, streamFile); - loop_end = read_32bitLE(0x04, streamFile); - if (loop_end <= 0 || (loop_end > vgmstream->num_samples)) { - loop_end = vgmstream->num_samples; - } - vgmstream_force_loop(vgmstream, 1, loop_start, loop_end); - - return vgmstream; - -fail: - close_streamfile(streamData); - close_vgmstream(vgmstream); - return NULL; +#include "meta.h" + +/* .pos - loop points for .wav [Ys I-II Complete (PC)] */ +VGMSTREAM* init_vgmstream_pos(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sf_data = NULL; + int32_t loop_start, loop_end; + + + /* checks */ + if (get_streamfile_size(sf) != 0x08) + return NULL; + if (!check_extensions(sf, "pos")) + return NULL; + + sf_data = open_streamfile_by_ext(sf, "wav"); + if (sf_data) { + vgmstream = init_vgmstream_riff(sf_data); + if (!vgmstream) goto fail; + vgmstream->meta_type = meta_RIFF_WAVE_POS; + } + else { + goto fail; + } + + close_streamfile(sf_data); + sf_data = NULL; + + /* install loops (wrong values are validated later) */ + loop_start = read_s32le(0x00, sf); + loop_end = read_s32le(0x04, sf); + if (loop_end <= 0 || (loop_end > vgmstream->num_samples)) { + loop_end = vgmstream->num_samples; + } + vgmstream_force_loop(vgmstream, 1, loop_start, loop_end); + + return vgmstream; + +fail: + close_streamfile(sf_data); + close_vgmstream(vgmstream); + return NULL; } \ No newline at end of file From fc2bca92a8648045a8f9080512222ec63eb21a7b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:52:32 +0200 Subject: [PATCH 048/141] cleanup: .smv --- src/formats.c | 2 +- src/meta/smv.c | 99 +++++++++++++++++++++---------------------- src/vgmstream_types.h | 2 +- 3 files changed, 51 insertions(+), 52 deletions(-) diff --git a/src/formats.c b/src/formats.c index e819e3b3b..6670d1fc0 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1293,7 +1293,7 @@ static const meta_info meta_info_list[] = { {meta_WAF, "KID WAF header"}, {meta_WAVE, "EngineBlack .WAVE header"}, {meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"}, - {meta_SMV, "Cho Aniki Zero .SMV header"}, + {meta_SMV, "extreme .SMV header"}, {meta_NXAP, "Nex NXAP header"}, {meta_EA_WVE_AU00, "Electronic Arts WVE (au00) header"}, {meta_EA_WVE_AD10, "Electronic Arts WVE (Ad10) header"}, diff --git a/src/meta/smv.c b/src/meta/smv.c index 6691a0846..bbb5c1c21 100644 --- a/src/meta/smv.c +++ b/src/meta/smv.c @@ -1,50 +1,49 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* .SMV - from Cho Aniki Zero (PSP) */ -VGMSTREAM * init_vgmstream_smv(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t channel_size, loop_start; - - - /* check extension */ - if (!check_extensions(streamFile, "smv")) - goto fail; - - channel_size = read_32bitLE(0x00,streamFile); - /* 0x08: number of full interleave blocks */ - channel_count = read_16bitLE(0x0a,streamFile); - loop_start = read_32bitLE(0x18,streamFile); - loop_flag = (loop_start != -1); - start_offset = 0x800; - - if (channel_size * channel_count + start_offset != get_streamfile_size(streamFile)) - goto fail; - - channel_size -= 0x10; /* last value has SPU end frame without flag 0x7 as it should */ - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(0x10, streamFile); - vgmstream->num_samples = ps_bytes_to_samples(channel_size*channel_count, channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start*channel_count, channel_count); - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->meta_type = meta_SMV; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x04, streamFile); - vgmstream->interleave_last_block_size = read_32bitLE(0x0c, streamFile); - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + +/* .SMV - from Cho Aniki Zero (PSP) */ +VGMSTREAM* init_vgmstream_smv(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, channel_size, loop_start; + int loop_flag, channels; + + + /* check extension */ + if (!check_extensions(sf, "smv")) + goto fail; + + channel_size = read_u32le(0x00,sf); + /* 0x08: number of full interleave blocks */ + channels = read_u16le(0x0a,sf); + loop_start = read_u32le(0x18,sf); + loop_flag = (loop_start != -1); + start_offset = 0x800; + + if (channel_size * channels + start_offset != get_streamfile_size(sf)) + goto fail; + + channel_size -= 0x10; /* last value has SPU end frame without flag 0x7 as it should */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = read_s32le(0x10, sf); + vgmstream->num_samples = ps_bytes_to_samples(channel_size, 1); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, 1); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->meta_type = meta_SMV; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_u32le(0x04, sf); + vgmstream->interleave_last_block_size = read_u32le(0x0c, sf); + + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 2560820eb..97807e2c1 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -580,7 +580,7 @@ typedef enum { meta_WAF, /* KID WAF [Ever 17 (PC)] */ meta_WAVE, /* EngineBlack games [Mighty Switch Force! (3DS)] */ meta_WAVE_segmented, /* EngineBlack games, segmented [Shantae and the Pirate's Curse (PC)] */ - meta_SMV, /* Cho Aniki Zero (PSP) */ + meta_SMV, meta_NXAP, /* Nex Entertainment games [Time Crisis 4 (PS3), Time Crisis Razing Storm (PS3)] */ meta_EA_WVE_AU00, /* Electronic Arts PS movies [Future Cop - L.A.P.D. (PS), Supercross 2000 (PS)] */ meta_EA_WVE_AD10, /* Electronic Arts PS movies [Wing Commander 3/4 (PS)] */ From dd92360096990a53f8c4eb1056a8bd3688726250 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 15:58:29 +0200 Subject: [PATCH 049/141] cleanup: vid1 --- src/meta/meta.h | 2 +- src/meta/vid1.c | 28 +++++++++++++++------------- src/vgmstream.c | 2 +- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/meta/meta.h b/src/meta/meta.h index a350ddd16..d8206c7a4 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -668,7 +668,7 @@ VGMSTREAM * init_vgmstream_ea_tmx(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_sbr(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ea_sbr_harmony(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_vid1(STREAMFILE* sf); VGMSTREAM * init_vgmstream_flx(STREAMFILE * streamFile); diff --git a/src/meta/vid1.c b/src/meta/vid1.c index fedeb81a0..3bc12b152 100644 --- a/src/meta/vid1.c +++ b/src/meta/vid1.c @@ -1,36 +1,38 @@ #include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" +#include "../util/endianness.h" /* VID1 - Factor 5/DivX format GC/Xbox games [Gun (GC), Tony Hawk's American Wasteland (GC), Enter The Matrix (Xbox)]*/ -VGMSTREAM * init_vgmstream_ngc_vid1(STREAMFILE* sf) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset, header_offset; +VGMSTREAM* init_vgmstream_vid1(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, header_offset; int loop_flag = 0, channels, sample_rate; uint32_t codec; int big_endian; - uint32_t (*read_u32)(off_t,STREAMFILE*); + read_u32_t read_u32; /* checks */ - /* .vid: video + (often) audio - * .ogg: audio only [Gun (GC)], .logg: for plugins */ - if (!check_extensions(sf,"vid,ogg,logg")) - goto fail; - - /* chunked/blocked format containing video or audio frames */ - if (read_u32be(0x00, sf) == 0x56494431) { /* "VID1" BE (GC) */ + if (is_id32be(0x00, sf, "VID1")) { /* BE (GC) */ big_endian = 1; } - else if (read_u32le(0x00,sf) == 0x56494431) { /* "VID1" LE (Xbox) */ + else if (is_id32le(0x00,sf, "VID1")) { /* LE (Xbox) */ big_endian = 0; } else { - goto fail; + return NULL; } + + /* .vid: video + (often) audio + * .ogg: audio only [Gun (GC)], .logg: for plugins */ + if (!check_extensions(sf,"vid,ogg,logg")) + return NULL; + read_u32 = big_endian ? read_u32be : read_u32le; + /* chunked/blocked format containing video or audio frames */ /* find actual header start/size in the chunks (id + size + null) */ { diff --git a/src/vgmstream.c b/src/vgmstream.c index a8605ee54..41d419520 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -337,7 +337,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ea_tmx, init_vgmstream_ea_sbr, init_vgmstream_ea_sbr_harmony, - init_vgmstream_ngc_vid1, + init_vgmstream_vid1, init_vgmstream_flx, init_vgmstream_mogg, init_vgmstream_kma9, From d3d8681a24382e64cac02ace79a207bb9f913224 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 16:14:41 +0200 Subject: [PATCH 050/141] cleanup: rwax --- src/formats.c | 16 +++++----- src/meta/rwx.c | 72 +++++++++++++++---------------------------- src/vgmstream_types.h | 2 +- 3 files changed, 33 insertions(+), 57 deletions(-) diff --git a/src/formats.c b/src/formats.c index 6670d1fc0..429985e33 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1052,7 +1052,7 @@ static const meta_info meta_info_list[] = { {meta_FSB3, "FMOD FSB3 header"}, {meta_FSB4, "FMOD FSB4 header"}, {meta_FSB5, "FMOD FSB5 header"}, - {meta_RWX, "RWX Header"}, + {meta_RWAX, "Konami RWAX header"}, {meta_XWB, "Microsoft XWB header"}, {meta_PS2_XA30, "Reflections XA30 PS2 header"}, {meta_MUSC, "Krome MUSC header"}, @@ -1134,7 +1134,7 @@ static const meta_info meta_info_list[] = { {meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"}, {meta_SAT_BAKA, "Konami BAKA header"}, {meta_SWAV, "Nintendo SWAV header"}, - {meta_VSF, "Square-Enix VSF header"}, + {meta_VSF, "Square Enix VSF header"}, {meta_NDS_RRDS, "Ridger Racer DS Header"}, {meta_PS2_SND, "Might and Magic SSND Header"}, {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, @@ -1201,7 +1201,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_JSTM, "JSTM Header"}, {meta_XVAG, "Sony XVAG header"}, {meta_CPS, "tri-Crescendo CPS Header"}, - {meta_SQEX_SCD, "Square-Enix SCD header"}, + {meta_SQEX_SCD, "Square Enix SCD header"}, {meta_NGC_NST_DSP, "Animaniacs NST header"}, {meta_BAF, "Bizarre Creations .baf header"}, {meta_MSF, "Sony MSF header"}, @@ -1211,7 +1211,7 @@ static const meta_info meta_info_list[] = { {meta_SPM, "Square SPM header"}, {meta_VGS_PS, "Princess Soft VGS header"}, {meta_PS2_IAB, "Runtime .IAB header"}, - {meta_VS_STR, "Square .VS STR* header"}, + {meta_VS_STR, "Square .VS STRx header"}, {meta_LSF_N1NJ4N, ".lsf !n1nj4n header"}, {meta_XWAV, "feelplus XWAV header"}, {meta_RAW_SNDS, "PC .snds raw header"}, @@ -1249,7 +1249,7 @@ static const meta_info meta_info_list[] = { {meta_FFMPEG, "FFmpeg supported format"}, {meta_FFMPEG_faulty, "FFmpeg supported format (check log)"}, {meta_CXS, "tri-Crescendo CXS header"}, - {meta_AKB, "Square-Enix AKB header"}, + {meta_AKB, "Square Enix AKB header"}, {meta_PASX, "Premium Agency PASX header"}, {meta_XMA_RIFF, "Microsoft XMA RIFF header"}, {meta_ASTB, "Capcom ASTB header"}, @@ -1288,8 +1288,8 @@ static const meta_info meta_info_list[] = { {meta_OGG_encrypted, "Ogg Vorbis header (encrypted)"}, {meta_KMA9, "Koei Tecmo KMA9 header"}, {meta_XWC, "Starbreeze XWC header"}, - {meta_SQEX_SAB, "Square-Enix SAB header"}, - {meta_SQEX_MAB, "Square-Enix MAB header"}, + {meta_SQEX_SAB, "Square Enix SAB header"}, + {meta_SQEX_MAB, "Square Enix MAB header"}, {meta_WAF, "KID WAF header"}, {meta_WAVE, "EngineBlack .WAVE header"}, {meta_WAVE_segmented, "EngineBlack .WAVE header (segmented)"}, @@ -1319,7 +1319,7 @@ static const meta_info meta_info_list[] = { {meta_WAVEBATCH, "Firebrand Games WBAT header"}, {meta_HD3_BD3, "Sony HD3+BD3 header"}, {meta_BNK_SONY, "Sony BNK header"}, - {meta_SSCF, "Square-Enix SSCF header"}, + {meta_SSCF, "Square Enix SSCF header"}, {meta_DSP_VAG, ".VAG DSP header"}, {meta_DSP_ITL, ".ITL DSP header"}, {meta_A2M, "Artificial Mind & Movement A2M header"}, diff --git a/src/meta/rwx.c b/src/meta/rwx.c index ad61bcfba..60482cd31 100644 --- a/src/meta/rwx.c +++ b/src/meta/rwx.c @@ -1,66 +1,42 @@ #include "meta.h" #include "../util.h" -/* RWX (found in Air Force Delta Storm (XBOX)) */ -VGMSTREAM * init_vgmstream_rwx(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("rwx",filename_extension(filename))) goto fail; +/* RWAX - from AirForce Delta Storm (Xbox) */ +VGMSTREAM* init_vgmstream_rwx(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag = 0; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x52415758) - goto fail; - - - loop_flag = read_32bitLE(0x0C,streamFile); - channel_count = 2; + /* checks */ + if (!is_id32be(0x00,sf, "RAWX")) + return NULL; + if (!check_extensions(sf,"rwx")) + return NULL; + + start_offset = read_u32le(0x04,sf); + loop_flag = read_s32le(0x0C,sf); + channels = 2; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; + vgmstream->meta_type = meta_RWAX; + vgmstream->sample_rate = read_s32le(0x08,sf); + vgmstream->num_samples = read_s32le(0x10,sf); + vgmstream->loop_start_sample = read_s32le(0x0C,sf); + vgmstream->loop_end_sample = read_s32le(0x10,sf); - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x04,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x08,streamFile); vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = read_32bitLE(0x10,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x10,streamFile); - } - vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x2; - vgmstream->meta_type = meta_RWX; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 97807e2c1..dd767fd67 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -328,7 +328,7 @@ typedef enum { meta_FSB3, /* FMOD Sample Bank, version 3.0/3.1 */ meta_FSB4, /* FMOD Sample Bank, version 4 */ meta_FSB5, /* FMOD Sample Bank, version 5 */ - meta_RWX, /* Air Force Delta Storm (XBOX) */ + meta_RWAX, meta_XWB, /* Microsoft XACT framework (Xbox, X360, Windows) */ meta_PS2_XA30, /* Driver - Parallel Lines (PS2) */ meta_MUSC, /* Krome PS2 games */ From a5b4103a10009d93aa7c9be74d840799d8bd6051 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 16:15:39 +0200 Subject: [PATCH 051/141] cleanup: rwx.c to rwax.c --- src/meta/meta.h | 2 +- src/meta/{rwx.c => rwax.c} | 2 +- src/vgmstream.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/meta/{rwx.c => rwax.c} (95%) diff --git a/src/meta/meta.h b/src/meta/meta.h index d8206c7a4..1a601e610 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -211,7 +211,7 @@ VGMSTREAM * init_vgmstream_fsb4_wav(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_fsb5(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_rwx(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_rwax(STREAMFILE* sf); VGMSTREAM * init_vgmstream_xwb(STREAMFILE * streamFile); diff --git a/src/meta/rwx.c b/src/meta/rwax.c similarity index 95% rename from src/meta/rwx.c rename to src/meta/rwax.c index 60482cd31..2bff7aabd 100644 --- a/src/meta/rwx.c +++ b/src/meta/rwax.c @@ -3,7 +3,7 @@ /* RWAX - from AirForce Delta Storm (Xbox) */ -VGMSTREAM* init_vgmstream_rwx(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_rwax(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; uint32_t start_offset; int channels, loop_flag = 0; diff --git a/src/vgmstream.c b/src/vgmstream.c index 41d419520..1f6e5076d 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -79,7 +79,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_fsb, init_vgmstream_fsb4_wav, init_vgmstream_fsb5, - init_vgmstream_rwx, + init_vgmstream_rwax, init_vgmstream_xwb, init_vgmstream_ps2_xa30, init_vgmstream_musc, From 543ff1d95362628a6bd6a2efc05cc30bd00556ff Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 16:36:54 +0200 Subject: [PATCH 052/141] cleanup: rename s14_sss.c to raw_s14_sss.c --- src/formats.c | 2 +- src/meta/meta.h | 2 +- src/meta/myspd.c | 35 ++++++++++++++------------- src/meta/{s14_sss.c => raw_s14_sss.c} | 4 +-- src/vgmstream.c | 2 +- 5 files changed, 23 insertions(+), 22 deletions(-) rename src/meta/{s14_sss.c => raw_s14_sss.c} (97%) diff --git a/src/formats.c b/src/formats.c index 429985e33..0ad4ddb90 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1164,7 +1164,7 @@ static const meta_info meta_info_list[] = { {meta_WII_BNS, "Nintendo BNS header"}, {meta_WII_WAS, "Sumo Digital iSWS header"}, {meta_XBOX_HLWAV, "Half-Life 2 .WAV header"}, - {meta_MYSPD, "U-Sing .MYSPD header"}, + {meta_MYSPD, "Punchers Impact .MYSPD header"}, {meta_HIS, "Her Interactive HIS header"}, {meta_AST_MV, "MicroVision AST header"}, {meta_AST_MMV, "Marvelous AST header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index 1a601e610..ab0a58a46 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -444,7 +444,7 @@ VGMSTREAM * init_vgmstream_bnsf(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_s14_sss(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_raw_s14_sss(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE* streamFile); diff --git a/src/meta/myspd.c b/src/meta/myspd.c index 373f23031..ac7cdb348 100644 --- a/src/meta/myspd.c +++ b/src/meta/myspd.c @@ -1,38 +1,39 @@ #include "meta.h" #include "../coding/coding.h" -/* .MYSPF - from U-Sing (Wii) */ -VGMSTREAM * init_vgmstream_myspd(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - int loop_flag = 0, channel_count; - off_t start_offset; - size_t channel_size; - - /* check extension, case insensitive */ - if (!check_extensions(streamFile,"myspd")) - goto fail; - channel_count = 2; +/* .MYSPD - from U-Sing (Wii) */ +VGMSTREAM* init_vgmstream_myspd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int loop_flag = 0, channels; + uint32_t start_offset, channel_size; + + /* checks */ + /* .myspd: actual extension */ + if (!check_extensions(sf,"myspd")) + return NULL; + + channels = 2; start_offset = 0x20; - channel_size = read_32bitBE(0x00,streamFile); + channel_size = read_s32be(0x00,sf); /* check size */ - if ((channel_size * channel_count + start_offset) != get_streamfile_size(streamFile)) + if (channel_size * channels + start_offset != get_streamfile_size(sf)) goto fail; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; - vgmstream->num_samples = ima_bytes_to_samples(channel_size*channel_count, channel_count); - vgmstream->sample_rate = read_32bitBE(0x04,streamFile); + vgmstream->num_samples = ima_bytes_to_samples(channel_size*channels, channels); + vgmstream->sample_rate = read_s32be(0x04,sf); vgmstream->meta_type = meta_MYSPD; vgmstream->coding_type = coding_IMA_int; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = channel_size; - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/src/meta/s14_sss.c b/src/meta/raw_s14_sss.c similarity index 97% rename from src/meta/s14_sss.c rename to src/meta/raw_s14_sss.c index 921e4e0d3..a52c98b6a 100644 --- a/src/meta/s14_sss.c +++ b/src/meta/raw_s14_sss.c @@ -6,7 +6,7 @@ static int test_interleave(STREAMFILE* sf, int channels, int interleave); /* .s14/.sss - headerless siren14 stream [The Idolm@ster (DS), Korogashi Puzzle Katamari Damacy (DS), Taiko no Tatsujin DS 1/2 (DS)] */ -VGMSTREAM* init_vgmstream_s14_sss(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_raw_s14_sss(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset = 0; int channels, loop_flag = 0, interleave; @@ -18,7 +18,7 @@ VGMSTREAM* init_vgmstream_s14_sss(STREAMFILE* sf) { } else if (check_extensions(sf,"s14")) { channels = 1; /* may have dual _0ch.s14 + _1ch.s14, needs .txtp */ } else { - goto fail; + return NULL; } /* raw siren comes in 3 frame sizes, try to guess the correct one */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 1f6e5076d..5303b1d90 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -552,7 +552,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_raw_snds, /* .snds raw SNDS IMA */ init_vgmstream_raw_wavm, /* .wavm raw xbox */ init_vgmstream_raw_pcm, /* .raw raw PCM */ - init_vgmstream_s14_sss, /* .s14/sss raw siren14 */ + init_vgmstream_raw_s14_sss, /* .s14/sss raw siren14 */ init_vgmstream_exakt_sc, /* .sc raw PCM */ init_vgmstream_zwdsp, /* fake format */ init_vgmstream_ps2_adm, /* weird non-constant PSX blocks */ From 7e5ebbda2a7598782991b720668f72d3f7b12f1b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 16:40:17 +0200 Subject: [PATCH 053/141] cleanup: rsf.c to raw_rsf.c --- src/libvgmstream.vcxproj | 6 +++--- src/libvgmstream.vcxproj.filters | 14 +++++++------- src/meta/meta.h | 2 +- src/meta/{rsf.c => raw_rsf.c} | 8 +++----- src/vgmstream.c | 2 +- 5 files changed, 15 insertions(+), 17 deletions(-) rename src/meta/{rsf.c => raw_rsf.c} (94%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 91b7e4ba1..40301d137 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -594,6 +594,8 @@ + + @@ -602,12 +604,10 @@ - + - - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 76e570c60..5c0197ca8 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1603,6 +1603,12 @@ meta\Source Files + + meta\Source Files + + + meta\Source Files + meta\Source Files @@ -1627,7 +1633,7 @@ meta\Source Files - + meta\Source Files @@ -1636,15 +1642,9 @@ meta\Source Files - - meta\Source Files - meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index ab0a58a46..983dad785 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -82,7 +82,7 @@ VGMSTREAM * init_vgmstream_nps(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_rs03(STREAMFILE *streamFile); -VGMSTREAM* init_vgmstream_rsf(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_raw_rsf(STREAMFILE* sf); VGMSTREAM * init_vgmstream_rwsd(STREAMFILE *streamFile); diff --git a/src/meta/rsf.c b/src/meta/raw_rsf.c similarity index 94% rename from src/meta/rsf.c rename to src/meta/raw_rsf.c index d6fdeedff..22791b9ac 100644 --- a/src/meta/rsf.c +++ b/src/meta/raw_rsf.c @@ -2,19 +2,17 @@ #include "../util.h" #include "../coding/coding.h" -/* .rsf - from Metroid Prime */ - -VGMSTREAM* init_vgmstream_rsf(STREAMFILE* sf) { +/* .rsf - from Metroid Prime (GC) */ +VGMSTREAM* init_vgmstream_raw_rsf(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; int channels, loop_flag; uint32_t interleave, file_size; /* checks */ if (!check_extensions(sf,"rsf")) - goto fail; + return NULL; /* this is all we have to go on, rsf is completely headerless */ - file_size = get_streamfile_size(sf); interleave = (file_size + 1) / 2; diff --git a/src/vgmstream.c b/src/vgmstream.c index 5303b1d90..c2bc9b841 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -531,7 +531,6 @@ init_vgmstream_t init_vgmstream_functions[] = { /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, init_vgmstream_agsc, - init_vgmstream_rsf, init_vgmstream_ps2_wmus, init_vgmstream_mib_mih, init_vgmstream_mjb_mjh, @@ -547,6 +546,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mpeg, /* semi-raw MP3 */ init_vgmstream_btsnd, /* semi-headerless */ init_vgmstream_encrypted, /* encrypted stuff */ + init_vgmstream_raw_rsf, /* raw GC streamed files */ init_vgmstream_raw_int, /* .int raw PCM */ init_vgmstream_ps_headerless, /* tries to detect a bunch of PS-ADPCM formats */ init_vgmstream_raw_snds, /* .snds raw SNDS IMA */ From c65c454d83eb99ebf75e1546c3658d3994caeeab Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 16:58:44 +0200 Subject: [PATCH 054/141] cleandup: ws_aud --- src/meta/ws_aud.c | 106 +++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 63 deletions(-) diff --git a/src/meta/ws_aud.c b/src/meta/ws_aud.c index 41ae998af..cd468007c 100644 --- a/src/meta/ws_aud.c +++ b/src/meta/ws_aud.c @@ -4,128 +4,108 @@ /* Westwood Studios .aud (WS-AUD) */ -VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - +VGMSTREAM* init_vgmstream_ws_aud(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; coding_t coding_type = -1; off_t format_offset; - - int channel_count; - int new_type = 0; /* if 0 is old type */ - + int channels; + bool new_type = false; int bytes_per_sample = 0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("aud",filename_extension(filename))) goto fail; + + /* checks **/ + if (!check_extensions(sf, "aud") ) + return NULL; /* check for 0x0000DEAF chunk marker for first chunk */ - if (read_32bitLE(0x10,streamFile)==0x0000DEAF) { /* new */ - new_type = 1; - } else if (read_32bitLE(0x0C,streamFile)==0x0000DEAF) { /* old */ - new_type = 0; - } else goto fail; - - if (new_type) - format_offset = 0xa; - else - format_offset = 0x6; + if (read_u32le(0x10,sf) == 0x0000DEAF) { /* new */ + new_type = true; + format_offset = 0x0A; + } + else if (read_u32le(0x0C,sf) == 0x0000DEAF) { /* old */ + new_type = false; + format_offset = 0x06; + } + else { + return NULL; + } + + /* blocked format with a mini-header */ - /* get channel count */ - if (read_8bit(format_offset,streamFile) & 1) - channel_count = 2; + if (read_u8(format_offset + 0x00, sf) & 1) + channels = 2; else - channel_count = 1; + channels = 1; - if (channel_count == 2) goto fail; /* TODO: not yet supported (largely - because not yet seen) */ + if (channels == 2) + goto fail; /* not seen */ - /* get output format */ - if (read_8bit(format_offset+1,streamFile) & 2) + if (read_u8(format_offset + 0x01,sf) & 2) bytes_per_sample = 2; else bytes_per_sample = 1; /* check codec type */ - switch (read_8bit(format_offset+1,streamFile)) { + switch (read_u8(format_offset + 0x01,sf)) { case 1: /* Westwood custom */ coding_type = coding_WS; - /* shouldn't happen? */ - if (bytes_per_sample != 1) goto fail; + if (bytes_per_sample != 1) goto fail; /* shouldn't happen? */ break; case 99: /* IMA ADPCM */ coding_type = coding_IMA_int; break; default: goto fail; - break; } /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(channel_count,0); + vgmstream = allocate_vgmstream(channels, 0); if (!vgmstream) goto fail; - /* fill in the vital statistics */ if (new_type) { - vgmstream->num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count; - } else { + vgmstream->num_samples = read_32bitLE(0x06,sf)/bytes_per_sample/channels; + } + else { /* Doh, no output size in old type files. We have to read through the * file looking at chunk headers! Crap! */ int32_t out_size = 0; off_t current_offset = 0x8; - off_t file_size = get_streamfile_size(streamFile); + off_t file_size = get_streamfile_size(sf); while (current_offset < file_size) { int16_t chunk_size; - chunk_size = read_16bitLE(current_offset,streamFile); - out_size += read_16bitLE(current_offset+2,streamFile); + chunk_size = read_16bitLE(current_offset,sf); + out_size += read_16bitLE(current_offset+2,sf); /* while we're here might as well check for valid chunks */ - if (read_32bitLE(current_offset+4,streamFile) != 0x0000DEAF) goto fail; + if (read_32bitLE(current_offset+4,sf) != 0x0000DEAF) goto fail; current_offset+=8+chunk_size; } - vgmstream->num_samples = out_size/bytes_per_sample/channel_count; + vgmstream->num_samples = out_size/bytes_per_sample/channels; } /* they tend to not actually have data for the last odd sample */ if (vgmstream->num_samples & 1) vgmstream->num_samples--; - vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile); + vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,sf); vgmstream->coding_type = coding_type; if (new_type) { vgmstream->meta_type = meta_WS_AUD; - } else { - vgmstream->meta_type = meta_WS_AUD_old; } vgmstream->layout_type = layout_blocked_ws_aud; - /* open the file for reading by each channel */ - { - int i; - STREAMFILE * file; - - file = streamFile->open(streamFile,filename, - STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - - for (i=0;ich[i].streamfile = file; - } - } + if (!vgmstream_open_stream(vgmstream, sf, 0x00) ) + goto fail; - /* start me up */ if (new_type) { - block_update_ws_aud(0xc,vgmstream); + block_update(0x0c, vgmstream); } else { - block_update_ws_aud(0x8,vgmstream); + block_update(0x08, vgmstream); } return vgmstream; - /* clean up anything we may have opened */ fail: if (vgmstream) close_vgmstream(vgmstream); return NULL; From 800b654fba343587b9c000f47afe4922b0083ade Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 17:01:40 +0200 Subject: [PATCH 055/141] cleanup: rename adp_bos to adp_wildfire --- src/formats.c | 5 ++--- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/{adp_bos.c => adp_wildfire.c} | 18 +++++++++--------- src/meta/meta.h | 2 +- src/vgmstream.c | 2 +- src/vgmstream_types.h | 5 ++--- 7 files changed, 19 insertions(+), 21 deletions(-) rename src/meta/{adp_bos.c => adp_wildfire.c} (79%) diff --git a/src/formats.c b/src/formats.c index 0ad4ddb90..e1802e29e 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1031,8 +1031,7 @@ static const meta_info meta_info_list[] = { {meta_AIFC, "Apple AIFF-C (Audio Interchange File Format) header"}, {meta_AIFF, "Apple AIFF (Audio Interchange File Format) header"}, {meta_STR_SNDS, "3DO SNDS header"}, - {meta_WS_AUD, "Westwood Studios .aud header"}, - {meta_WS_AUD_old, "Westwood Studios .aud (old) header"}, + {meta_WS_AUD, "Westwood Studios .AUD header"}, {meta_PS2_IVB, "IVB/BVII header"}, {meta_SVS, "Square SVS header"}, {meta_RIFF_WAVE, "RIFF WAVE header"}, @@ -1218,7 +1217,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_WMUS, "assumed The Warriors Sony ADPCM by .wmus extension"}, {meta_HYPERSCAN_KVAG, "Mattel Hyperscan KVAG"}, {meta_IOS_PSND, "PSND Header"}, - {meta_BOS_ADP, "ADP! header"}, + {meta_ADP_WILDFIRE, "Wildfire ADP! header"}, {meta_QD_ADP, "Quantic Dream .ADP header"}, {meta_EB_SFX, "Excitebots .sfx header"}, {meta_EB_SF0, "assumed Excitebots .sf0 by extension"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 40301d137..47201af97 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -335,9 +335,9 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 5c0197ca8..f6466097f 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -826,15 +826,15 @@ meta\Source Files - - meta\Source Files - meta\Source Files meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/adp_bos.c b/src/meta/adp_wildfire.c similarity index 79% rename from src/meta/adp_bos.c rename to src/meta/adp_wildfire.c index 38b05de20..0ce5b89d2 100644 --- a/src/meta/adp_bos.c +++ b/src/meta/adp_wildfire.c @@ -1,18 +1,18 @@ #include "meta.h" -/* ADP - from Balls of Steel */ -VGMSTREAM* init_vgmstream_adp_bos(STREAMFILE* sf) { +/* ADP - from Wildfire Studios games [Balls of Steel (PC)] */ +VGMSTREAM* init_vgmstream_adp_wildfire(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - off_t start_offset; - int loop_flag = 0; - int channels; + uint32_t start_offset; + int channels, loop_flag = 0; /* checks */ + if (!is_id32be(0x00,sf, "ADP!")) + return NULL; + if (!check_extensions(sf,"adp")) - goto fail; + return NULL; - if (!is_id32be(0x00,sf, "ADP!")) - goto fail; loop_flag = (-1 != read_s32le(0x08,sf)); channels = 1; @@ -30,7 +30,7 @@ VGMSTREAM* init_vgmstream_adp_bos(STREAMFILE* sf) { vgmstream->coding_type = coding_DVI_IMA_int; vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_BOS_ADP; + vgmstream->meta_type = meta_ADP_WILDFIRE; // 0x10, 0x12 - both initial history? //vgmstream->ch[0].adpcm_history1_32 = read_16bitLE(0x10,sf); diff --git a/src/meta/meta.h b/src/meta/meta.h index 983dad785..3995add24 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -519,7 +519,7 @@ VGMSTREAM * init_vgmstream_hyperscan_kvag(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ios_psnd(STREAMFILE* streamFile); -VGMSTREAM* init_vgmstream_adp_bos(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_adp_wildfire(STREAMFILE* sf); VGMSTREAM* init_vgmstream_adp_qd(STREAMFILE* sf); diff --git a/src/vgmstream.c b/src/vgmstream.c index c2bc9b841..bc9594f40 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -245,7 +245,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_xwav_old, init_vgmstream_hyperscan_kvag, init_vgmstream_ios_psnd, - init_vgmstream_adp_bos, + init_vgmstream_adp_wildfire, init_vgmstream_adp_qd, init_vgmstream_eb_sfx, init_vgmstream_eb_sf0, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index dd767fd67..b411f10af 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -410,8 +410,7 @@ typedef enum { meta_AIFC, /* Audio Interchange File Format AIFF-C */ meta_AIFF, /* Audio Interchange File Format */ meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */ - meta_WS_AUD, /* Westwood Studios .aud */ - meta_WS_AUD_old, /* Westwood Studios .aud, old style */ + meta_WS_AUD, meta_RIFF_WAVE, /* RIFF, for WAVs */ meta_RIFF_WAVE_POS, /* .wav + .pos for looping (Ys Complete PC) */ meta_RIFF_WAVE_labl, /* RIFF w/ loop Markers in LIST-adtl-labl */ @@ -506,7 +505,7 @@ typedef enum { meta_PS2_WMUS, /* The Warriors (PS2) */ meta_HYPERSCAN_KVAG, /* Hyperscan KVAG/BVG */ meta_IOS_PSND, /* Crash Bandicoot Nitro Kart 2 (iOS) */ - meta_BOS_ADP, + meta_ADP_WILDFIRE, meta_QD_ADP, meta_EB_SFX, /* Excitebots .sfx */ meta_EB_SF0, /* Excitebots .sf0 */ From c02568d249107930315af3ac676fb461d2d3eeb8 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 17:56:09 +0200 Subject: [PATCH 056/141] cleanup: misc --- src/coding/circus_decoder_lzxpcm.h | 110 ++++++++++++++--------------- src/formats.c | 10 +-- src/meta/dsp_adx.c | 32 +++++---- src/meta/meta.h | 4 +- src/meta/myspd.c | 10 +-- src/meta/ngc_ymf.c | 90 +++++++++-------------- src/meta/sts.c | 24 +++---- src/meta/ydsp.c | 104 ++++++++------------------- src/meta/zsd.c | 104 ++++++++++++--------------- src/util/m2_psb.c | 46 ++++++------ src/vgmstream.c | 4 +- src/vgmstream_types.h | 4 +- 12 files changed, 229 insertions(+), 313 deletions(-) diff --git a/src/coding/circus_decoder_lzxpcm.h b/src/coding/circus_decoder_lzxpcm.h index b457f700d..c4d60f248 100644 --- a/src/coding/circus_decoder_lzxpcm.h +++ b/src/coding/circus_decoder_lzxpcm.h @@ -213,7 +213,7 @@ static int lzxpcm_decompress(lzxpcm_stream_t* strm) { default: goto fail; } - } + } buffer_end: strm->next_out += dst_pos; @@ -232,65 +232,65 @@ static int lzxpcm_decompress(lzxpcm_stream_t* strm) { #if 0 /* non-streamed form that XPCM originally uses, assumes buffers are big enough */ static int lzxpcm_decompress_full(uint8_t* dst, size_t dst_size, const uint8_t* src, size_t src_size) { - int src_pos = 0; - int dst_pos = 0; - uint32_t flags = 0; + int src_pos = 0; + int dst_pos = 0; + uint32_t flags = 0; - while (src_pos < src_size && dst_pos < dst_size) { - flags >>= 1; + while (src_pos < src_size && dst_pos < dst_size) { + flags >>= 1; - if ((flags & 0x0100) == 0) { - flags = 0xFF00 | src[src_pos++]; - } - - if (flags & 1) { + if ((flags & 0x0100) == 0) { + flags = 0xFF00 | src[src_pos++]; + } + + if (flags & 1) { /* uncompressed byte per bit */ - dst[dst_pos++] = src[src_pos++]; - } - else { + dst[dst_pos++] = src[src_pos++]; + } + else { /* compressed data */ - uint32_t length; - uint32_t offset; - const uint32_t token = src[src_pos++]; - - if (token >= 0xC0) { - length = ((token >> 2) & 0x0F) + 4; /* 6b */ - - offset = ((token & 3) << 8) | src[src_pos++]; /* upper 2b + lower 8b */ - } - else if (token >= 0x80) { - length = ((token >> 5) & 3) + 2; /* 2b */ - - offset = token & 0x1F; /* 5b */ - if (offset == 0) { - offset = src[src_pos++]; - } - } - else if (token == 0x7F) { - length = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u) + 2; - src_pos += 2; - - offset = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u); - src_pos += 2; - } - else { - length = token + 4; - - offset = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u); - src_pos += 2; - } - - if (dst_pos + length > dst_size) { - length = dst_size - dst_pos; - } - - for (int i = 0; i < length; i++) { - dst[dst_pos] = dst[dst_pos - offset]; - dst_pos++; - } - } - } + uint32_t length; + uint32_t offset; + const uint32_t token = src[src_pos++]; + + if (token >= 0xC0) { + length = ((token >> 2) & 0x0F) + 4; /* 6b */ + + offset = ((token & 3) << 8) | src[src_pos++]; /* upper 2b + lower 8b */ + } + else if (token >= 0x80) { + length = ((token >> 5) & 3) + 2; /* 2b */ + + offset = token & 0x1F; /* 5b */ + if (offset == 0) { + offset = src[src_pos++]; + } + } + else if (token == 0x7F) { + length = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u) + 2; + src_pos += 2; + + offset = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u); + src_pos += 2; + } + else { + length = token + 4; + + offset = (uint16_t)(src[src_pos] | src[src_pos+1] << 8u); + src_pos += 2; + } + + if (dst_pos + length > dst_size) { + length = dst_size - dst_pos; + } + + for (int i = 0; i < length; i++) { + dst[dst_pos] = dst[dst_pos - offset]; + dst_pos++; + } + } + } return 0; } diff --git a/src/formats.c b/src/formats.c index e1802e29e..56b4bc465 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1094,7 +1094,7 @@ static const meta_info meta_info_list[] = { {meta_SAP, "VING .SAP header"}, {meta_DC_IDVI, "Capcom IDVI header"}, {meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, - {meta_NGC_YMF, "YMF DSP Header"}, + {meta_YMF, "Yuke's .YMF Header"}, {meta_FAG, "Radical .FAG Header"}, {meta_PS2_MIHB, "Sony MultiStream MIC header"}, {meta_DSP_WII_MUS, "mus header"}, @@ -1117,7 +1117,7 @@ static const meta_info meta_info_list[] = { {meta_SPT_SPD, "SPT+SPD DSP Header"}, {meta_ISH_ISD, "ISH+ISD DSP Header"}, {meta_GSP_GSB, "Tecmo GSP+GSB Header"}, - {meta_YDSP, "Yuke's DSP (YDSP) Header"}, + {meta_YDSP, "Yuke's YDSP Header"}, {meta_NGC_SSM, "SSM DSP Header"}, {meta_PS2_JOE, "Asobo Studio .JOE header"}, {meta_VGS, "Guitar Hero VGS Header"}, @@ -1139,7 +1139,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_VSF_TTA, "VSF with SMSS Header"}, {meta_ADS_MIDWAY, "Midway ADS header"}, {meta_PS2_MCG, "Gunvari MCG Header"}, - {meta_ZSD, "ZSD Header"}, + {meta_ZSD, "Konami ZSD header"}, {meta_REDSPARK, "RedSpark Header"}, {meta_IVAUD, "Rockstar .ivaud header"}, {meta_DSP_WII_WSD, ".WSD header"}, @@ -1241,7 +1241,7 @@ static const meta_info meta_info_list[] = { {meta_IDSP_NAMCO, "Namco IDSP header"}, {meta_WIIU_BTSND, "Nintendo Wii U Menu Boot Sound"}, {meta_MCA, "Capcom MCA header"}, - {meta_XB3D_ADX, "Xenoblade 3D ADX header"}, + {meta_ADX_MONSTER, "Monster Games .ADX header"}, {meta_HCA, "CRI HCA header"}, {meta_SVAG_SNK, "SNK SVAG header"}, {meta_PS2_VDS_VDM, "Procyon Studio VDS/VDM header"}, @@ -1380,7 +1380,7 @@ static const meta_info meta_info_list[] = { {meta_KWB, "Koei Tecmo WaveBank header"}, {meta_LRMD, "Sony LRMD header"}, {meta_WWISE_FX, "Audiokinetic Wwise FX header"}, - {meta_DIVA, "DIVA header"}, + {meta_DIVA, "Sega DIVA header"}, {meta_IMUSE, "LucasArts iMUSE header"}, {meta_KTSR, "Koei Tecmo KTSR header"}, {meta_KAT, "Sega KAT header"}, diff --git a/src/meta/dsp_adx.c b/src/meta/dsp_adx.c index 42cbb3d8e..ac4564db3 100644 --- a/src/meta/dsp_adx.c +++ b/src/meta/dsp_adx.c @@ -2,36 +2,38 @@ #include "../coding/coding.h" #include "../util.h" -/* .ADX - from Xenoblade 3D (3DS) */ -VGMSTREAM* init_vgmstream_dsp_adx(STREAMFILE *sf) { +/* .ADX - from Monster Games [Xenoblade 3D (3DS)] */ +VGMSTREAM* init_vgmstream_adx_monster(STREAMFILE *sf) { VGMSTREAM* vgmstream = NULL; int loop_flag, channels; int channel_header_spacing = 0x34; - /* checks */ - if (!check_extensions(sf,"adx")) - goto fail; + /* checks */ if (read_u32be(0x00,sf) != 0x02000000) - goto fail; + return NULL; - channels = read_32bitLE(0, sf); - loop_flag = read_16bitLE(0x6e, sf); + /* .adx: reused from Wii version, but actually DSP */ + if (!check_extensions(sf,"adx")) + return NULL; - if (channels > 2 || channels < 0) goto fail; + channels = read_s32le(0x0, sf); + loop_flag = read_s16le(0x6e, sf); + if (channels > 2 || channels < 0) + goto fail; vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; + vgmstream->meta_type = meta_ADX_MONSTER; vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_XB3D_ADX; - vgmstream->sample_rate = read_32bitLE(0x70,sf); - vgmstream->num_samples = read_32bitLE(0x74, sf); - vgmstream->loop_start_sample = read_32bitLE(0x78, sf); - vgmstream->loop_end_sample = read_32bitLE(0x7c, sf); + vgmstream->sample_rate = read_s32le(0x70,sf); + vgmstream->num_samples = read_s32le(0x74, sf); + vgmstream->loop_start_sample = read_s32le(0x78, sf); + vgmstream->loop_end_sample = read_s32le(0x7c, sf); - dsp_read_coefs_le(vgmstream,sf, 0x4, channel_header_spacing); + dsp_read_coefs_le(vgmstream,sf, 0x04, channel_header_spacing); /* semi-interleave: manually open streams at offset */ { diff --git a/src/meta/meta.h b/src/meta/meta.h index 3995add24..fe0ac6100 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -296,7 +296,7 @@ VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_idsp_ie(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_ymf(STREAMFILE* sf); VGMSTREAM * init_vgmstream_sadl(STREAMFILE * streamFile); @@ -575,7 +575,7 @@ VGMSTREAM * init_vgmstream_ps2_vds_vdm(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_cxs(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_dsp_adx(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_adx_monster(STREAMFILE* sf); VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_akb2(STREAMFILE *streamFile); diff --git a/src/meta/myspd.c b/src/meta/myspd.c index ac7cdb348..f4bf58b6c 100644 --- a/src/meta/myspd.c +++ b/src/meta/myspd.c @@ -18,18 +18,18 @@ VGMSTREAM* init_vgmstream_myspd(STREAMFILE* sf) { channel_size = read_s32be(0x00,sf); /* check size */ - if (channel_size * channels + start_offset != get_streamfile_size(sf)) - goto fail; + if (channel_size * channels + start_offset != get_streamfile_size(sf)) + goto fail; - /* build the VGMSTREAM */ + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(channels,loop_flag); if (!vgmstream) goto fail; - vgmstream->num_samples = ima_bytes_to_samples(channel_size*channels, channels); + vgmstream->num_samples = ima_bytes_to_samples(channel_size*channels, channels); vgmstream->sample_rate = read_s32be(0x04,sf); vgmstream->meta_type = meta_MYSPD; - vgmstream->coding_type = coding_IMA_int; + vgmstream->coding_type = coding_IMA_int; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = channel_size; diff --git a/src/meta/ngc_ymf.c b/src/meta/ngc_ymf.c index 9fad79ecb..357d6ec6c 100644 --- a/src/meta/ngc_ymf.c +++ b/src/meta/ngc_ymf.c @@ -1,77 +1,51 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* YMF (WWE WrestleMania X8) */ -VGMSTREAM * init_vgmstream_ngc_ymf(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; +/* YMF - from Yuke's games [WWE WrestleMania X8 (GC)] */ +VGMSTREAM* init_vgmstream_ymf(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("ymf",filename_extension(filename))) goto fail; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x00000180) - goto fail; + /* checks */ + if (read_u32be(0x00,sf) != 0x00000180 || + read_u32be(0x08,sf) != 0x00000003 || + read_u32be(0x0c,sf) != 0xCCCCCCCC) + return NULL; + /* 0x04: used data size? */ + + /* .ymf: actual extension */ + if (!check_extensions(sf, "ymf")) + return NULL; + + /* .ymf can contain audio or video, but not both (videos start with 0x100 and change minor values), + * though it's are found in ./movie/*.* and probably are considered so */ loop_flag = 0; - channel_count = 2; + channels = 2; + start_offset = read_u32be(0x00,sf); - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x180; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0xA8,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0xDC,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile); - } + vgmstream->meta_type = meta_YMF; + vgmstream->sample_rate = read_32bitBE(0xA8,sf); + vgmstream->num_samples = read_32bitBE(0xDC,sf); + vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x20000; - vgmstream->meta_type = meta_NGC_YMF; + dsp_read_coefs_be(vgmstream, sf, 0xAE, 0x60); + //dsp_read_hist_be(vgmstream, sf, 0xAE + 0x20, 0x60); - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0xAE +i*2,streamFile); - } - if (vgmstream->channels) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x10E +i*2,streamFile); - } - } - } - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/sts.c b/src/meta/sts.c index b8f245f93..84f682241 100644 --- a/src/meta/sts.c +++ b/src/meta/sts.c @@ -9,18 +9,18 @@ VGMSTREAM* init_vgmstream_sts(STREAMFILE* sf) { /* checks */ - if (!check_extensions(sf, "sts")) - goto fail; - data_size = read_u32be(0x00,sf); if (data_size + 0x04 != get_streamfile_size(sf)) - goto fail; + return NULL; + + if (!check_extensions(sf, "sts")) + return NULL; channels = read_u8(0x08,sf) + 1; - sample_rate = read_u16be(0x0c,sf); - /* 0x10: dsp related? */ - /* 0x16: usable size */ - channel_size = read_u32be(0x1a,sf); + sample_rate = read_u16be(0x0c,sf); + /* 0x10: dsp related? */ + /* 0x16: usable size */ + channel_size = read_u32be(0x1a,sf); loop_flag = 0; //(read_s32be(0x4C,sf) != -1); /* not seen */ @@ -34,16 +34,16 @@ VGMSTREAM* init_vgmstream_sts(STREAMFILE* sf) { vgmstream->meta_type = meta_STS; vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = dsp_bytes_to_samples(channel_size, 1); + vgmstream->num_samples = dsp_bytes_to_samples(channel_size, 1); vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = channel_size + 0x2e; + vgmstream->interleave_block_size = channel_size + 0x2e; - dsp_read_coefs_be(vgmstream, sf, 0x1e, start_offset - 0x1e + channel_size); - dsp_read_hist_be(vgmstream, sf, 0x1e + 0x24, start_offset - 0x1e + channel_size); + dsp_read_coefs_be(vgmstream, sf, 0x1e, start_offset - 0x1e + channel_size); + dsp_read_hist_be(vgmstream, sf, 0x1e + 0x24, start_offset - 0x1e + channel_size); if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; diff --git a/src/meta/ydsp.c b/src/meta/ydsp.c index d4c46aa0b..8b37f85fc 100644 --- a/src/meta/ydsp.c +++ b/src/meta/ydsp.c @@ -1,92 +1,48 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* YDSP (from WWE Day of Reckoning) */ -VGMSTREAM * init_vgmstream_ydsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int loop_flag; - int channel_count; - off_t start_offset; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("ydsp",filename_extension(filename))) goto fail; +/* YDSP - from Yuke's games [WWE Day of Reckoning (GC), WWE WrestleMania XIX (GC)] */ +VGMSTREAM* init_vgmstream_ydsp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int channels, loop_flag; + uint32_t start_offset; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x59445350) /* "YDSP" */ - goto fail; + /* checks */ + if (!is_id32be(0x00,sf, "YDSP")) + return NULL; - loop_flag = (read_32bitBE(0xB0,streamFile)!=0x0); - channel_count = (uint16_t)read_16bitBE(0x10,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; + /* .ydsp: header id (in bigfile, .yds is the likely extension comparing similar files) */ + if (!check_extensions(sf, "ydsp")) + return NULL; - /* fill in the vital statistics */ + loop_flag = (read_s32be(0xB0,sf) != 0x0); + channels = read_u16be(0x10,sf); start_offset = 0x120; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x0C,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->meta_type = meta_YDSP; - - vgmstream->num_samples = (read_32bitBE(0x08,streamFile))*14/8/channel_count; - if (loop_flag) - { - vgmstream->loop_start_sample = read_32bitBE(0xB0,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0xB4,streamFile); - } - - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else if (channel_count == 2) - { - vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile); - vgmstream->layout_type = layout_interleave; - } - + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + vgmstream->meta_type = meta_YDSP; + vgmstream->sample_rate = read_s32be(0x0C,sf); - /* open the file for reading */ - - if (vgmstream->coding_type == coding_NGC_DSP) - { - int i; - for (i=0;i<16;i++) - { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x20+i*2,streamFile); - } - if (vgmstream->channels == 2) - { - for (i=0;i<16;i++) - { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x44+i*2,streamFile); - } - } - } + vgmstream->num_samples = dsp_bytes_to_samples(read_u32be(0x08,sf), channels); + vgmstream->loop_start_sample = read_s32be(0xB0,sf); + vgmstream->loop_end_sample = read_s32be(0xB4,sf); - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitBE(0x14,sf); - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } + dsp_read_coefs_be(vgmstream, sf, 0x20, 0x24); + //dsp_read_hist_be(vgmstream, sf, 0x20 + 0x20, 0x24); + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/zsd.c b/src/meta/zsd.c index 245e49ef7..c83bee2bd 100644 --- a/src/meta/zsd.c +++ b/src/meta/zsd.c @@ -1,60 +1,44 @@ -#include "meta.h" -#include "../util.h" - -/* ZSD (Dragon Booster) */ -VGMSTREAM * init_vgmstream_zsd(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("zsd",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x5A534400) goto fail; - - loop_flag = 0; - channel_count = 1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitLE(0x20,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - vgmstream->coding_type = coding_PCM8; - vgmstream->num_samples = read_32bitLE(0x18,streamFile)/channel_count; - vgmstream->interleave_block_size=0x0; - - vgmstream->layout_type = layout_none; - vgmstream->meta_type = meta_ZSD; - - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../util.h" + +/* ZSD - from Dragon Booster (DS) */ +VGMSTREAM* init_vgmstream_zsd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag; + + /* checks */ + if (!is_id32be(0x00,sf, "ZSD\0")) + return NULL; + + /* .zsd: actual extension */ + if (!check_extensions(sf, "zsd")) + return NULL; + + /* 0x04: 0x1000? */ + /* 0x08: 0x0c? */ + /* 0x14: 0x08? */ + /* 0x1c: 0x1000? */ + channels = read_s32le(0x0c,sf); + + loop_flag = 0; + start_offset = read_s32le(0x20,sf); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_ZSD; + vgmstream->sample_rate = read_s32le(0x10,sf); + vgmstream->num_samples = read_s32le(0x18,sf) / channels; + vgmstream->coding_type = coding_PCM8; + vgmstream->layout_type = layout_none; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/util/m2_psb.c b/src/util/m2_psb.c index d38dcd774..f8e272450 100644 --- a/src/util/m2_psb.c +++ b/src/util/m2_psb.c @@ -103,20 +103,20 @@ typedef struct { } list_t; struct psb_context_t { - uint32_t header_id; - uint16_t version; - uint16_t encrypt_value; - uint32_t encrypt_offset; - uint32_t keys_offset; + uint32_t header_id; + uint16_t version; + uint16_t encrypt_value; + uint32_t encrypt_offset; + uint32_t keys_offset; - uint32_t strings_list_offset; - uint32_t strings_data_offset; - uint32_t data_offsets_offset; - uint32_t data_sizes_offset; + uint32_t strings_list_offset; + uint32_t strings_data_offset; + uint32_t data_offsets_offset; + uint32_t data_sizes_offset; - uint32_t data_offset; /* also "resources" */ - uint32_t root_offset; /* initial node */ - uint32_t unknown; /* hash/crc? (v3) */ + uint32_t data_offset; /* also "resources" */ + uint32_t root_offset; /* initial node */ + uint32_t unknown; /* hash/crc? (v3) */ /* main buf and derived stuff */ uint8_t* buf; @@ -328,19 +328,19 @@ psb_context_t* psb_init(STREAMFILE* sf) { bytes = read_streamfile(header, 0x00, sizeof(header), sf); if (bytes != sizeof(header)) goto fail; - ctx->header_id = get_u32be(header + 0x00); - ctx->version = get_u16le(header + 0x04); - ctx->encrypt_value = get_u32le(header + 0x06); - ctx->encrypt_offset = get_u32le(header + 0x08); - ctx->keys_offset = get_u32le(header + 0x0c); + ctx->header_id = get_u32be(header + 0x00); + ctx->version = get_u16le(header + 0x04); + ctx->encrypt_value = get_u32le(header + 0x06); + ctx->encrypt_offset = get_u32le(header + 0x08); + ctx->keys_offset = get_u32le(header + 0x0c); - ctx->strings_list_offset = get_u32le(header + 0x10); - ctx->strings_data_offset = get_u32le(header + 0x14); - ctx->data_offsets_offset = get_u32le(header + 0x18); - ctx->data_sizes_offset = get_u32le(header + 0x1c); + ctx->strings_list_offset = get_u32le(header + 0x10); + ctx->strings_data_offset = get_u32le(header + 0x14); + ctx->data_offsets_offset = get_u32le(header + 0x18); + ctx->data_sizes_offset = get_u32le(header + 0x1c); - ctx->data_offset = get_u32le(header + 0x20); - ctx->root_offset = get_u32le(header + 0x24); + ctx->data_offset = get_u32le(header + 0x20); + ctx->root_offset = get_u32le(header + 0x24); if (ctx->version >= PSB_VERSION3) ctx->unknown = get_u32le(header + 0x28); diff --git a/src/vgmstream.c b/src/vgmstream.c index bc9594f40..a98783836 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -126,7 +126,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_xa2, init_vgmstream_idsp_nl, init_vgmstream_idsp_ie, - init_vgmstream_ngc_ymf, + init_vgmstream_ymf, init_vgmstream_sadl, init_vgmstream_fag, init_vgmstream_ps2_mihb, @@ -278,7 +278,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_svag_snk, init_vgmstream_ps2_vds_vdm, init_vgmstream_cxs, - init_vgmstream_dsp_adx, + init_vgmstream_adx_monster, init_vgmstream_akb, init_vgmstream_akb2, #ifdef VGM_USE_FFMPEG diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index b411f10af..42cecc4bb 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -369,7 +369,7 @@ typedef enum { meta_GCA, /* Metal Slug Anthology */ meta_NGC_SSM, /* Golden Gashbell Full Power */ meta_PS2_JOE, /* Wall-E / Pixar games */ - meta_NGC_YMF, /* WWE WrestleMania X8 */ + meta_YMF, meta_SADL, meta_FAG, /* Jackie Chan - Stuntmaster */ meta_PS2_MIHB, /* Merged MIH+MIB */ @@ -527,7 +527,7 @@ typedef enum { meta_KT_WIIBGM, /* Koei Tecmo WiiBGM */ meta_KTSS, /* Koei Tecmo Nintendo Stream (KNS) */ meta_MCA, /* Capcom MCA "MADP" */ - meta_XB3D_ADX, /* Xenoblade Chronicles 3D ADX */ + meta_ADX_MONSTER, meta_HCA, /* CRI HCA */ meta_SVAG_SNK, meta_PS2_VDS_VDM, /* Graffiti Kingdom */ From 842735b8dbaded2a9b9402eb84202b26941525b2 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 24 Jun 2023 18:05:31 +0200 Subject: [PATCH 057/141] cleanup: renames --- src/libvgmstream.vcxproj | 4 ++-- src/libvgmstream.vcxproj.filters | 12 ++++++------ src/meta/{dsp_adx.c => adx_monster.c} | 0 src/meta/{ngc_ymf.c => ymf.c} | 0 4 files changed, 8 insertions(+), 8 deletions(-) rename src/meta/{dsp_adx.c => adx_monster.c} (100%) rename src/meta/{ngc_ymf.c => ymf.c} (100%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 47201af97..2dc0b2164 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -341,6 +341,7 @@ + @@ -403,7 +404,6 @@ - @@ -520,7 +520,6 @@ - @@ -734,6 +733,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f6466097f..3d2d456bf 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -844,6 +844,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1030,9 +1033,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1381,9 +1381,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -2023,6 +2020,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/dsp_adx.c b/src/meta/adx_monster.c similarity index 100% rename from src/meta/dsp_adx.c rename to src/meta/adx_monster.c diff --git a/src/meta/ngc_ymf.c b/src/meta/ymf.c similarity index 100% rename from src/meta/ngc_ymf.c rename to src/meta/ymf.c From 8db9d8ead3d308e216eec370956400c4aed1816d Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 00:59:10 +0200 Subject: [PATCH 058/141] cleanup: voi --- src/formats.c | 1 + src/meta/meta.h | 2 +- src/meta/ps2_voi.c | 89 ++++++++++++++++--------------------------- src/meta/ymf.c | 2 +- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 6 files changed, 37 insertions(+), 61 deletions(-) diff --git a/src/formats.c b/src/formats.c index 56b4bc465..7566f1bf7 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1179,6 +1179,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_GCM, "Namco GCM header"}, {meta_SMPL, "Skonec SMPL header"}, {meta_PS2_MSA, "Success .MSA header"}, + {meta_VOI, "Irem .VOI header"}, {meta_NGC_PDT, "Hudson .PDT header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, {meta_DSP_DDSP, ".DDSP header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index fe0ac6100..e6f8131b8 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -452,7 +452,7 @@ VGMSTREAM* init_vgmstream_smpl(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_voi(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE* streamFile); diff --git a/src/meta/ps2_voi.c b/src/meta/ps2_voi.c index 2d5a38689..7cae07964 100644 --- a/src/meta/ps2_voi.c +++ b/src/meta/ps2_voi.c @@ -1,81 +1,56 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* VOI - found in "RAW Danger" (PS2) */ -VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int loop_flag = 0; - int channel_count; + +/* .VOI - from Raw Danger (PS2) */ +VGMSTREAM* init_vgmstream_voi(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int channels, loop_flag = 0; off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("voi",filename_extension(filename))) goto fail; - /* check header */ - if (((read_32bitLE(0x04,streamFile)*2)+0x800) != (get_streamfile_size(streamFile))) - { - goto fail; - } + /* checks */ + if (read_u32le(0x00,sf) != 1 && read_u32le(0x00,sf) != 2) + return NULL; + + if (!check_extensions(sf, "voi")) + return NULL; + + /* probably number of samples of all channels */ + if ((read_u32le(0x04,sf) * 2 + 0x800) != get_streamfile_size(sf)) + return NULL; + + channels = read_s32le(0x00,sf); loop_flag = 0; - channel_count = read_32bitLE(0x00,streamFile); + start_offset = 0x800; - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; + vgmstream->meta_type = meta_VOI; + vgmstream->num_samples = pcm16_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels); vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/channel_count/2; - - if (loop_flag) - { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x04,streamFile)/2); - } + vgmstream->layout_type = layout_interleave; - if (read_32bitLE(0x08,streamFile) == 0) - { + if (read_32bitLE(0x08,sf) == 0) { vgmstream->sample_rate = 48000; vgmstream->interleave_block_size = 0x200; } - else if (read_32bitLE(0x08,streamFile) == 1) - { + else if (read_32bitLE(0x08,sf) == 1) { vgmstream->sample_rate = 24000; vgmstream->interleave_block_size = 0x100; } - else - { - goto fail; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_VOI; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } + else { + goto fail; } + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/ymf.c b/src/meta/ymf.c index 357d6ec6c..e326073ae 100644 --- a/src/meta/ymf.c +++ b/src/meta/ymf.c @@ -20,7 +20,7 @@ VGMSTREAM* init_vgmstream_ymf(STREAMFILE* sf) { return NULL; /* .ymf can contain audio or video, but not both (videos start with 0x100 and change minor values), - * though it's are found in ./movie/*.* and probably are considered so */ + * though it's are found in ./movie/... and probably are considered so */ loop_flag = 0; channels = 2; diff --git a/src/vgmstream.c b/src/vgmstream.c index a98783836..5a3b0e092 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -209,7 +209,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_gcm, init_vgmstream_smpl, init_vgmstream_ps2_msa, - init_vgmstream_ps2_voi, + init_vgmstream_voi, init_vgmstream_ngc_rkv, init_vgmstream_dsp_ddsp, init_vgmstream_p3d, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 42cecc4bb..516fca48a 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -466,7 +466,7 @@ typedef enum { meta_PS2_GCM, /* NamCollection */ meta_SMPL, meta_PS2_MSA, /* Psyvariar -Complete Edition- */ - meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */ + meta_VOI, meta_P3D, /* Prototype P3D */ meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */ meta_DSP_DDSP, /* Various (2 dsp files stuck together */ From 56c0ece4426777fb2d371a22086612b2da3df3ce Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 00:59:59 +0200 Subject: [PATCH 059/141] cleanup: rename ps2_voi.c to voi.c --- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/{ps2_voi.c => voi.c} | 0 3 files changed, 4 insertions(+), 4 deletions(-) rename src/meta/{ps2_voi.c => voi.c} (100%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 2dc0b2164..cf30950a2 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -579,7 +579,6 @@ - @@ -680,6 +679,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 3d2d456bf..819626e12 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1558,9 +1558,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1861,6 +1858,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/ps2_voi.c b/src/meta/voi.c similarity index 100% rename from src/meta/ps2_voi.c rename to src/meta/voi.c From c8479a1501802d21c693fa16573f2d1fd6a07e5c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 01:59:21 +0200 Subject: [PATCH 060/141] cleanup: ps2_xa2 to xa2_acclaim --- src/formats.c | 3 +- src/libvgmstream.vcxproj | 3 +- src/libvgmstream.vcxproj.filters | 9 ++--- src/meta/meta.h | 4 +-- src/meta/ps2_xa2.c | 60 ------------------------------- src/meta/ps2_xa2_rrp.c | 62 -------------------------------- src/meta/xa2_acclaim.c | 60 +++++++++++++++++++++++++++++++ src/vgmstream.c | 3 +- src/vgmstream_types.h | 3 +- 9 files changed, 68 insertions(+), 139 deletions(-) delete mode 100644 src/meta/ps2_xa2.c delete mode 100644 src/meta/ps2_xa2_rrp.c create mode 100644 src/meta/xa2_acclaim.c diff --git a/src/formats.c b/src/formats.c index 7566f1bf7..68fa87028 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1090,7 +1090,7 @@ static const meta_info meta_info_list[] = { {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, {meta_XMU, "Outrage XMU header"}, {meta_XVAS, "Konami .XVAS header"}, - {meta_PS2_XA2, "Acclaim XA2 Header"}, + {meta_XA2_ACCLAIM, "Acclaim .XA2 Header"}, {meta_SAP, "VING .SAP header"}, {meta_DC_IDVI, "Capcom IDVI header"}, {meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, @@ -1145,7 +1145,6 @@ static const meta_info meta_info_list[] = { {meta_DSP_WII_WSD, ".WSD header"}, {meta_WII_NDP, "Icon Games NDP header"}, {meta_PS2_SPS, "Ape Escape 2 SPS Header"}, - {meta_PS2_XA2_RRP, "Acclaim XA2 Header"}, {meta_NDS_HWAS, "Vicarious Visions HWAS header"}, {meta_NGC_LPS, "Rave Master LPS Header"}, {meta_NAOMI_ADPCM, "NAOMI/NAOMI2 Arcade games ADPCM header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index cf30950a2..8c9c43ec8 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -582,8 +582,6 @@ - - @@ -707,6 +705,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 819626e12..302202fbd 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1567,12 +1567,6 @@ meta\Source Files - - meta\Source Files - - - meta\Source Files - meta\Source Files @@ -1942,6 +1936,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index e6f8131b8..4a4a254cf 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -292,7 +292,7 @@ VGMSTREAM * init_vgmstream_kraw(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_xa2_acclaim(STREAMFILE* sf); VGMSTREAM * init_vgmstream_idsp_ie(STREAMFILE * streamFile); @@ -389,8 +389,6 @@ VGMSTREAM * init_vgmstream_ivaud(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ps2_sps(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_nds_hwas(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_lps(STREAMFILE * streamFile); diff --git a/src/meta/ps2_xa2.c b/src/meta/ps2_xa2.c deleted file mode 100644 index ffad6f751..000000000 --- a/src/meta/ps2_xa2.c +++ /dev/null @@ -1,60 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* XA2 (XG3 Extreme-G Racing) */ -VGMSTREAM * init_vgmstream_ps2_xa2(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xa2",filename_extension(filename))) goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x0,streamFile); - - if (read_32bitLE(0x4,streamFile) > 0x1000) goto fail; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/channel_count/16*28; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile); - vgmstream->meta_type = meta_PS2_XA2; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - -fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/ps2_xa2_rrp.c b/src/meta/ps2_xa2_rrp.c deleted file mode 100644 index 64091d17a..000000000 --- a/src/meta/ps2_xa2_rrp.c +++ /dev/null @@ -1,62 +0,0 @@ -#include "meta.h" - - -/* XA2 (RC Revenge Pro) */ -VGMSTREAM * init_vgmstream_ps2_xa2_rrp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xa2",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x50,streamFile) != 0x00000000) - goto fail; - - loop_flag = 0; - channel_count = read_32bitLE(0x0,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 44100; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (get_streamfile_size(streamFile)-0x800)*28/16/channel_count; - vgmstream->layout_type = layout_interleave; - if (channel_count > 2) - vgmstream->interleave_block_size = 0x400; - else - vgmstream->interleave_block_size = 0x1000; - vgmstream->meta_type = meta_PS2_XA2_RRP; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - } - } - - return vgmstream; - -fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/xa2_acclaim.c b/src/meta/xa2_acclaim.c new file mode 100644 index 000000000..b55e670f3 --- /dev/null +++ b/src/meta/xa2_acclaim.c @@ -0,0 +1,60 @@ +#include "meta.h" +#include "../coding/coding.h" + + +/* XA2 - from Acclaim games [RC Revenge Pro (PS2), XGIII: Extreme G Racing (PS2)] */ +VGMSTREAM* init_vgmstream_xa2_acclaim(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, sizes_offset; + int channels, loop_flag = 0, interleave; + + + /* checks */ + if (read_u32le(0x00,sf) > 0x10) + return NULL; + + if (!check_extensions(sf, "xa2")) + return NULL; + + channels = read_s32le(0x00, sf); /* seen +16 */ + loop_flag = 0; + + if (read_u32le(0x04,sf) > 0x1000) { /* RCRP (no interleave field) */ + interleave = (channels > 2) ? 0x400 : 0x1000; + sizes_offset = 0x04; + } + else { + interleave = read_s32le(0x04,sf); + sizes_offset = 0x08; + } + + /* N sizes that rougly sum data size (not all the same value), then empty */ + for (int i = 0; i < channels; i++) { + if (read_32bitBE(sizes_offset + 0x04 * i, sf) == 0) + goto fail; + } + + if (read_32bitBE(sizes_offset + 0x04 * channels, sf) != 0) + goto fail; + + start_offset = 0x800; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_XA2_ACCLAIM; + vgmstream->sample_rate = 44100; + vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels); + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 5a3b0e092..6ef4bcbc1 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -123,7 +123,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_idsp_tt, init_vgmstream_kraw, init_vgmstream_ps2_omu, - init_vgmstream_ps2_xa2, + init_vgmstream_xa2_acclaim, init_vgmstream_idsp_nl, init_vgmstream_idsp_ie, init_vgmstream_ymf, @@ -177,7 +177,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_wii_wsd, init_vgmstream_dsp_ndp, init_vgmstream_ps2_sps, - init_vgmstream_ps2_xa2_rrp, init_vgmstream_nds_hwas, init_vgmstream_ngc_lps, init_vgmstream_ps2_snd, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 516fca48a..94baa9fcc 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -356,7 +356,7 @@ typedef enum { meta_DC_IDVI, /* Eldorado Gate */ meta_KRAW, /* Geometry Wars - Galaxies */ meta_PS2_OMU, /* PS2 Int file with Header */ - meta_PS2_XA2, /* XG3 Extreme-G Racing */ + meta_XA2_ACCLAIM, meta_NUB, meta_IDSP_NL, /* Mario Strikers Charged (Wii) */ meta_IDSP_IE, /* Defencer (GC) */ @@ -392,7 +392,6 @@ typedef enum { meta_PS2_VSF_TTA, /* Tiny Toon Adventures: Defenders of the Universe */ meta_ADS_MIDWAY, meta_PS2_SPS, /* Ape Escape 2 */ - meta_PS2_XA2_RRP, /* RC Revenge Pro */ meta_NGC_DSP_KONAMI, /* Konami DSP header, found in various games */ meta_UBI_CKD, /* Ubisoft CKD RIFF header (Rayman Origins Wii) */ meta_RAW_WAVM, From bb7176463b767663e5fab5b7bfc360e4b068b83f Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 11:18:17 +0200 Subject: [PATCH 061/141] cleanup: remove unused bdsp apparently an attempt to support extracted .hst/hxg files from PK: Out of Shadows --- src/formats.c | 2 - src/layout/blocked.c | 3 -- src/layout/blocked_bdsp.c | 18 ------- src/layout/layout.h | 1 - src/libvgmstream.vcxproj | 2 - src/libvgmstream.vcxproj.filters | 6 --- src/meta/dsp_bdsp.c | 87 -------------------------------- src/meta/meta.h | 2 - src/vgmstream.c | 1 - src/vgmstream_types.h | 2 - 10 files changed, 124 deletions(-) delete mode 100644 src/layout/blocked_bdsp.c delete mode 100644 src/meta/dsp_bdsp.c diff --git a/src/formats.c b/src/formats.c index 68fa87028..3c03e690c 100644 --- a/src/formats.c +++ b/src/formats.c @@ -100,7 +100,6 @@ static const char* extension_list[] = { "bcwav", "bcv", //txth/reserved [The Bigs (PSP)] "bd3", - "bdsp", "bfstm", "bfwav", "bg00", @@ -942,7 +941,6 @@ static const layout_info layout_info_list[] = { {layout_blocked_filp, "blocked (FILP)"}, {layout_blocked_ea_swvr, "blocked (EA SWVR)"}, {layout_blocked_adm, "blocked (ADM)"}, - {layout_blocked_bdsp, "blocked (BDSP)"}, {layout_blocked_ivaud, "blocked (IVAUD)"}, {layout_blocked_ps2_iab, "blocked (IAB)"}, {layout_blocked_vs_str, "blocked (STR VS)"}, diff --git a/src/layout/blocked.c b/src/layout/blocked.c index d38a20533..bb7f65648 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -156,9 +156,6 @@ void block_update(off_t block_offset, VGMSTREAM* vgmstream) { case layout_blocked_adm: block_update_adm(block_offset,vgmstream); break; - case layout_blocked_bdsp: - block_update_bdsp(block_offset,vgmstream); - break; case layout_blocked_ps2_iab: block_update_ps2_iab(block_offset,vgmstream); break; diff --git a/src/layout/blocked_bdsp.c b/src/layout/blocked_bdsp.c deleted file mode 100644 index f5e763abd..000000000 --- a/src/layout/blocked_bdsp.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void block_update_bdsp(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitBE(vgmstream->current_block_offset,vgmstream->ch[0].streamfile)/7*8; - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0xC0; - - for (i=0;ichannels;i++) { - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=vgmstream->current_block_offset*i; - - } -} diff --git a/src/layout/layout.h b/src/layout/layout.h index 1eeda70b5..4f3e64d6f 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -31,7 +31,6 @@ void block_update_filp(off_t block_offset, VGMSTREAM* vgmstream); void block_update_ivaud(off_t block_offset, VGMSTREAM* vgmstream); void block_update_ea_swvr(off_t block_offset, VGMSTREAM* vgmstream); void block_update_adm(off_t block_offset, VGMSTREAM* vgmstream); -void block_update_bdsp(off_t block_offset, VGMSTREAM* vgmstream); void block_update_ps2_iab(off_t block_offset, VGMSTREAM* vgmstream); void block_update_vs_str(off_t block_offset, VGMSTREAM* vgmstream); void block_update_rws(off_t block_offset, VGMSTREAM* vgmstream); diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 8c9c43ec8..55e963044 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -283,7 +283,6 @@ - @@ -404,7 +403,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 302202fbd..6c8724ecf 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -670,9 +670,6 @@ layout\Source Files - - layout\Source Files - layout\Source Files @@ -1033,9 +1030,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/dsp_bdsp.c b/src/meta/dsp_bdsp.c deleted file mode 100644 index a72dd7820..000000000 --- a/src/meta/dsp_bdsp.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE *streamFile) { - - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int channel_count; - int loop_flag; - int i; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bdsp",filename_extension(filename))) goto fail; - - channel_count = 2; - loop_flag = 0; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x8,streamFile); - vgmstream->coding_type = coding_NGC_DSP; - -#if 0 - if(loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x64,streamFile); - vgmstream->loop_end_sample = read_32bitBE(0x68,streamFile); - } -#endif - - - vgmstream->layout_type = layout_blocked_bdsp; - vgmstream->interleave_block_size = 0x8; - vgmstream->meta_type = meta_DSP_BDSP; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - - if (!vgmstream->ch[i].streamfile) goto fail; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=i*vgmstream->interleave_block_size; - } - } - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1C+i*2,streamFile); - } - if (vgmstream->channels == 2) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x7C+i*2,streamFile); - } - } - } - - /* Calc num_samples */ - start_offset = 0x0; - block_update_bdsp(start_offset,vgmstream); - vgmstream->num_samples=0; - - do - { - vgmstream->num_samples += vgmstream->current_block_size*14/8; - block_update_bdsp(vgmstream->next_block_offset,vgmstream); - } - while (vgmstream->next_block_offset Date: Sun, 25 Jun 2023 11:32:11 +0200 Subject: [PATCH 062/141] cleanup: simplify VAG meta description --- src/formats.c | 9 +++------ src/meta/vag.c | 20 ++++++++++---------- src/vgmstream_types.h | 10 ++++------ 3 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/formats.c b/src/formats.c index 3c03e690c..6a372cd48 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1007,10 +1007,9 @@ static const meta_info meta_info_list[] = { {meta_DSP_GCM, "Double DSP header stereo by .gcm extension"}, {meta_IDSP_TT, "Traveller's Tales IDSP header"}, {meta_RAW_PCM, "PC .raw raw header"}, - {meta_PS2_VAGi, "Sony VAGi header"}, - {meta_PS2_VAGp, "Sony VAGp header"}, - {meta_PS2_pGAV, "Sony pGAV header"}, - {meta_PS2_VAGp_AAAP, "Acclaim Austin AAAp VAG header"}, + {meta_VAG, "Sony VAG header"}, + {meta_VAG_custom, "Sony VAG header (custom)"}, + {meta_AAAP, "Acclaim Austin AAAp header"}, {meta_SEB, "Game Arts .SEB header"}, {meta_STR_WAV, "Blitz Games .STR+WAV header"}, {meta_ILD, "Tose ILD header"}, @@ -1220,8 +1219,6 @@ static const meta_info meta_info_list[] = { {meta_EB_SFX, "Excitebots .sfx header"}, {meta_EB_SF0, "assumed Excitebots .sf0 by extension"}, {meta_MTAF, "Konami MTAF header"}, - {meta_PS2_VAG1, "Konami VAG1 header"}, - {meta_PS2_VAG2, "Konami VAG2 header"}, {meta_ALP, "High Voltage ALP header"}, {meta_WPD, "WPD 'DPW' header"}, {meta_MN_STR, "Mini Ninjas 'STR' header"}, diff --git a/src/meta/vag.c b/src/meta/vag.c index a00daeacc..94c60593a 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -54,7 +54,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { switch(vag_id) { case 0x56414731: /* "VAG1" [Metal Gear Solid 3 (PS2), Cabela's African Safari (PSP), Shamu's Deep Sea Adventures (PS2)] */ - meta_type = meta_PS2_VAG1; //TODO not always Konami (Sand Grain Studios) + meta_type = meta_VAG_custom; //TODO not always Konami (Sand Grain Studios) start_offset = 0x40; /* 0x30 is extra data in VAG1 */ interleave = 0x10; loop_flag = 0; @@ -66,7 +66,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { break; case 0x56414732: /* "VAG2" (2 channels) [Metal Gear Solid 3 (PS2)] */ - meta_type = meta_PS2_VAG2; + meta_type = meta_VAG_custom; start_offset = 0x40; /* 0x30 is extra data in VAG2 */ channels = 2; interleave = 0x800; @@ -74,7 +74,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { break; case 0x56414769: /* "VAGi" (interleaved) */ - meta_type = meta_PS2_VAGi; + meta_type = meta_VAG_custom; start_offset = 0x800; channels = 2; interleave = read_u32le(0x08,sf); @@ -82,7 +82,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { break; case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */ - meta_type = meta_PS2_pGAV; + meta_type = meta_VAG_custom; start_offset = 0x30; if (is_id32be(0x20,sf, "Ster")) { @@ -109,7 +109,7 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { break; case 0x56414770: /* "VAGp" (standard and variations) */ - meta_type = meta_PS2_VAGp; + meta_type = meta_VAG; if (check_extensions(sf,"vig")) { /* MX vs. ATV Untamed (PS2) */ @@ -339,12 +339,12 @@ VGMSTREAM* init_vgmstream_vag_aaap(STREAMFILE* sf) { int loop_flag; /* checks */ + if (!is_id32be(0x00, sf, "AAAp")) + return NULL; + /* .vag - assumed, we don't know the original filenames */ if (!check_extensions(sf, "vag")) - goto fail; - - if (read_u32be(0x00, sf) != 0x41414170) /* "AAAp" */ - goto fail; + return NULL; interleave = read_u16le(0x04, sf); channels = read_u16le(0x06, sf); @@ -369,7 +369,7 @@ VGMSTREAM* init_vgmstream_vag_aaap(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_PS2_VAGp_AAAP; + vgmstream->meta_type = meta_AAAP; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = ps_bytes_to_samples(channel_size, 1); vgmstream->coding_type = coding_PSX; diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index a091b2576..cbcdbe09d 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -304,10 +304,9 @@ typedef enum { meta_PS_HEADERLESS, /* headerless PS-ADPCM */ meta_MIB_MIH, meta_PS2_MIC, /* KOEI MIC File */ - meta_PS2_VAGi, /* VAGi Interleaved File */ - meta_PS2_VAGp, /* VAGp Mono File */ - meta_PS2_pGAV, /* VAGp with Little Endian Header */ - meta_PS2_VAGp_AAAP, /* Acclaim Austin Audio VAG header */ + meta_VAG, + meta_VAG_custom, + meta_AAAP, meta_SEB, meta_STR_WAV, /* Blitz Games STR+WAV files */ meta_ILD, @@ -507,8 +506,7 @@ typedef enum { meta_EB_SFX, /* Excitebots .sfx */ meta_EB_SF0, /* Excitebots .sf0 */ meta_MTAF, - meta_PS2_VAG1, /* Metal Gear Solid 3 VAG1 */ - meta_PS2_VAG2, /* Metal Gear Solid 3 VAG2 */ + meta_VAG_custom, meta_ALP, meta_WPD, /* Shuffle! (PC) */ meta_MN_STR, /* Mini Ninjas (PC/PS3/WII) */ From 803db193b7a479ec8b471c366a12887f54756a44 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 16:07:16 +0200 Subject: [PATCH 063/141] Add .pwb [Psychonauts (PS2)] Also remove .pnb --- src/formats.c | 12 ++--- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +-- src/meta/bnk_sony.c | 31 +++++++----- src/meta/meta.h | 4 +- src/meta/ps2_pnb.c | 66 ------------------------- src/meta/pwb.c | 82 ++++++++++++++++++++++++++++++++ src/vgmstream.c | 2 +- src/vgmstream_types.h | 3 +- 9 files changed, 115 insertions(+), 93 deletions(-) delete mode 100644 src/meta/ps2_pnb.c create mode 100644 src/meta/pwb.c diff --git a/src/formats.c b/src/formats.c index 6a372cd48..9d589319b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -416,7 +416,6 @@ static const char* extension_list[] = { "pcm", "pdt", "pk", - "pnb", "pona", "pos", "ps3", @@ -424,6 +423,7 @@ static const char* extension_list[] = { "psf", "psh", //fake extension for .vsv (to be removed) "psnd", + "pwb", "r", "rac", //txth/reserved [Manhunt (Xbox)] @@ -976,9 +976,9 @@ static const meta_info meta_info_list[] = { {meta_CSMP, "Retro Studios CSMP header"}, {meta_RFRM, "Retro Studios RFRM header"}, {meta_DTK, "Nintendo DTK raw header"}, - {meta_RSF, "Retro Studios RSF raw header"}, + {meta_RSF, "Retro Studios .RSF raw header"}, {meta_AFC, "Nintendo .AFC header"}, - {meta_AST, "Nintendo AST header"}, + {meta_AST, "Nintendo .AST header"}, {meta_HALPST, "HAL Laboratory HALPST header"}, {meta_DSP_RS03, "Retro Studios RS03 header"}, {meta_DSP_STD, "Nintendo DSP header"}, @@ -987,7 +987,7 @@ static const meta_info meta_info_list[] = { {meta_ADS, "Sony ADS header"}, {meta_NPS, "Namco NPSF header"}, {meta_RWSD, "Nintendo RWSD header (single stream)"}, - {meta_RWAR, "Nintendo RWAR header (single RWAV stream)"}, + {meta_RWAR, "Nintendo RWAR header (single stream)"}, {meta_RWAV, "Nintendo RWAV header"}, {meta_CWAV, "Nintendo CWAV header"}, {meta_FWAV, "Nintendo FWAV header"}, @@ -1013,9 +1013,9 @@ static const meta_info meta_info_list[] = { {meta_SEB, "Game Arts .SEB header"}, {meta_STR_WAV, "Blitz Games .STR+WAV header"}, {meta_ILD, "Tose ILD header"}, - {meta_PS2_PNB, "assumed PNB (PsychoNauts Bgm File) by .pnb extension"}, + {meta_PWB, "Double Fine WB header"}, {meta_RAW_WAVM, "Xbox .wavm raw header"}, - {meta_DSP_STR, "assumed Conan Gamecube STR File by .str extension"}, + {meta_DSP_STR, "Cauldron .STR header"}, {meta_EA_SCHL, "Electronic Arts SCHl header (variable)"}, {meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"}, {meta_CAF, "tri-Crescendo CAF Header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 55e963044..7f20fbc54 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -565,7 +565,6 @@ - @@ -585,6 +584,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 6c8724ecf..6a03b7e68 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1516,9 +1516,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1576,6 +1573,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 052a54f51..0d92f4f47 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -9,9 +9,8 @@ typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec; VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; uint32_t start_offset, stream_offset, name_offset = 0; - uint32_t sblk_offset, data_offset; - uint32_t stream_size, data_size, interleave = 0; - int channels = 0, loop_flag, sample_rate, parts, sblk_version, big_endian; + uint32_t stream_size, interleave = 0; + int channels = 0, loop_flag, sample_rate, big_endian; int loop_start = 0, loop_end = 0; uint32_t center_note, center_fine, flags; uint32_t atrac9_info = 0; @@ -37,25 +36,33 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { big_endian = 0; } else { - goto fail; + return NULL; } /* checks */ if (!check_extensions(sf, "bnk")) - goto fail; + return NULL; + uint32_t sblk_offset, sblk_size, data_offset, data_size, zlsd_size = 0; + int parts, sblk_version; parts = read_u32(0x04,sf); - if (parts < 2 || parts > 3) goto fail; + if (parts < 2 || parts > 3) + return NULL; /* in theory a bank can contain multiple blocks */ sblk_offset = read_u32(0x08,sf); - /* 0x0c: sblk size */ + sblk_size = read_u32(0x0c,sf); data_offset = read_u32(0x10,sf); - data_size = read_u32(0x14,sf); - /* when sblk_offset >= 0x20: */ - /* 0x18: ZLSD small footer, rare in earlier versions [Yakuza 6's Puyo Puyo (PS4)] */ - /* 0x1c: ZLSD size */ + data_size = read_u32(0x14,sf); + if (sblk_offset >= 0x20) { + /* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */ + //zlsd_offset = read_u32(0x18,sf); + zlsd_size = read_u32(0x1c,sf); + } + + if (sblk_offset + sblk_size + data_size + zlsd_size != get_streamfile_size(sf)) + return NULL; /* SE banks, also used for music. Most table fields seems reserved/defaults and * don't change much between subsongs or files, so they aren't described in detail. @@ -64,7 +71,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* SBlk part: parse header */ if (read_u32(sblk_offset+0x00,sf) != get_id32be("klBS")) /* SBlk = SFX block */ - goto fail; + return NULL; sblk_version = read_u32(sblk_offset+0x04,sf); /* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4, 0x05=PS5) * - 04: non-fixed bank? diff --git a/src/meta/meta.h b/src/meta/meta.h index d273c70b1..788cddf5a 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -111,8 +111,6 @@ VGMSTREAM * init_vgmstream_seb(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ild(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_raw_wavm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile); @@ -983,4 +981,6 @@ VGMSTREAM* init_vgmstream_sscf_encrypted(STREAMFILE* sf); VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/ps2_pnb.c b/src/meta/ps2_pnb.c deleted file mode 100644 index 5d9d4696c..000000000 --- a/src/meta/ps2_pnb.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* PNB : PsychoNauts Bgm File */ - -VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - int loop_flag=0; - int channel_count; - off_t start_offset; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("pnb",filename_extension(filename))) goto fail; - - /* check loop */ - loop_flag = (read_32bitLE(0x0C,streamFile)!=0xFFFFFFFF); - channel_count=1; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = 1; - vgmstream->sample_rate = 44100; - - /* Check for Compression Scheme */ - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitBE(0x08,streamFile)/16*28; - - /* Get loop point values */ - if(vgmstream->loop_flag) { - vgmstream->loop_start_sample = read_32bitBE(0x0C,streamFile)/16*28; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - vgmstream->interleave_block_size = 0x10; - vgmstream->layout_type = layout_interleave; - vgmstream->meta_type = meta_PS2_PNB; - - start_offset = (off_t)read_32bitBE(0x00,streamFile); - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - - if (!vgmstream->ch[i].streamfile) goto fail; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset= - (off_t)(start_offset+vgmstream->interleave_block_size*i); - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/pwb.c b/src/meta/pwb.c new file mode 100644 index 000000000..408c7f779 --- /dev/null +++ b/src/meta/pwb.c @@ -0,0 +1,82 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* WB - from Psychonauts (PS2) */ +VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + int channels, loop_flag; + uint32_t stream_offset, stream_size, loop_start, loop_end; + + + /* checks */ + if (!is_id32be(0x00, sf, "WB\2\0")) + return NULL; + + /* .pwb: actual extension (bigfile has only hashes but there are names in internal files) + * (some .pwb have a companion .psb, seems cue-related) */ + if (!check_extensions(sf, "pwb")) + return NULL; + + /* 00: ID + * 04: null + * 08: header offset? (0x20) + * 0c: header size? (0x20) + * 10: entries offset + * 14: entries size + * 18: data offset + * 1c: data size + * 20: always 1 (channels? codec?) + * 24: entries count + * 28: entry size + * 2c: data offset + */ + + + stream_offset = read_u32le(0x18, sf); + + int total_subsongs = read_s32le(0x24, sf); + int target_subsong = sf->stream_index; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail; + + + { + uint32_t offset = read_u32le(0x10, sf) + (target_subsong - 1) * read_u32le(0x28, sf); + + /* 0x00: flags? */ + /* 0x04: always 000AC449 */ + stream_offset = read_u32le(offset + 0x08, sf) + stream_offset; + stream_size = read_u32le(offset + 0x0c, sf); + loop_start = read_u32le(offset + 0x10, sf); + loop_end = read_u32le(offset + 0x14, sf) + loop_start; + loop_flag = loop_end; /* both 0 if no loop */ + channels = 1; + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_PWB; + vgmstream->sample_rate = 24000; + + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(loop_start, channels); + vgmstream->loop_end_sample = ps_bytes_to_samples(loop_end, channels); + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_none; + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + if (!vgmstream_open_stream(vgmstream, sf, stream_offset)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + close_streamfile(sf); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 2b254355c..64ca770b8 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -525,6 +525,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_utf_ahx, init_vgmstream_ego_dic, init_vgmstream_awd, + init_vgmstream_pwb, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, @@ -534,7 +535,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mjb_mjh, init_vgmstream_mic_koei, init_vgmstream_seb, - init_vgmstream_ps2_pnb, init_vgmstream_sli_loops, init_vgmstream_tgc, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index cbcdbe09d..88f263ab0 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -310,7 +310,7 @@ typedef enum { meta_SEB, meta_STR_WAV, /* Blitz Games STR+WAV files */ meta_ILD, - meta_PS2_PNB, /* PsychoNauts Bgm File */ + meta_PWB, meta_VPK, /* VPK Audio File */ meta_PS2_BMDX, /* Beatmania thing */ meta_PS2_IVB, /* Langrisser 3 IVB */ @@ -506,7 +506,6 @@ typedef enum { meta_EB_SFX, /* Excitebots .sfx */ meta_EB_SF0, /* Excitebots .sf0 */ meta_MTAF, - meta_VAG_custom, meta_ALP, meta_WPD, /* Shuffle! (PC) */ meta_MN_STR, /* Mini Ninjas (PC/PS3/WII) */ From 90c4724ddbc62adc3a9f764736103199aa80a175 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Sun, 25 Jun 2023 17:11:01 +0300 Subject: [PATCH 064/141] RWS: pre-AWD variant 0x809 (Burnout 2: Point of Impact) --- src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 3 + src/meta/meta.h | 6 +- src/meta/rws_mono.c | 134 +++++++++++++++++++++++++++++++ src/vgmstream.c | 1 + 5 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 src/meta/rws_mono.c diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index d08efabe8..0003b4bff 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -606,6 +606,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 01de1365e..164ec6d57 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1639,6 +1639,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 7bee9ea97..ae3d5266a 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -21,8 +21,6 @@ VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile); -VGMSTREAM* init_vgmstream_awd(STREAMFILE *sf); - VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_cstr(STREAMFILE *streamFile); @@ -990,4 +988,8 @@ VGMSTREAM* init_vgmstream_sscf_encrypted(STREAMFILE* sf); VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf); + +VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/rws_mono.c b/src/meta/rws_mono.c new file mode 100644 index 000000000..1b12f5acb --- /dev/null +++ b/src/meta/rws_mono.c @@ -0,0 +1,134 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/endianness.h" + + +/* RWS - RenderWare Stream (with the tag 0x809) */ +VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + bool big_endian; + char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; + int bit_depth = 0, channels = 0, idx, interleave, loop_flag, sample_rate = 0, total_subsongs, target_subsong = sf->stream_index; + read_u32_t read_u32; + off_t chunk_offset, header_offset, stream_offset = 0; + size_t chunk_size, header_size, stream_size = 0; + + + /* checks */ + if (read_u32le(0x00, sf) != 0x809) /* File ID */ + goto fail; + if (read_u32le(0x04, sf) + 0x0C != get_streamfile_size(sf)) + goto fail; + /* Burnout 2: Point of Impact (PS2, GCN, Xbox): + * Predecessor to the common 0x80D-0x80F tag rws.c (which is also used in B2) + * with some parts of it later reworked into awd.c seemingly */ + if (!check_extensions(sf, "rws")) + goto fail; + + /* Uses various chunk IDs across the file: + * 0x00000809: File ID + * 0x0000080A: File header ID + * 0x0000080C: File data ID + * + * 0x00000802: Stream ID + * 0x00000803: Stream header ID + * 0x00000804: Stream data ID + */ + + chunk_offset = 0x0C; + if (read_u32le(chunk_offset, sf) != 0x80A) /* File header ID */ + goto fail; + chunk_size = read_u32le(chunk_offset + 0x04, sf); /* usually 0x44 */ + + read_string(header_name, STREAM_NAME_SIZE, chunk_offset + 0x40, sf); + + chunk_offset += chunk_size + 0x0C; + if (read_u32le(chunk_offset, sf) != 0x80C) /* File data ID */ + goto fail; + + big_endian = guess_endian32(chunk_offset + 0x0C, sf); + read_u32 = big_endian ? read_u32be : read_u32le; + + total_subsongs = read_u32(chunk_offset + 0x0C, sf); + + if (!target_subsong) + target_subsong = 1; + + chunk_offset += 0x10; + for (idx = 1; idx <= total_subsongs; idx++) { + if (read_u32le(chunk_offset, sf) != 0x802) /* Stream ID */ + goto fail; + chunk_size = read_u32le(chunk_offset + 0x04, sf); + + if (idx == target_subsong) { + header_offset = chunk_offset + 0x0C; + if (read_u32le(header_offset, sf) != 0x803) /* Stream header ID */ + goto fail; + header_size = read_u32le(header_offset + 0x04, sf); /* usually 0xA0 */ + + sample_rate = read_u32(header_offset + 0x10, sf); + stream_size = read_u32(header_offset + 0x18, sf); + bit_depth = read_u8(header_offset + 0x1C, sf); + channels = read_u8(header_offset + 0x1D, sf); /* always 1? */ + if (channels != 1) + goto fail; + + /* Assumed misc data offs/size at header_offset + 0x20 to +0x24 + * which is always empty since GCN uses PCM S16BE encoding here */ + + read_string(stream_name, STREAM_NAME_SIZE, header_offset + 0x7C, sf); + + stream_offset = header_offset + header_size + 0x0C; + if (read_u32le(stream_offset, sf) != 0x804) /* Stream data ID */ + goto fail; + if (read_u32le(stream_offset + 0x04, sf) != stream_size) + goto fail; + } + chunk_offset += chunk_size + 0x0C; + } + + if (total_subsongs < 1 || target_subsong > total_subsongs) + goto fail; + + interleave = 0; + loop_flag = 0; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) + goto fail; + + vgmstream->meta_type = meta_RWS; + vgmstream->layout_type = layout_none; + vgmstream->sample_rate = sample_rate; + vgmstream->stream_size = stream_size; + vgmstream->num_streams = total_subsongs; + vgmstream->interleave_block_size = interleave; + + /* Likely unreliable, but currently only can be tested with Burnout 2 */ + switch (bit_depth) { + case 4: /* PS-ADPCM, normally DSP-ADPCM would be 4 too (as is in awd.c) but GCN uses PCM */ + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = coding_PSX; + break; + + case 16: /* PCM Signed 16-bit */ + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + break; + + default: + goto fail; + } + + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", header_name, stream_name); + + if (!vgmstream_open_stream(vgmstream, sf, stream_offset + 0x0C)) + goto fail; + + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} \ No newline at end of file diff --git a/src/vgmstream.c b/src/vgmstream.c index 495c4ba38..e3a90bca2 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -529,6 +529,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_s_p_sth, init_vgmstream_utf_ahx, init_vgmstream_ego_dic, + init_vgmstream_rws_mono, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, From d18e9b5b3535204dbbb05921b8c76a99f2849fbe Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 16:18:02 +0200 Subject: [PATCH 065/141] cleanup: ps2_rstm to rstm_rockstar --- src/formats.c | 2 +- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 ++-- src/meta/meta.h | 2 +- src/meta/ps2_rstm.c | 44 ------------------------------ src/meta/rstm_rockstar.c | 47 ++++++++++++++++++++++++++++++++ src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 8 files changed, 55 insertions(+), 52 deletions(-) delete mode 100644 src/meta/ps2_rstm.c create mode 100644 src/meta/rstm_rockstar.c diff --git a/src/formats.c b/src/formats.c index 9d589319b..e625cb3fa 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1060,7 +1060,7 @@ static const meta_info meta_info_list[] = { {meta_SAT_DVI, "Konami KCEN DVI. header"}, {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, {meta_BG00, "Falcom BG00 Header"}, - {meta_PS2_RSTM, "Rockstar Games RSTM Header"}, + {meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"}, {meta_ACM, "InterPlay ACM Header"}, {meta_MUS_ACM, "InterPlay MUS ACM header"}, {meta_PS2_KCES, "Konami KCES Header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 7f20fbc54..6bfc9274a 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -566,7 +566,6 @@ - @@ -598,6 +597,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 6a03b7e68..101f799ee 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1519,9 +1519,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1615,6 +1612,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 788cddf5a..b00af1cdd 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -233,7 +233,7 @@ VGMSTREAM * init_vgmstream_bg00(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_rstm_rockstar(STREAMFILE* sf); VGMSTREAM * init_vgmstream_acm(STREAMFILE * streamFile); diff --git a/src/meta/ps2_rstm.c b/src/meta/ps2_rstm.c deleted file mode 100644 index 664a24395..000000000 --- a/src/meta/ps2_rstm.c +++ /dev/null @@ -1,44 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* RSTM - from Rockstar games [Midnight Club 3, Bully - Canis Canim Edit (PS2)] */ -VGMSTREAM * init_vgmstream_ps2_rstm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - - /* check extension (.rsm: in filelist, .rstm: renamed to header id) */ - if ( !check_extensions(streamFile,"rsm,rstm") ) - goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x5253544D) /* "RSTM" */ - goto fail; - - loop_flag = (read_32bitLE(0x24,streamFile)!=0xFFFFFFFF); - channel_count = read_32bitLE(0x0C,streamFile); - start_offset = 0x800; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = read_32bitLE(0x08,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(read_32bitLE(0x20,streamFile),channel_count); - vgmstream->loop_start_sample = ps_bytes_to_samples(read_32bitLE(0x24,streamFile),channel_count); - vgmstream->loop_end_sample = vgmstream->num_samples; - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_PS2_RSTM; - - /* open the file for reading */ - if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) ) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/rstm_rockstar.c b/src/meta/rstm_rockstar.c new file mode 100644 index 000000000..abb77086d --- /dev/null +++ b/src/meta/rstm_rockstar.c @@ -0,0 +1,47 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* RSTM - from Rockstar games [Midnight Club 3, Bully - Canis Canim Edit (PS2)] */ +VGMSTREAM* init_vgmstream_rstm_rockstar(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag; + + + /* checks */ + if (!is_id32be(0x00, sf, "RSTM")) + return NULL; + + /* .rsm: in filelist + * .rstm: header id */ + if (!check_extensions(sf,"rsm,rstm")) + return NULL; + + loop_flag = (read_s32le(0x24,sf) > 0); + channels = read_s32le(0x0C,sf); + start_offset = 0x800; + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_RSTM_ROCKSTAR; + + vgmstream->sample_rate = read_s32le(0x08,sf); + vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x20,sf),channels); + vgmstream->loop_start_sample = ps_bytes_to_samples(read_u32le(0x24,sf),channels); + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x10; + + /* open the file for reading */ + if ( !vgmstream_open_stream(vgmstream, sf, start_offset) ) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 64ca770b8..a038e82dc 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -91,7 +91,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_bg00, init_vgmstream_sat_dvi, init_vgmstream_dc_kcey, - init_vgmstream_ps2_rstm, + init_vgmstream_rstm_rockstar, init_vgmstream_acm, init_vgmstream_mus_acm, init_vgmstream_ps2_kces, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 88f263ab0..e83577e90 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -336,7 +336,7 @@ typedef enum { meta_IKM, meta_STER, meta_BG00, /* Ibara, Mushihimesama */ - meta_PS2_RSTM, /* Midnight Club 3 */ + meta_RSTM_ROCKSTAR, meta_PS2_KCES, /* Dance Dance Revolution */ meta_HXD, meta_VSV, From aa0d5bf9df27f440e72ebe38581b3abe307142fd Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 16:20:15 +0200 Subject: [PATCH 066/141] rename ps2_ild.c to ild.c --- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/{ps2_ild.c => ild.c} | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) rename src/meta/{ps2_ild.c => ild.c} (97%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 6bfc9274a..2a50e4e99 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -446,6 +446,7 @@ + @@ -555,7 +556,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 101f799ee..db96bc277 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1159,6 +1159,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1486,9 +1489,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/ps2_ild.c b/src/meta/ild.c similarity index 97% rename from src/meta/ps2_ild.c rename to src/meta/ild.c index d7b1146ea..d961fd1c0 100644 --- a/src/meta/ps2_ild.c +++ b/src/meta/ild.c @@ -10,10 +10,10 @@ VGMSTREAM* init_vgmstream_ild(STREAMFILE* sf) { /* check ILD Header */ if (!is_id32be(0x00,sf, "ILD\0")) - goto fail; + return NULL; if (!check_extensions(sf, "ild")) - goto fail; + return NULL; channels = read_u32le(0x04,sf); /* tracks (seen 2 and 4) */ start_offset = read_u32le(0x08,sf); From 8fe3caba59f1e3a93347b6aa704c1015df660342 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 16:22:29 +0200 Subject: [PATCH 067/141] cleanup: ps2_omu to omu --- src/formats.c | 2 +- src/meta/meta.h | 2 +- src/meta/omu.c | 12 +++++------- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 5 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/formats.c b/src/formats.c index e625cb3fa..071734d19 100644 --- a/src/formats.c +++ b/src/formats.c @@ -994,7 +994,7 @@ static const meta_info meta_info_list[] = { {meta_XA, "Sony XA header"}, {meta_RXWS, "Sony RXWS header"}, {meta_RAW_INT, "PS2 .int raw header"}, - {meta_PS2_OMU, "Alter Echo OMU Header"}, + {meta_OMU, "Outrage OMU Header"}, {meta_DSP_STM, "Intelligent Systems STM header"}, {meta_EXST, "Sony EXST header"}, {meta_SVAG_KCET, "Konami SVAG header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index b00af1cdd..cd1d732c8 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -288,7 +288,7 @@ VGMSTREAM * init_vgmstream_ps2_rnd(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_kraw(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ps2_omu(STREAMFILE *streamFile); +VGMSTREAM* init_vgmstream_omu(STREAMFILE* sf); VGMSTREAM* init_vgmstream_xa2_acclaim(STREAMFILE* sf); diff --git a/src/meta/omu.c b/src/meta/omu.c index 387114108..61f6aee20 100644 --- a/src/meta/omu.c +++ b/src/meta/omu.c @@ -1,7 +1,7 @@ #include "meta.h" /* IMU - found in Alter Echo (PS2) */ -VGMSTREAM* init_vgmstream_ps2_omu(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_omu(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset; int loop_flag, channels; @@ -9,13 +9,11 @@ VGMSTREAM* init_vgmstream_ps2_omu(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "OMU ")) - goto fail; - + return NULL; if (!check_extensions(sf,"omu")) - goto fail; - + return NULL; if (!is_id32be(0x08,sf, "FRMT")) - goto fail; + return NULL; loop_flag = 1; channels = read_u8(0x14,sf); @@ -33,7 +31,7 @@ VGMSTREAM* init_vgmstream_ps2_omu(STREAMFILE* sf) { vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x200; - vgmstream->meta_type = meta_PS2_OMU; + vgmstream->meta_type = meta_OMU; if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; diff --git a/src/vgmstream.c b/src/vgmstream.c index a038e82dc..90792c9cd 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -122,7 +122,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_rnd, init_vgmstream_idsp_tt, init_vgmstream_kraw, - init_vgmstream_ps2_omu, + init_vgmstream_omu, init_vgmstream_xa2_acclaim, init_vgmstream_idsp_nl, init_vgmstream_idsp_ie, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index e83577e90..aa8fb36fd 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -353,7 +353,7 @@ typedef enum { meta_SAP, meta_DC_IDVI, /* Eldorado Gate */ meta_KRAW, /* Geometry Wars - Galaxies */ - meta_PS2_OMU, /* PS2 Int file with Header */ + meta_OMU, meta_XA2_ACCLAIM, meta_NUB, meta_IDSP_NL, /* Mario Strikers Charged (Wii) */ From 0a1e79d27cc7332d228c400befa3180d66602a99 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Sun, 25 Jun 2023 17:25:19 +0300 Subject: [PATCH 068/141] RWS 0x809: remove size check (PS2 sometimes pads 4 extra bytes) --- src/meta/rws_mono.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/meta/rws_mono.c b/src/meta/rws_mono.c index 1b12f5acb..ea88ccf50 100644 --- a/src/meta/rws_mono.c +++ b/src/meta/rws_mono.c @@ -17,8 +17,7 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { /* checks */ if (read_u32le(0x00, sf) != 0x809) /* File ID */ goto fail; - if (read_u32le(0x04, sf) + 0x0C != get_streamfile_size(sf)) - goto fail; + /* Burnout 2: Point of Impact (PS2, GCN, Xbox): * Predecessor to the common 0x80D-0x80F tag rws.c (which is also used in B2) * with some parts of it later reworked into awd.c seemingly */ @@ -29,7 +28,7 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { * 0x00000809: File ID * 0x0000080A: File header ID * 0x0000080C: File data ID - * + * * 0x00000802: Stream ID * 0x00000803: Stream header ID * 0x00000804: Stream data ID @@ -73,7 +72,7 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { if (channels != 1) goto fail; - /* Assumed misc data offs/size at header_offset + 0x20 to +0x24 + /* Assumed misc data offs/size at header_offset + 0x20 to +0x24 * which is always empty since GCN uses PCM S16BE encoding here */ read_string(stream_name, STREAM_NAME_SIZE, header_offset + 0x7C, sf); @@ -131,4 +130,4 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { fail: close_vgmstream(vgmstream); return NULL; -} \ No newline at end of file +} From a2400271c93f4bb75a412b7e03e3d9f543eb2822 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 20:59:38 +0200 Subject: [PATCH 069/141] Remove .leg fake ext (use TXTH) [Legaia 2 (PS2)] --- src/formats.c | 5 +-- src/libvgmstream.vcxproj | 1 - src/libvgmstream.vcxproj.filters | 3 -- src/meta/meta.h | 2 - src/meta/ps2_leg.c | 66 -------------------------------- src/vgmstream.c | 1 - src/vgmstream_types.h | 1 - 7 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 src/meta/ps2_leg.c diff --git a/src/formats.c b/src/formats.c index 071734d19..ad8041922 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1053,10 +1053,9 @@ static const meta_info meta_info_list[] = { {meta_PS2_XA30, "Reflections XA30 PS2 header"}, {meta_MUSC, "Krome MUSC header"}, {meta_MUSX, "Eurocom MUSX header"}, - {meta_LEG, "Legaia 2 - Duel Saga LEG Header"}, {meta_FILP, "Bio Hazard - Gun Survivor FILp Header"}, {meta_IKM, "MiCROViSiON IKM header"}, - {meta_STER, "ALCHEMY STER header"}, + {meta_STER, "ALCHEMY STER header"}, {meta_SAT_DVI, "Konami KCEN DVI. header"}, {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, {meta_BG00, "Falcom BG00 Header"}, @@ -1334,7 +1333,7 @@ static const meta_info meta_info_list[] = { {meta_ADPCM_CAPCOM, "Capcom .ADPCM header"}, {meta_UE4OPUS, "Epic Games UE4OPUS header"}, {meta_XWMA, "Microsoft XWMA RIFF header"}, - {meta_VA3, "Konami VA3 header" }, + {meta_VA3, "Konami VA3 header"}, {meta_XOPUS, "Exient XOPUS header"}, {meta_VS_SQUARE, "Square VS header"}, {meta_NWAV, "Chunsoft NWAV header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 2a50e4e99..a69417ec8 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -558,7 +558,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index db96bc277..8c4436326 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1495,9 +1495,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index cd1d732c8..cd0a57ef6 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -219,8 +219,6 @@ VGMSTREAM * init_vgmstream_musc(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_musx(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_leg(STREAMFILE * streamFile); - VGMSTREAM * init_vgmstream_filp(STREAMFILE * streamFile); VGMSTREAM* init_vgmstream_ikm(STREAMFILE* sf); diff --git a/src/meta/ps2_leg.c b/src/meta/ps2_leg.c deleted file mode 100644 index 146bca55b..000000000 --- a/src/meta/ps2_leg.c +++ /dev/null @@ -1,66 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* LEG - found in Legaia 2 - Duel Saga (PS2) -the headers are stored seperately in the main executable... */ -VGMSTREAM * init_vgmstream_leg(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("leg",filename_extension(filename))) goto fail; - - /* comparing the filesize with (num_samples*0x800) + headersize, - if it doesn't match, we will abort the vgmstream... */ - if ((read_32bitLE(0x48,streamFile)*0x800)+0x4C != get_streamfile_size(streamFile)) - goto fail; - - loop_flag = (read_32bitLE(0x44,streamFile)!=0); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x4C; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x40,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x48,streamFile)*0x800)*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = (read_32bitLE(0x44,streamFile)*0x800)*28/16/channel_count; - vgmstream->loop_end_sample = (read_32bitLE(0x48,streamFile)*0x800)*28/16/channel_count; - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x400; - vgmstream->meta_type = meta_LEG; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index 90792c9cd..cd8f395fa 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -84,7 +84,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_xa30, init_vgmstream_musc, init_vgmstream_musx, - init_vgmstream_leg, init_vgmstream_filp, init_vgmstream_ikm, init_vgmstream_ster, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index aa8fb36fd..37d1a7861 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -331,7 +331,6 @@ typedef enum { meta_PS2_XA30, /* Driver - Parallel Lines (PS2) */ meta_MUSC, /* Krome PS2 games */ meta_MUSX, - meta_LEG, /* Legaia 2 [no header_id] */ meta_FILP, /* Resident Evil - Dead Aim */ meta_IKM, meta_STER, From 442084cc85cf8c128a6c1cc66d93c537250ad75a Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 21:20:28 +0200 Subject: [PATCH 070/141] Add format info generator and update FORMATS.md --- .github/formats-info.py | 282 +++++ .gitignore | 1 + doc/FORMATS.md | 2168 +++++++++++++++++++++++++++++++++----- doc/TXTH.md | 2 +- src/libvgmstream.vcxproj | 2 +- 5 files changed, 2213 insertions(+), 242 deletions(-) create mode 100644 .github/formats-info.py diff --git a/.github/formats-info.py b/.github/formats-info.py new file mode 100644 index 000000000..e7f74ae2a --- /dev/null +++ b/.github/formats-info.py @@ -0,0 +1,282 @@ +# Generates formats-info.md based on src/meta code, to update FORMATS.md. +# A bit crummy and all but whatevs. + +import glob, os, re + +#TODO maybe sort by meta order list in vgmstream.c +#TODO fix ??? descriptions +#TODO fix some "ext + ext" exts +#TODO improve some ubi formats +#TODO detect subfile/init_x calls that aren't VGMSTREAM * init_ +#TODO detect MPEG_x, OPUS_x subtypes +#TODO ignore some check extensions +#TODO include common idstrings (first is_id32be() / is_id32le / get_id32be / get_id32be) +# > after first valid init? + +META_FILES = '../**/meta/*.c' +FORMAT_FILES = '../**/formats.c' +IS_PRINT_INFO = False #false = write + +#VGMSTREAM * init_vgmstream_9tav(STREAMFILE *sf) #allow static since it's used in some cases +RE_INIT = re.compile(r"VGMSTREAM[ ]*\*[ ]*init_vgmstream_([A-Za-z0-9_]+)\(.+\)") +RE_INIT_STATIC = re.compile(r"static VGMSTREAM[ ]*\*[ ]*init_vgmstream_([A-Za-z0-9_]+)\(.+\)") + +RE_CODING = re.compile(r"coding_([A-Z0-9][A-Za-z0-9_]+)") + +RE_META = re.compile(r"meta_([A-Z0-9][A-Za-z0-9_]+)") + +#sf_dat = open_streamfile_by_ext(sf, "dat"); +RE_COMPANION_EXT = re.compile(r"open_streamfile_by_ext\(.+,[ ]*\"(.+)\"[ ]*\)") + +# a = init_... +RE_SUBFILES = re.compile(r"^(?!VGMSTREAM).*init_vgmstream_([A-Za-z0-9_]+)[(;]") +RE_COMPANION_FILE = re.compile(r"open_streamfile_by_filename\(.+,[ ]*(.+)?\)") + +# if (!check_extensions(sf,"...")) +# if (check_extensions(sf,"...")) { ... } else goto fail; +RE_NEW_EXTCHECK = re.compile(r"\([ ]*[!]*check_extensions\([ ]*.+?,[ ]*\"(.+)\"[ ]*\)") +#if (strcasecmp("bg00",filename_extension(filename))) goto fail; +RE_OLD_EXTCHECK = re.compile(r"if[ ]*\(strcasecmp\([ ]*\"(.+)\"[ ]*,filename_extension") + +# formats.c extract +RE_FORMATS_META = re.compile(r"{meta_([A-Z0-9][A-Za-z0-9_]+)[ ]*,[ ]* \"(.+)\"[ ]*}") + +FILES_SKIP = [ + 'txth.c','txtp.c','genh.c', + 'silence.c', 'mp4_faac.c', 'deblock_streamfile.c', + 'ps_headerless.c', 'zwdsp.c', 'ngc_bh2pcm.c', +] + +EXT_RENAMES = {'...': '(any)', '': '(extensionless)'} +INIT_IGNORES = ['default', 'main'] +META_IGNORES = ['meta_type', 'meta_t'] +CODING_IGNORES = ['coding_type', 'coding_t', 'FFmpeg', 'SILENCE'] +SUBFILES_IGNORES = ['subkey', 'silence', 'silence_container'] + + +# various codecs that +INIT_CODECS = { + re.compile(r'init_ffmpeg_aac\('): 'AAC', + re.compile(r'init_ffmpeg_xwma\('): 'XWMA', + re.compile(r'init_ffmpeg_atrac3plus_.+\('): 'ATRAC3PLUS', + re.compile(r'init_ffmpeg_atrac3_.+\('): 'ATRAC3', + re.compile(r'init_ffmpeg_xma_.+\('): 'XMA', + re.compile(r'init_ffmpeg_xma1_.+\('): 'XMA1', + re.compile(r'init_ffmpeg_xma2_.+\('): 'XMA2', + re.compile(r'init_mpeg_custom\('): 'MPEG', + re.compile(r'init_ffmpeg_mp4_.+\('): 'MP4/AAC', + re.compile(r'init_ffmpeg_offset\('): 'FFmpeg(various)', + re.compile(r'init_ffmpeg_header_offset\('): 'FFmpeg(various)', + re.compile(r'init_ffmpeg_header_offset_subsong\('): 'FFmpeg(various)', + re.compile(r'init_ffmpeg_.+?_opus.*\('): 'Opus', + re.compile(r'init_vgmstream_ogg_vorbis_config\('): 'OGG', +} + +class MetaInit: + def __init__(self, name): + self.name = name + self.subfiles = [] + self.exts = [] + self.companions = [] + #self.metas = [] + + def is_used(self): + return self.subfiles or self.exts or self.companions + +class MetaFile: + def __init__(self, file): + self.fileinfo = os.path.basename(file) + # divide each file into sub-metas since some .c have a bunch of them + self.curr = MetaInit('default') #shouldn't be used but... + self.inits = [self.curr] + self.metas = [] + self.codings = [] + + def add_inits(self, elems): + if len(elems) > 1: + raise ValueError("multiinit?") + + for elem in elems: + self.curr = MetaInit(elem) + self.inits.append(self.curr) + + def _add(self, new_items, items, renames={}): + if not new_items: + return + + for new_item in new_items: + if new_item in renames: + new_item = renames[new_item] + if new_item not in items: + items.append(new_item) + + #def add_inits(self, elems): + # self._add(elems, self.inits) + + def add_codings(self, codings): + self._add(codings, self.codings) + + def add_exts(self, exts, renames={}): + self._add(exts, self.curr.exts, renames) + + def add_metas(self, metas): + self._add(metas, self.metas) + + def add_companions(self, elems): + self._add(elems, self.curr.companions) + + def add_subfiles(self, elems): + self._add(elems, self.curr.subfiles) + +class App: + def __init__(self): + self.infos = [] + self.desc_metas = {} + + def extract_extensions(self, line): + + exts = RE_NEW_EXTCHECK.findall(line) + if not exts: + exts = RE_OLD_EXTCHECK.findall(line) + if not exts: + return + exts_str = ','.join(exts) + return exts_str.split(',') + + def extract_regex(self, line, regex, ignores=[]): + items = [] + results = regex.findall(line) + for result in results: + if result in ignores: + continue + items.append(result) + return items + + def extract_codecs(self, line): + for regex, codec in INIT_CODECS.items(): + if regex.search(line): + return [codec] + + def parse_files(self): + infos = self.infos + + files = glob.glob(META_FILES, recursive=True) + for file in files: + info = MetaFile(file) + with open(file, 'r', encoding='utf-8') as f: + internals = [] + for line in f: + # use to ignore subcalls to internal functions + items = self.extract_regex(line, RE_INIT_STATIC) + if items: + internals += items + + items = self.extract_regex(line, RE_INIT) + info.add_inits(items) + + items = self.extract_extensions(line) + info.add_exts(items, EXT_RENAMES) + + items = self.extract_regex(line, RE_META, META_IGNORES) + info.add_metas(items) + + items = self.extract_regex(line, RE_CODING, CODING_IGNORES) + info.add_codings(items) + + items = self.extract_regex(line, RE_COMPANION_EXT) + info.add_companions(items) + + items = self.extract_regex(line, RE_COMPANION_FILE) + if items: + info.add_companions(['(external)']) + + items = self.extract_regex(line, RE_SUBFILES, SUBFILES_IGNORES) + if not any(x in internals for x in items): + info.add_subfiles(items) + + items = self.extract_codecs(line) + info.add_codings(items) + + infos.append(info) + + def parse_formats(self): + desc_metas = self.desc_metas + files = glob.glob(FORMAT_FILES, recursive=True) + for file in files: + with open(file, 'r', encoding='utf-8') as f: + for line in f: + items = self.extract_regex(line, RE_FORMATS_META) + if not items or len(items[0]) != 2: + continue + meta, desc = items[0] + desc_metas[meta] = desc + + + def print(self): + desc_metas = self.desc_metas + infos = self.infos + + lines = [] + for info in infos: + #info.sort() + if info.fileinfo in FILES_SKIP: + continue + + fileinfo = '- **%s**' % (info.fileinfo) + #if info.metas: + # metas = ' '.join(info.metas) + # fileinfo += " (%s)" % (metas) + lines.append(fileinfo) + + + if info.metas: + for meta in info.metas: + desc = desc_metas.get(meta, '???') + metainfo = "%s [*%s*]" % (desc, meta) + lines.append(' - ' + metainfo) + else: + lines.append(' - (container)') + + for init in info.inits: + if not init.is_used(): + continue + if INIT_IGNORES and init.name in INIT_IGNORES: + continue + + initinfo = '*%s*' % (init.name) + + infoexts = '' + if init.exts: + infoexts = '.' + ' .'.join(init.exts) + if init.companions: + if not init.exts: + infoexts = '(base)' + infoexts += ' + .' + ' .'.join(init.companions) + if infoexts: + #lines.append(infoexts) + initinfo += ": `%s`" % infoexts + lines.append(' - ' + initinfo) + + if init.subfiles: + subfiles = 'Subfiles: *%s*' % ' '.join(init.subfiles) + lines.append(' - ' + subfiles) + + if info.codings: + codings = 'Codecs: ' + ' '.join(info.codings) + lines.append(' - ' + codings) + + #lines.append('') + + if IS_PRINT_INFO: + print('\n'.join(lines)) + else: + with open('formats-info.md', 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + + def process(self): + self.parse_files() + self.parse_formats() + self.print() + + +App().process() diff --git a/.gitignore b/.gitignore index af30a2f59..2e22a21b8 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,5 @@ doc/INFO.md doc/_build changelog.txt +formats-info.md __pycache__ \ No newline at end of file diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 0ce1f25cc..581549678 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -1,249 +1,1937 @@ -## Supported file types -As manakoAT likes to say, the extension doesn't really mean anything, but it's -the most obvious way to identify files. +# vgmstream support list -This list is not complete and many other files are supported. +## Supported formats +The following list is auto-generated, and may be missing a few things, but should give +you an idea of what vgmstream supports. -- PS2/PSX ADPCM: - - .ads/.ss2 - - .ass - - .ast - - .bg00 - - .bmdx - - .cnk - - .enth - - .fag - - .filp - - .gcm - - .gms - - .hgc1 - - .ikm - - .ild - - .ivb - - .joe - - .kces - - .khv - - .leg - - .mcg - - .mib, .mi4 (w/ or w/o .mih) - - .mic - - .mihb (merged mih+mib) - - .msa - - .msvp - - .musc - - .npsf - - .pnb - - .psh - - .rkv - - .rnd - - .rstm - - .rws - - .snd - - .sfs - - .sl3 - - .smpl (w/ bad flags) - - .ster - - .str+.sth - - .str (MGAV blocked) - - .sts - - .svag - - .svs - - .tec (w/ bad flags) - - .tk5 (w/ bad flags) - - .vas - - .vag - - .vgs (w/ bad flags) - - .vig - - .vpk - - .vs - - .vsf - - .wp2 - - .xa2 - - .xa30 - - .xwb+xwh -- GC/Wii/3DS DSP ADPCM: - - .aaap - - .agsc - - .asr - - .bns - - .bo2 - - .cfn - - .ddsp - - .dsp - - standard, optional dual file stereo - - RS03 - - Cstr - - _lr.dsp - - MPDS - - .gca - - .gcm - - .gsp+.gsp - - .hps - - .idsp - - .ish+.isd - - .lps - - .mca - - .mpdsp - - .mss - - .mus (not quite right) - - .ndp - - .pdt - - .sdt - - .smp - - .sns - - .spt+.spd - - .ssm - - .stm/.dsp - - .str - - .str+.sth - - .sts - - .swd - - .thp, .dsp - - .tydsp - - .vjdsp - - .waa, .wac, .wad, .wam - - .was - - .wsd - - .wsi - - .ydsp - - .ymf - - .zwdsp -- PCM: - - .aiff (8 bit, 16 bit) - - .asd (16 bit) - - .baka (16 bit) - - .bh2pcm (16 bit) - - .dmsg (16 bit) - - .gcsw (16 bit) - - .gcw (16 bit) - - .his (8 bit) - - .int (16 bit) - - .pcm (8 bit, 16 bit) - - .kraw (16 bit) - - .raw (16 bit) - - .rwx (16 bit) - - .sap (16 bit) - - .snd (16 bit) - - .sps (16 bit) - - .str (16 bit) - - .xss (16 bit) - - .voi (16 bit) - - .wb (16 bit) - - .zsd (8 bit) -- Xbox IMA ADPCM: - - .matx - - .wavm - - .wvs - - .xmu - - .xvas - - .xwav -- Yamaha AICA ADPCM: - - .adpcm - - .dcs+.dcsw - - .str - - .spsd -- IMA ADPCM: - - .bar (IMA ADPCM) - - .pcm/dvi (DVI IMA ADPCM) - - .hwas (IMA ADPCM) - - .dvi/idvi (DVI IMA ADPCM) - - .ivaud (IMA ADPCM) - - .myspd (IMA ADPCM) - - .strm (IMA ADPCM) -- multi: - - .aifc (SDX2 DPCM, DVI IMA ADPCM) - - .asf/as4 (8/16 bit PCM, DVI IMA ADPCM) - - .ast (GC AFC ADPCM, 16 bit PCM) - - .aud (IMA ADPCM, WS DPCM) - - .aus (PSX ADPCM, Xbox IMA ADPCM) - - .awd/.hwd/.lwd (PSX ADPCM, XBOX IMA ADPCM, GC DSP ADPCM, 16 bit PCM) - - .brstm (GC DSP ADPCM, 8/16 bit PCM) - - .emff (PSX APDCM, GC DSP ADPCM) - - .fsb/wii (PSX ADPCM, GC DSP ADPCM, Xbox IMA ADPCM, MPEG audio, FSB Vorbis, MS XMA) - - .msf (PCM, PSX ADPCM, ATRAC3, MP3) - - .musx (PSX ADPCM, Xbox IMA ADPCM, DAT4 IMA ADPCM) - - .nwa (16 bit PCM, NWA DPCM) - - .p3d (Radical ADPCM, Radical MP3, XMA2) - - .psw (PSX ADPCM, GC DSP ADPCM) - - .rwar, .rwav (GC DSP ADPCM, 8/16 bit PCM) - - .rws (PSX ADPCM, XBOX IMA ADPCM, GC DSP ADPCM, 16 bit PCM) - - .rwsd (GC DSP ADPCM, 8/16 bit PCM) - - .rsd (PSX ADPCM, 16 bit PCM, GC DSP ADPCM, Xbox IMA ADPCM, Radical ADPCM) - - .rrds (NDS IMA ADPCM) - - .sad (GC DSP ADPCM, NDS IMA ADPCM, Procyon Studios NDS ADPCM) - - .sgd/sgb+sgh/sgx (PSX ADPCM, ATRAC3plus, AC3) - - .seg (Xbox IMA ADPCM, PS2 ADPCM) - - .sng/asf/str/eam/aud (8/16 bit PCM, EA-XA ADPCM, PSX ADPCM, GC DSP ADPCM, XBOX IMA ADPCM, MPEG audio, EALayer3) - - .strm (NDS IMA ADPCM, 8/16 bit PCM) - - .sb0..7 (Ubi IMA ADPCM, GC DSP ADPCM, PSX ADPCM, Xbox IMA ADPCM, ATRAC3) - - .swav (NDS IMA ADPCM, 8/16 bit PCM) - - .xwb (PCM, Xbox IMA ADPCM, MS ADPCM, XMA, XWMA, ATRAC3) - - .xwb+xwh (PCM, PSX ADPCM, ATRAC3) - - .wav/lwav (unsigned 8 bit PCM, 16 bit PCM, GC DSP ADPCM, MS IMA ADPCM, XBOX IMA ADPCM) - - .wem [lwav/logg/xma] (PCM, Wwise Vorbis, Wwise IMA ADPCM, XMA, XWMA, GC DSP ADPCM, Wwise Opus) -- etc: - - .2dx9 (MS ADPCM) - - .aax (CRI ADX ADPCM) - - .acm (InterPlay ACM) - - .adp (GC DTK ADPCM) - - .adx (CRI ADX ADPCM) - - .afc (GC AFC ADPCM) - - .ahx (MPEG-2 Layer II) - - .aix (CRI ADX ADPCM) - - .at3 (Sony ATRAC3 / ATRAC3plus) - - .aud (Silicon Knights Vorbis) - - .baf (PSX configurable ADPCM) - - .bgw (PSX configurable ADPCM) - - .bnsf (G.722.1) - - .caf (Apple IMA4 ADPCM, others) - - .dec/de2 (MS ADPCM) - - .hca (CRI High Compression Audio) - - .pcm/kcey (DVI IMA ADPCM) - - .lsf (LSF ADPCM) - - .mc3 (Paradigm MC3 ADPCM) - - .mp4/lmp4 (AAC) - - .msf (PCM, PSX ADPCM, ATRAC3, MP3) - - .mtaf (Konami ADPCM) - - .mta2 (Konami XAS-like ADPCM) - - .mwv (Level-5 0x555 ADPCM) - - .ogg/logg (Ogg Vorbis) - - .ogl (Shin'en Vorbis) - - .rsf (CCITT G.721 ADPCM) - - .sab (Worms 4 soundpacks) - - .s14/sss (G.722.1) - - .sc (Activision EXAKT SASSC DPCM) - - .scd (MS ADPCM, MPEG Audio, 16 bit PCM) - - .sd9 (MS ADPCM) - - .smp (MS ADPCM) - - .spw (PSX configurable ADPCM) - - .stm/lstm (16 bit PCM, DVI IMA ADPCM, GC DSP ADPCM) - - .str (SDX2 DPCM) - - .stx (GC AFC ADPCM) - - .ulw (u-Law PCM) - - .um3 (Ogg Vorbis) - - .xa (CD-ROM XA audio) - - .xma (MS XMA/XMA2) - - .sb0/sb1/sb2/sb3/sb4/sb5/sb6/sb7 (many) - - .sm0/sm1/sm2/sm3/sm4/sm5/sm6/sm7 (many) - - .bao/pk (many) -- artificial/generic headers: - - .genh (lots) - - .txth (lots) +Keep in mind that while the extension is the most obvious way to identify files, +different formats can reuse them (a `.wav` could be a standard Windows WAV, or many +other things). Similarly, just because vgmstream supports a few `.bnk` formats +doesn't mean it supports many other generic `.bnk` that have nothing to do with audio. + +Some formats are subdivided into small variations, listed under the same `.c` file. +Others may refer to "subfiles"; this means internally chain into other formats and +its codecs. Those "container" formats may not have a unique description or codecs +and just reuse the subfile's. + +Also note that for historical reasons, some formats allow fake extensions (never found +in any game), like `.xwav`. Those may be removed from time to time as code is cleaned +up. Formats marked as "*raw_*" also may be phased out at times when support is moved +to *TXTH*. + +Support for the listed formats below should be complete enough. If you have files from +a supported that don't play feel free to report. Often it means the format may be a bit +different internally (encrypted, different versions, etc) and not always can be fixed. + +### List +- **208.c** + - Ocean .208 header [*208*] + - *208*: `.208` + - Codecs: PCM8_U +- **2dx9.c** + - beatmania IIDX 2DX9 header [*2DX9*] + - *2dx9*: `.2dx9` + - Codecs: MSADPCM +- **9tav.c** + - Konami 9TAV header [*9TAV*] + - *9tav*: `.9tav` + - Codecs: ATRAC9 +- **a2m.c** + - Artificial Mind & Movement A2M header [*A2M*] + - *a2m*: `.int` + - Codecs: PSX +- **aac_triace.c** + - tri-Ace AAC header [*AAC_TRIACE*] + - *aac_triace*: `.aac .laac` + - Codecs: XMA2 ATRAC3 ATRAC9 MSADPCM ASKA OGG_VORBIS +- **aax.c** + - CRI AAX header [*AAX*] + - *aax*: `.aax .(extensionless)` + - Subfiles: *hca adx* +- **acb.c** + - (container) + - *acb*: `.acb` + - Subfiles: *cpk_memory awb_memory* +- **acm.c** + - InterPlay ACM Header [*ACM*] + - *acm*: `.acm .tun .wavc` + - Codecs: ACM +- **acx.c** + - (container) + - *acx*: `.acx` + - Subfiles: *adx* +- **adm3.c** + - Crankcase ADM3 header [*ADM3*] + - *adm3*: `.wem` + - Codecs: APPLE_IMA4 +- **adpcm_capcom.c** + - Capcom .ADPCM header [*ADPCM_CAPCOM*] + - *adpcm_capcom*: `.adpcm .mca` + - Codecs: NGC_DSP +- **adp_konami.c** + - Konami ADP header [*ADP_KONAMI*] + - *adp_konami*: `.adp` + - Codecs: OKI4S +- **adp_qd.c** + - Quantic Dream .ADP header [*QD_ADP*] + - *adp_qd*: `.adp` + - Codecs: QD_IMA +- **adp_wildfire.c** + - Wildfire ADP! header [*ADP_WILDFIRE*] + - *adp_wildfire*: `.adp` + - Codecs: DVI_IMA_int +- **ads.c** + - Sony ADS header [*ADS*] + - *ads*: `.ads .ss2 .pcm .adx .(extensionless) .800` + - *ads_container*: `.ads .cads` + - Subfiles: *ads* + - Codecs: PCM16LE DVI_IMA_int PSX +- **ads_midway.c** + - Midway ADS header [*ADS_MIDWAY*] + - *ads_midway*: `.ads` + - Codecs: NGC_DSP XBOX_IMA_int +- **adx.c** + - CRI ADX header type 03 [*ADX_03*] + - CRI ADX header type 04 [*ADX_04*] + - CRI ADX header type 05 [*ADX_05*] + - *adx* + - Subfiles: *adx_subkey* + - *adx_subkey*: `.adx .adp + .(external)` + - Codecs: CRI_ADX_fixed CRI_ADX CRI_ADX_exp CRI_ADX_enc_8 CRI_ADX_enc_9 +- **adx_monster.c** + - Monster Games .ADX header [*ADX_MONSTER*] + - *adx_monster*: `.adx` + - Codecs: NGC_DSP +- **afc.c** + - Nintendo .AFC header [*AFC*] + - *afc*: `.afc .stx` + - Codecs: NGC_AFC +- **agsc.c** + - Retro Studios AGSC header [*AGSC*] + - *agsc*: `.agsc` + - Codecs: NGC_DSP +- **ahv.c** + - Amuze AHV header [*AHV*] + - *ahv*: `.ahv` + - Codecs: PSX +- **ahx.c** + - CRI AHX header [*AHX*] + - *ahx*: `.ahx` + - Codecs: MPEG +- **aifc.c** + - Apple AIFF-C (Audio Interchange File Format) header [*AIFC*] + - Apple AIFF (Audio Interchange File Format) header [*AIFF*] + - *aifc*: `.aif .laif .wav .lwav .(extensionless) .aifc .laifc .afc .cbd2 .bgm .fda .n64 .xa .aiff .laiff .acm .adp .ai .pcm` + - Codecs: SDX2 CBD2 DVI_IMA_int APPLE_IMA4 RELIC VADPCM PCM8 PCM16BE XA +- **aif_asobo.c** + - Asobo Studio .AIF header [*AIF_ASOBO*] + - *aif_asobo*: `.aif .laif` + - Codecs: XBOX_IMA +- **aix.c** + - CRI AIX header [*AIX*] + - *aix*: `.aix` + - Subfiles: *adx* +- **akb.c** + - Square Enix AKB header [*AKB*] + - *akb*: `.akb` + - Subfiles: *ogg_vorbis_config* + - *akb2*: `.akb` + - Subfiles: *ogg_vorbis_config* + - Codecs: MSADPCM OGG FFmpeg(various) PCM16LE +- **alp.c** + - High Voltage ALP header [*ALP*] + - *alp*: `.tun .pcm` + - Codecs: HV_IMA +- **ao.c** + - AlphaOgg .AO header [*AO*] + - *ao*: `.ao` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **apc.c** + - Cryo APC header [*APC*] + - *apc*: `.apc` + - Codecs: IMA +- **apple_caff.c** + - Apple Core Audio Format File header [*CAFF*] + - *apple_caff*: `.caf` + - Codecs: PCM8 APPLE_IMA4 +- **asf.c** + - Argonaut ASF header [*ASF*] + - *asf*: `.asf .lasf` + - Codecs: ASF +- **ast.c** + - Nintendo .AST header [*AST*] + - *ast*: `.ast` + - Codecs: NGC_AFC PCM16BE +- **astb.c** + - Capcom ASTB header [*ASTB*] + - *astb*: `.ast` + - Codecs: XMA +- **ast_mmv.c** + - Marvelous AST header [*AST_MMV*] + - *ast_mmv*: `.ast` + - Codecs: PSX +- **ast_mv.c** + - MicroVision AST header [*AST_MV*] + - *ast_mv*: `.ast` + - Codecs: PSX +- **atsl.c** + - (container) + - *atsl*: `.atsl .atsl3 .atsl4 .atslx` + - Subfiles: *ogg_vorbis riff xma ktac ktss* +- **atx.c** + - (container) + - *atx*: `.atx + .(external)` + - Subfiles: *riff* +- **aus.c** + - Capcom AUS Header [*AUS*] + - *aus*: `.aus` + - Codecs: XBOX_IMA PSX +- **awb.c** + - (container) + - *awb* + - Subfiles: *awb_memory* + - *awb_memory*: `.awb .afs2 + .acb .(external)` + - Subfiles: *adx_subkey hca_subkey vag riff bcwav ngc_dsp_std dsp_cwac mp4_aac_ffmpeg* +- **awc.c** + - Rockstar AWC header [*AWC*] + - *awc*: `.awc` + - Codecs: PCM16BE PCM16LE AWC_IMA XMA2 MPEG VORBIS_custom +- **awd.c** + - RenderWare Audio Wave Dictionary header [*AWD*] + - *awd*: `.awd .hwd .lwd` + - Codecs: PSX PCM16LE NGC_DSP XBOX_IMA +- **baf.c** + - Bizarre Creations .baf header [*BAF*] + - *baf*: `.baf` + - Codecs: PCM16LE PSX_cfg XMA1 +- **bar.c** + - Guitar Hero III Mobile .bar [*GH3_BAR*] + - *bar*: `.bar` + - Codecs: IMA +- **bcstm.c** + - Nintendo CSTM Header [*CSTM*] + - *bcstm*: `.bcstm` + - Codecs: PCM8 PCM16LE NGC_DSP NW_IMA +- **bfstm.c** + - Nintendo FSTM Header [*FSTM*] + - *bfstm*: `.bfstm` + - Codecs: PCM8 PCM16BE PCM16LE NGC_DSP +- **bfwav.c** + - Nintendo RWAV header [*RWAV*] + - Nintendo FWAV header [*FWAV*] + - Nintendo CWAV header [*CWAV*] + - *brwav*: `.brwav .rwav` + - *bfwav*: `.bfwav .fwav` + - *bcwav*: `.bcwav .adpcm .bms .sfx .str .zic` + - *brwar*: `.rwar` + - Subfiles: *brwav* + - Codecs: PCM8 PCM16BE PCM16LE NGC_DSP NW_IMA +- **bgw.c** + - Square Enix .BGW header [*FFXI_BGW*] + - Square Enix .SPW header [*FFXI_SPW*] + - *bgw*: `.bgw` + - *spw*: `.spw` + - Codecs: PSX_cfg ATRAC3 PCM16LE +- **bigrp.c** + - Inti Creates .BIGRP header [*BIGRP*] + - *bigrp*: `.bigrp` + - Codecs: ICE_RANGE ICE_DCT +- **bik.c** + - RAD Game Tools Bink header [*BINK*] + - *bik*: `.bik .bik2 .bk2 .ps3 .xmv .xen .vid .bika` + - Codecs: FFmpeg(various) +- **bkhd.c** + - Audiokinetic Wwise FX header [*WWISE_FX*] + - *bkhd*: `.bnk` + - Subfiles: *wwise_bnk bkhd_fx* + - *bkhd_fx*: `.wem .bnk` + - Codecs: PCMFLOAT +- **bmp_konami.c** + - Konami BMP header [*BMP_KONAMI*] + - *bmp_konami*: `.bin .lbin` + - Codecs: OKI4S +- **bnk_relic.c** + - Relic BNK header [*BNK_RELIC*] + - *bnk_relic*: `.bnk` + - Codecs: RELIC +- **bnk_sony.c** + - Sony BNK header [*BNK_SONY*] + - *bnk_sony*: `.bnk` + - Codecs: ATRAC9 PCM16BE PCM16LE PSX HEVAG +- **bnsf.c** + - Namco Bandai BNSF header [*BNSF*] + - *bnsf*: `.bnsf + .(external)` + - Codecs: G7221C G719 +- **brstm.c** + - Nintendo RSTM header [*RSTM*] + - *brstm*: `.brstm .brstmspm` + - Codecs: PCM8 PCM16BE NGC_DSP +- **bsf.c** + - (container) + - *bsf*: `.bsf` + - Subfiles: *ngc_dsp_std vag riff* +- **btsnd.c** + - Nintendo Wii U Menu Boot Sound [*WIIU_BTSND*] + - *btsnd*: `.btsnd` + - Codecs: PCM16BE +- **bwav.c** + - Nintendo BWAV header [*BWAV*] + - *bwav*: `.bwav` + - Subfiles: *opus_std* + - Codecs: PCM16LE NGC_DSP +- **bw_mp3_riff.c** + - (container) + - *bw_mp3_riff* + - Subfiles: *riff* + - *bw_riff_mp3* + - Subfiles: *mpeg* +- **caf.c** + - tri-Crescendo CAF Header [*CAF*] + - *caf*: `.caf .cfn .(extensionless)` + - Codecs: NGC_DSP +- **ck.c** + - Cricket Audio CKS header [*CKS*] + - Cricket Audio CKB header [*CKB*] + - *cks*: `.cks` + - *ckb*: `.ckb` + - Codecs: PCM16LE PCM8 MSADPCM_ck +- **compresswave.c** + - CompressWave .cwav header [*COMPRESSWAVE*] + - *compresswave*: `.cwav` + - Codecs: COMPRESSWAVE +- **cpk.c** + - (container) + - *cpk* + - Subfiles: *cpk_memory* + - *cpk_memory*: `.awb + .acb` + - Subfiles: *hca bcwav adx* +- **cps.c** + - tri-Crescendo CPS Header [*CPS*] + - *cps*: `.cps` + - Codecs: PCM16BE PSX +- **csb.c** + - CRI ADPCM_WII header [*UTF_DSP*] + - *csb*: `.csb` + - Subfiles: *aax utf_ahx utf_dsp* + - *utf_dsp*: `.aax .(extensionless)` + - *utf_ahx*: `.aax .(extensionless)` + - Subfiles: *ahx* + - Codecs: NGC_DSP +- **csmp.c** + - Retro Studios CSMP header [*CSMP*] + - *csmp*: `.csmp` + - Codecs: NGC_DSP +- **cstr.c** + - Namco Cstr header [*DSP_CSTR*] + - *cstr*: `.dsp` + - Codecs: NGC_DSP +- **cxs.c** + - tri-Crescendo CXS header [*CXS*] + - *cxs*: `.cxs` + - Codecs: XMA2 +- **dcs_wav.c** + - In Utero DCS+WAV header [*DCS_WAV*] + - *dcs_wav*: `.dcs + .wav` + - Codecs: AICA_int +- **dc_asd.c** + - ASD Header [*DC_ASD*] + - *dc_asd*: `.asd` + - Codecs: PCM16LE +- **dc_idvi.c** + - Capcom IDVI header [*DC_IDVI*] + - *dc_idvi*: `.dvi .idvi` + - Codecs: DVI_IMA_int +- **dc_kcey.c** + - Konami KCEY KCEYCOMP header [*DC_KCEY*] + - *dc_kcey*: `.pcm .kcey` + - Codecs: DVI_IMA +- **dc_str.c** + - Sega Stream Asset Builder header [*DC_STR*] + - variant of Sega Stream Asset Builder header [*DC_STR_V2*] + - *dc_str*: `.str` + - *dc_str_v2*: `.str` + - Codecs: AICA_int PCM16LE +- **dec.c** + - Falcom DEC RIFF header [*DEC*] + - *dec*: `.dec .de2 + .(external)` + - Codecs: MSADPCM +- **derf.c** + - Xilam DERF header [*DERF*] + - *derf*: `.adp` + - Codecs: DERF +- **diva.c** + - Sega DIVA header [*DIVA*] + - *diva*: `.diva` + - Codecs: DVI_IMA +- **dmsg_segh.c** + - (container) + - *dmsg*: `.sgt .dmsg` + - Subfiles: *riff* +- **dsb.c** + - (container) + - *dsb*: `.dsb` + - Subfiles: *bnsf* +- **dsf.c** + - Ocean DSF header [*DSF*] + - *dsf*: `.dsf` + - Codecs: DSA +- **ea_1snh.c** + - Electronic Arts EACS header [*EA_EACS*] + - Electronic Arts 1SNh header [*EA_1SNH*] + - *ea_1snh*: `.asf .lasf .sng .as4 .cnk .uv .tgq .tgv .(extensionless)` + - *ea_eacs*: `.eas .bnk .as4` + - Codecs: PCM8_int PCM16_int ULAW_int DVI_IMA PSX +- **ea_eaac.c** + - Electronic Arts SNR+SNS header [*EA_SNR_SNS*] + - Electronic Arts SPS header [*EA_SPS*] + - Electronic Arts SNU header [*EA_SNU*] + - *ea_snr_sns*: `.snr` + - *ea_sps*: `.sps` + - *ea_snu*: `.snu` + - *ea_abk_eaac*: `.abk + .ast` + - *ea_sbr*: `.sbr + .sbs` + - *ea_hdr_sth_dat*: `.hdr + .sth .dat .mus .(external)` + - *ea_mpf_mus_eaac*: `.mpf + .(external)` + - *ea_tmx*: `.tmx` + - Subfiles: *gin* + - *ea_sbr_harmony*: `.sbr + .sbs` + - *eaaudiocore_header*: `(base) + .sns` + - Codecs: PCM16_int EA_XAS_V1 MPEG NGC_DSP SPEEX ATRAC9 Opus XMA1 XMA2 +- **ea_schl.c** + - Electronic Arts BNK header [*EA_BNK*] + - Electronic Arts SCHl header (variable) [*EA_SCHL*] + - *ea_schl*: `.asf .lasf .str .chk .eam .exa .sng .aud .sx .xa .strm .stm .hab .xsf .gsf .(extensionless)` + - *ea_schl_video*: `.uv .dct .mad .wve .vp6` + - *ea_bnk*: `.bnk .sdt .hdt .ldt .abk .ast` + - *ea_abk*: `.abk + .ast` + - *ea_hdr_dat*: `.hdr + .dat` + - Subfiles: *vag* + - *ea_hdr_dat_v2*: `.hdr + .dat .mus .(external)` + - *ea_map_mus*: `.map .lin .mpf` + - *ea_mpf_mus*: `.mpf + .(external)` + - Codecs: EA_XA EA_XA_int EA_XA_V2 PCM8_int PCM16_int PCM8 PCM16LE PCM16BE PSX XBOX_IMA_int NGC_DSP VADPCM MPEG EA_MT ATRAC3 +- **ea_schl_fixed.c** + - Electronic Arts SCHl header (fixed) [*EA_SCHL_fixed*] + - *ea_schl_fixed*: `.asf .lasf .cnk` + - Codecs: PCM8 PCM16BE PCM16LE DVI_IMA PSX +- **ea_swvr.c** + - Electronic Arts SWVR header [*EA_SWVR*] + - *ea_swvr*: `.stream .str` + - Codecs: PSX NGC_DSP PCM8_U_int +- **ea_wve_ad10.c** + - Electronic Arts WVE (Ad10) header [*EA_WVE_AD10*] + - *ea_wve_ad10*: `.wve .mov` + - Codecs: PSX PCM8_U_int +- **ea_wve_au00.c** + - Electronic Arts WVE (au00) header [*EA_WVE_AU00*] + - *ea_wve_au00*: `.wve .fsv` + - Codecs: EA_XA_int PSX_cfg +- **ego_dic.c** + - Codemasters DIC1 header [*DIC1*] + - *ego_dic*: `.dic + .(external)` + - Codecs: PCM16LE ULAW XBOX_IMA OGG_VORBIS +- **encrypted.c** + - (container) + - *encrypted_ogg_tpf*: `.ogg .logg` + - Subfiles: *ogg_vorbis* + - *encrypted_mp3_tpf*: `.mp3` + - Subfiles: *ffmpeg* + - *encrypted_riff*: `.bgm .mse .koe` + - Subfiles: *riff* + - *encrypted_rpgmvo_riff*: `.rpgmvo` + - Subfiles: *riff* + - *encrypted_mc161*: `.mus` + - Subfiles: *ogg_vorbis* +- **esf.c** + - Eurocom ESF header [*ESF*] + - *esf*: `.esf` + - Codecs: DVI_IMA PCM8_U PCM16LE +- **exakt_sc.c** + - assumed Activision / EXAKT SC by extension [*EXAKT_SC*] + - *exakt_sc*: `.sc` + - Codecs: SASSC +- **excitebots.c** + - Excitebots .sfx header [*EB_SFX*] + - assumed Excitebots .sf0 by extension [*EB_SF0*] + - *eb_sfx*: `.sfx` + - *eb_sf0*: `.sf0` + - Codecs: PCM16BE NGC_DSP +- **exst.c** + - Sony EXST header [*EXST*] + - *exst*: `.sts .sts_cp3 .x + .int_cp3 .int` + - Codecs: PSX +- **ezw.c** + - EZ2DJ EZWAVE header [*EZW*] + - *ezw*: `.ezw` + - Codecs: PCM16LE +- **fag.c** + - Radical .FAG Header [*FAG*] + - *fag*: `.fag` + - Codecs: PSX +- **fda.c** + - Relic FDA header [*FDA*] + - *fda*: `.fda` + - Codecs: RELIC +- **ffdl.c** + - (container) + - *ffdl*: `.ogg .logg .mp4 .lmp4 .bin .(extensionless)` + - Subfiles: *ogg_vorbis mp4_aac_ffmpeg* +- **ffmpeg.c** + - FFmpeg supported format (check log) [*FFMPEG_faulty*] + - FFmpeg supported format [*FFMPEG*] + - *ffmpeg*: `.(any) .at3` + - Codecs: FFmpeg(various) +- **ffw.c** + - Freedom Fighters BGM header [*FFW*] + - *ffw*: `.ffw` + - Codecs: PCM16BE +- **flx.c** + - Ultima IX .FLX header [*PC_FLX*] + - *flx*: `.flx` + - Codecs: PCM16LE EA_XA EA_XA_int EA_MT +- **fsb.c** + - FMOD FSB1 header [*FSB1*] + - FMOD FSB2 header [*FSB2*] + - FMOD FSB3 header [*FSB3*] + - FMOD FSB4 header [*FSB4*] + - *fsb*: `.fsb .bnk .sfx .ps3 .xen` + - *fsb4_wav*: `.fsb .wii` + - Subfiles: *fsb* + - Codecs: MPEG XBOX_IMA FSB_IMA PSX XMA1 XMA2 NGC_DSP NGC_DSP_subint CELT_FSB PCM8_U PCM8 PCM16BE PCM16LE +- **fsb5.c** + - FMOD FSB5 header [*FSB5*] + - *fsb5*: `.fsb .snd` + - Codecs: PCM8_U PCM16BE PCM16LE PCMFLOAT NGC_DSP NGC_DSP_subint FSB_IMA XBOX_IMA PSX HEVAG XMA2 MPEG CELT_FSB ATRAC9 XWMA VORBIS_custom FADPCM Opus +- **fsb5_fev.c** + - (container) + - *fsb5_fev_bank*: `.bank` + - Subfiles: *fsb5 fsb_encrypted* +- **fsb_encrypted.c** + - (container) + - *fsb_encrypted*: `.fsb .ps3 .xen` + - Subfiles: *fsb fsb5* +- **fwse.c** + - MT Framework FWSE header [*FWSE*] + - *fwse*: `.fwse` + - Codecs: MTF_IMA +- **g1l.c** + - Koei Tecmo WiiBGM Header [*KT_WIIBGM*] + - *kt_g1l*: `.g1l` + - *kt_wiibgm_offset*: `.g1l .dsp` + - Codecs: NGC_DSP_subint +- **gca.c** + - GCA DSP Header [*GCA*] + - *gca*: `.gca` + - Codecs: NGC_DSP +- **gcsw.c** + - MileStone GCSW header [*GCSW*] + - *gcsw*: `.gcw` + - Codecs: PCM16BE +- **gcub.c** + - Sega GCub header [*GCUB*] + - *gcub*: `.wav .lwav .gcub` + - Codecs: NGC_DSP_subint NGC_DSP +- **ghs.c** + - Hexadrive GHS/S_P_STH header [*GHS*] + - *ghs*: `.gtd` + - *s_p_sth*: `.gtd` + - Subfiles: *msf* + - Codecs: XMA ATRAC9 +- **gin.c** + - Electronic Arts Gnsu header [*GIN*] + - *gin*: `.gin` + - Codecs: EA_XAS_V0 +- **gsp_gsb.c** + - Tecmo GSP+GSB Header [*GSP_GSB*] + - *gsp_gsb*: `.gsb + .gsp` + - Codecs: NGC_DSP ATRAC3 XMA +- **h4m.c** + - Hudson HVQM4 header [*H4M*] + - *h4m*: `.h4m .hvqm` + - Codecs: H4M_IMA +- **halpst.c** + - HAL Laboratory HALPST header [*HALPST*] + - *halpst*: `.hps` + - Codecs: NGC_DSP +- **hca.c** + - CRI HCA header [*HCA*] + - *hca* + - Subfiles: *hca_subkey* + - *hca_subkey*: `.hca` + - Codecs: CRI_HCA +- **hd3_bd3.c** + - Sony HD3+BD3 header [*HD3_BD3*] + - *hd3_bd3*: `.bd3 + .hd3` + - Codecs: PSX +- **his.c** + - Her Interactive HIS header [*HIS*] + - *his*: `.his` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG PCM8_U PCM16LE OGG_VORBIS +- **hxd.c** + - Tecmo HXD Header [*HXD*] + - *hxd*: `.hxd + .bd .str .at3` + - Codecs: PSX +- **idsp_ie.c** + - Inevitable Entertainment IDSP Header [*IDSP_IE*] + - *idsp_ie*: `.idsp` + - Codecs: NGC_DSP +- **idtech.c** + - id Software MZRT header [*MZRT*] + - id Software BSNF header [*BSNF*] + - *mzrt_v0*: `.idwav .idmsf .idxma` + - *mzrt_v1*: `.idmsf` + - *bsnf*: `.bsnd + .(external)` + - Codecs: PCM16LE MSADPCM XMA MPEG XMA2 OGG_VORBIS ATRAC9 +- **ifs.c** + - (container) + - *ifs*: `.ifs` + - Subfiles: *bmp_konami* +- **ikm.c** + - MiCROViSiON IKM header [*IKM*] + - *ikm_pc* + - Subfiles: *ogg_vorbis_config* + - *ikm_psp* + - Subfiles: *riff* + - *ikm*: `.ikm` + - Codecs: PSX OGG +- **ild.c** + - Tose ILD header [*ILD*] + - *ild*: `.ild` + - Codecs: PSX +- **ima.c** + - Blitz Games .IMA header [*IMA*] + - *ima*: `.ima` + - Codecs: BLITZ_IMA +- **imc.c** + - iNiS .IMC header [*IMC*] + - *imc*: `.imc` + - *imc_container*: `.imc` + - Subfiles: *imc* + - Codecs: PSX +- **imuse.c** + - LucasArts iMUSE header [*IMUSE*] + - *imuse*: `.imx .imc .wav .lwav` + - Codecs: IMUSE +- **ios_psnd.c** + - PSND Header [*IOS_PSND*] + - *ios_psnd*: `.psnd` + - Codecs: PCM16LE +- **isb.c** + - Creative ISACT header [*ISB*] + - *isb*: `.isb` + - Subfiles: *msf* + - Codecs: PCM8_U PCM16LE XBOX_IMA OGG_VORBIS XMA +- **ish_isd.c** + - ISH+ISD DSP Header [*ISH_ISD*] + - *ish_isd*: `.isd + .ish` + - Codecs: NGC_DSP +- **ivag.c** + - Namco IVAG header [*IVAG*] + - *ivag*: `.ivag` + - Codecs: PSX +- **ivaud.c** + - Rockstar .ivaud header [*IVAUD*] + - *ivaud*: `.ivaud .(extensionless)` + - Codecs: PCM16LE XMA1 MPEG IMA_int +- **ivb.c** + - IVB/BVII header [*PS2_IVB*] + - *ivb*: `.ivb` + - Codecs: PSX +- **jstm.c** + - JSTM Header [*PS2_JSTM*] + - *jstm*: `.stm .jstm` + - Codecs: PCM16LE +- **kat.c** + - Sega KAT header [*KAT*] + - *kat*: `.kat` + - Codecs: AICA_int PCM8 PCM16LE +- **kma9.c** + - Koei Tecmo KMA9 header [*KMA9*] + - *kma9*: `.km9` + - Codecs: ATRAC9 +- **knon.c** + - Paon KNON header [*KNON*] + - *knon*: `.str .asr` + - Codecs: NGC_DSP PCM16BE +- **kraw.c** + - Geometry Wars: Galaxies KRAW header [*KRAW*] + - *kraw*: `.kraw` + - Codecs: PCM16BE +- **ktac.c** + - Koei Tecmo KTAC header [*KTAC*] + - *ktac*: `.ktac` + - Codecs: MP4/AAC +- **ktsc.c** + - (container) + - *ktsc*: `.ktsl2asbin .asbin` + - Subfiles: *ktsr* +- **ktsr.c** + - Koei Tecmo KTSR header [*KTSR*] + - *ktsr*: `.ktsl2asbin .asbin` + - Subfiles: *riff ogg_vorbis ktss* + - Codecs: MSADPCM_int NGC_DSP ATRAC9 +- **ktss.c** + - Koei Tecmo KTSS header [*KTSS*] + - *ktss*: `.kns .kno .ktss` + - Codecs: NGC_DSP Opus +- **kwb.c** + - Koei Tecmo WaveBank header [*KWB*] + - *kwb*: `.wbd .wb2 .sed + .wbh .whd .wh2` + - *xws*: `.xws` + - *koei_wavebank* + - Subfiles: *msf dsp_apex* + - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 +- **lopu_fb.c** + - French-Bread LOPU header [*LOPU_FB*] + - *lopu_fb*: `.lopus` + - Codecs: Opus +- **lpcm_fb.c** + - French-Bread LPCM header [*LPCM_FB*] + - *lpcm_fb*: `.ladpcm` + - Codecs: NGC_DSP +- **lpcm_shade.c** + - Shade LPCM header [*LPCM_SHADE*] + - *lpcm_shade*: `.w .lpcm` + - Codecs: PCM16LE +- **lp_ap_lep.c** + - Konami LP/AP/LEP header [*LP_AP_LEP*] + - *lp_ap_lep*: `.bin .lbin .lp .lep .ap` + - Codecs: PCM16LE PSX +- **lrmd.c** + - Sony LRMD header [*LRMD*] + - *lrmd*: `.lrmb + .lrmh` + - Codecs: ATRAC3 +- **lsf.c** + - .lsf !n1nj4n header [*LSF_N1NJ4N*] + - *lsf_n1nj4n*: `.lsf` + - Codecs: LSF +- **mattel_hyperscan.c** + - Mattel Hyperscan KVAG [*HYPERSCAN_KVAG*] + - *hyperscan_kvag*: `.bvg` + - Codecs: DVI_IMA +- **maxis_xa.c** + - Maxis XA Header [*MAXIS_XA*] + - *maxis_xa*: `.xa` + - Codecs: MAXIS_XA +- **mc3.c** + - Paradigm MC3 header [*MC3*] + - *mc3*: `.mc3` + - Codecs: MC3 +- **mca.c** + - Capcom MCA header [*MCA*] + - *mca*: `.mca` + - Codecs: NGC_DSP +- **mib_mih.c** + - Sony MultiStream MIH+MIB header [*MIB_MIH*] + - *mib_mih*: `.mib + .mih` + - Codecs: PSX +- **mjb_mjh.c** + - Sony MultiStream MJH+MJB header [*MJB_MJH*] + - *mjb_mjh*: `.mjb + .mjh .mjb` + - Codecs: PSX +- **mn_str.c** + - Mini Ninjas 'STR' header [*MN_STR*] + - *mn_str*: `.mnstr` + - Codecs: PCM16LE +- **mogg.c** + - Harmonix Music Systems MOGG Vorbis [*MOGG*] + - *mogg*: `.mogg` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **mp4.c** + - MP4/AAC header [*MP4*] + - *mp4_aac_ffmpeg*: `.mp4 .m4a .m4v .lmp4 .bin .lbin .msd` + - Codecs: FFmpeg(various) +- **mpeg.c** + - MPEG header [*MPEG*] + - *mpeg*: `.mp3 .mp2 .lmp3 .lmp2 .mus` + - Codecs: MPEG +- **msb_msh.c** + - Sony MultiStream MSH+MSB header [*MSB_MSH*] + - *msb_msh*: `.msb + .msh` + - Codecs: PSX +- **msf.c** + - Sony MSF header [*MSF*] + - *msf*: `.msf .msa .at3 .mp3 .str` + - Codecs: PCM16BE PCM16LE PSX ATRAC3 FFmpeg(various) +- **msf_banpresto.c** + - (container) + - *msf_banpresto_wmsf*: `.msf` + - Subfiles: *msf* + - *msf_banpresto_2msf*: `.at9` + - Subfiles: *riff* +- **msf_konami.c** + - Konami MSF header [*MSF_KONAMI*] + - *msf_konami*: `.msf` + - Codecs: PSX +- **msf_tamasoft.c** + - Tama-Soft MSF header [*MSF_TAMASOFT*] + - *msf_tamasoft*: `.msf` + - Codecs: PCM16LE +- **mss.c** + - Guerilla MCSS header [*MSS*] + - *mss*: `.mss` + - Codecs: XBOX_IMA PSX +- **msv.c** + - Sony MultiStream MSV header [*MSV*] + - *msv*: `.msv .msvp` + - Codecs: PSX +- **mta2.c** + - Konami MTA2 header [*MTA2*] + - *mta2*: `.mta2` + - *mta2_container*: `.dbm .bgm .mta2` + - Subfiles: *mta2* + - Codecs: MTA2 +- **mtaf.c** + - Konami MTAF header [*MTAF*] + - *mtaf*: `.mtaf` + - Codecs: MTAF +- **mul.c** + - Crystal Dynamics .MUL header [*MUL*] + - *mul*: `.mul .emff` + - Subfiles: *fsb* + - Codecs: PSX NGC_DSP CD_IMA XMA1 +- **mups.c** + - (container) + - *mups*: `.mups .(extensionless)` + - Subfiles: *ogg_vorbis* +- **musc.c** + - Krome MUSC header [*MUSC*] + - *musc*: `.mus .musc` + - Codecs: PSX +- **musx.c** + - Eurocom MUSX header [*MUSX*] + - *musx*: `.sfx .musx` + - Codecs: PSX DAT4_IMA DVI_IMA_int XBOX_IMA NGC_DSP PCM16BE PCM16LE +- **mus_acm.c** + - InterPlay MUS ACM header [*MUS_ACM*] + - *mus_acm*: `.mus` + - Subfiles: *acm ogg_vorbis* +- **mus_vc.c** + - Vicious Cycle .MUS header [*MUS_VC*] + - *mus_vc*: `.mus` + - Codecs: NGC_DSP XBOX_IMA +- **myspd.c** + - Punchers Impact .MYSPD header [*MYSPD*] + - *myspd*: `.myspd` + - Codecs: IMA_int +- **naac.c** + - Namco NAAC header [*NAAC*] + - *naac*: `.naac` + - Codecs: AAC +- **naomi_adpcm.c** + - NAOMI/NAOMI2 Arcade games ADPCM header [*NAOMI_ADPCM*] + - *naomi_adpcm*: `.adpcm` + - Codecs: AICA_int +- **nds_hwas.c** + - Vicarious Visions HWAS header [*NDS_HWAS*] + - *nds_hwas*: `.hwas` + - Codecs: IMA_int +- **nds_rrds.c** + - Ridger Racer DS Header [*NDS_RRDS*] + - *nds_rrds*: `.(extensionless) .rrds` + - Codecs: IMA_int +- **nds_strm.c** + - Nintendo STRM header [*STRM*] + - *nds_strm*: `.strm` + - Codecs: PCM8 PCM16LE NDS_IMA +- **nds_strm_ffta2.c** + - Final Fantasy Tactics A2 RIFF Header [*NDS_STRM_FFTA2*] + - *nds_strm_ffta2*: `.bin .strm` + - Codecs: FFTA2_IMA +- **ngc_adpdtk.c** + - Nintendo DTK raw header [*DTK*] + - *dtk*: `.dtk .adp .trk .wav .lwav` + - Codecs: NGC_DTK +- **ngc_dsp_konami.c** + - Konami DSP header [*NGC_DSP_KONAMI*] + - *ngc_dsp_konami*: `.dsp` + - Codecs: NGC_DSP +- **ngc_dsp_mpds.c** + - MPDS DSP header [*NGC_DSP_MPDS*] + - *ngc_dsp_mpds*: `.dsp .mds` + - Codecs: NGC_DSP +- **ngc_dsp_std.c** + - Nintendo DSP header [*DSP_STD*] + - Intelligent Systems STM header [*DSP_STM*] + - Single DSP header stereo by .mpdsp extension [*DSP_MPDSP*] + - Double DSP header stereo by _lr.dsp extension [*DSP_JETTERS*] + - Double DSP header stereo by .mss extension [*DSP_MSS*] + - Double DSP header stereo by .gcm extension [*DSP_GCM*] + - Namco IDSP header [*IDSP_NAMCO*] + - Procyon Studio SADB header [*DSP_SADB*] + - Traveller's Tales IDSP header [*IDSP_TT*] + - Next Level IDSP header [*IDSP_NL*] + - .WSD header [*DSP_WII_WSD*] + - .DDSP header [*DSP_DDSP*] + - Sumo Digital iSWS header [*WII_WAS*] + - Infogrames .DSP header [*DSP_STR_IG*] + - XIII dsp header [*DSP_XIII*] + - Icon Games NDP header [*WII_NDP*] + - Cabelas games .DSP header [*DSP_CABELAS*] + - Acclaim Austin AAAp DSP header [*NGC_DSP_AAAP*] + - Capcom DSPW header [*DSP_DSPW*] + - IADP Header [*NGC_DSP_IADP*] + - Bethesda .mcadpcm header [*DSP_MCADPCM*] + - UE4 Switch Audio header [*DSP_SWITCH_AUDIO*] + - .VAG DSP header [*DSP_VAG*] + - .ITL DSP header [*DSP_ITL*] + - AQUASTYLE ADPY header [*DSP_ADPY*] + - AQUASTYLE ADPX header [*DSP_ADPX*] + - LucasArts .DS2 header [*DSP_DS2*] + - Infernal .ITL DSP header [*DSP_ITL_i*] + - Square Enix DSP header [*DSP_SQEX*] + - Koei Tecmo WiiVoice header [*DSP_WIIVOICE*] + - Exient WIIADPCM header [*DSP_WIIADPCM*] + - CRI CWAC header [*DSP_CWAC*] + - TOSE .IDSP header [*IDSP_TOSE*] + - Kuju London .KWA header [*DSP_KWA*] + - Koei Tecmo APEX header [*DSP_APEX*] + - *ngc_dsp_std*: `.dsp .adp .(extensionless)` + - *ngc_dsp_std_le*: `.adpcm` + - *ngc_mdsp_std*: `.dsp .mdsp` + - *ngc_dsp_stm*: `.stm .lstm .dsp` + - *ngc_mpdsp*: `.mpdsp .ste` + - *ngc_dsp_std_int*: `.dsp .mss .gcm` + - *idsp_namco*: `.idsp` + - *sadb*: `.sad` + - *idsp_tt*: `.gcm .idsp .wua` + - *idsp_nl*: `.idsp` + - *wii_wsd*: `.wsd` + - *dsp_ddsp*: `.adp .ddsp .wav .lwav` + - *wii_was*: `.was .dsp .isws` + - *dsp_str_ig*: `.str` + - *dsp_xiii*: `.dsp` + - *dsp_ndp*: `.nds .ndp` + - *dsp_cabelas*: `.dsp` + - *ngc_dsp_aaap*: `.dsp` + - *dsp_dspw*: `.dspw` + - *ngc_dsp_iadp*: `.adp .iadp` + - *dsp_mcadpcm*: `.mcadpcm` + - *dsp_switch_audio*: `.switch_audio .dsp` + - *dsp_sps_n1*: `.vag .nlsd` + - *dsp_itl_ch*: `.itl` + - *dsp_adpy*: `.adpcmx` + - *dsp_adpx*: `.adpcmx` + - *dsp_ds2*: `.ds2 .dsp` + - *dsp_itl*: `.itl .dsp` + - *dsp_sqex*: `.wav .lwav` + - *dsp_wiivoice*: `.dsp` + - *dsp_wiiadpcm*: `.adpcm` + - *dsp_cwac*: `.dsp` + - *idsp_tose*: `.idsp` + - *dsp_kwa*: `.kwa` + - *dsp_apex*: `.dsp` + - Codecs: NGC_DSP NGC_DSP_subint +- **ngc_dsp_ygo.c** + - Konami custom DSP Header [*DSP_YGO*] + - *dsp_ygo*: `.dsp` + - Codecs: NGC_DSP +- **ngc_ffcc_str.c** + - Final Fantasy: Crystal Chronicles STR header [*FFCC_STR*] + - *ngc_ffcc_str*: `.str` + - Codecs: NGC_DSP +- **ngc_lps.c** + - Rave Master LPS Header [*NGC_LPS*] + - *ngc_lps*: `.lps` + - Codecs: NGC_DSP +- **ngc_nst_dsp.c** + - Animaniacs NST header [*NGC_NST_DSP*] + - *ngc_nst_dsp*: `.dsp` + - Codecs: NGC_DSP +- **ngc_pdt.c** + - Hudson .PDT header [*NGC_PDT*] + - *ngc_pdt*: `.pdt` + - *ngc_pdt_split*: `.pdt` + - Codecs: NGC_DSP +- **ngc_sck_dsp.c** + - The Scorpion King SCK Header [*NGC_SCK_DSP*] + - *ngc_sck_dsp*: `.dsp + .sck` + - Codecs: NGC_DSP +- **ngc_ssm.c** + - SSM DSP Header [*NGC_SSM*] + - *ngc_ssm*: `.ssm` + - Codecs: NGC_DSP +- **ngc_str_cauldron.c** + - Cauldron .STR header [*DSP_STR*] + - *ngc_str*: `.str` + - Codecs: NGC_DSP +- **ngc_tydsp.c** + - .tydsp Header [*NGC_TYDSP*] + - *ngc_tydsp*: `.tydsp` + - Codecs: NGC_DSP +- **nps.c** + - Namco NPSF header [*NPS*] + - *nps*: `.nps .npsf` + - Codecs: PSX +- **nub.c** + - Namco NUB header [*NUB*] + - *nub*: `.nub .nub2 + .(external)` + - Subfiles: *nub_xma nub_wav nub_vag nub_at3 nub_dsp nub_idsp nub_is14 function* + - *nub_wav*: `.wav .lwav` + - *nub_vag*: `.vag` + - *nub_at3*: `.at3` + - Subfiles: *riff* + - *nub_xma*: `.xma` + - *nub_dsp*: `.dsp` + - Subfiles: *ngc_dsp_std* + - *nub_idsp*: `.idsp` + - Subfiles: *idsp_namco* + - *nub_is14*: `.is14` + - Subfiles: *bnsf* + - Codecs: PCM16BE PSX XMA +- **nus3audio.c** + - (container) + - *nus3audio*: `.nus3audio` + - Subfiles: *idsp_namco opus_nus3 riff bnsf* +- **nus3bank.c** + - (container) + - *nus3bank*: `.nub2 .nus3bank` + - Subfiles: *idsp_namco opus_nus3 riff bnsf ivag xma nus3bank_encrypted* + - *nus3bank_encrypted*: `.nus3bank .xma` + - Subfiles: *xma* +- **nwa.c** + - VisualArt's NWA header (NWAINFO.INI looping) [*NWA_NWAINFOINI*] + - VisualArt's NWA header (Gameexe.ini looping) [*NWA_GAMEEXEINI*] + - VisualArt's NWA header [*NWA*] + - *nwa*: `.nwa + .(external)` + - Codecs: PCM8 PCM16LE NWA +- **nwav.c** + - Chunsoft NWAV header [*NWAV*] + - *nwav*: `.nwav .(extensionless)` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **nxa.c** + - Entergram NXA header [*NXA*] + - *opus_nxa*: `.nxa` + - Codecs: Opus +- **nxap.c** + - Nex NXAP header [*NXAP*] + - *nxap*: `.adp` + - Codecs: NXAP +- **ogg_opus.c** + - Ogg Opus header [*OGG_OPUS*] + - *ogg_opus*: `.opus .lopus .ogg .logg .bgm` + - Codecs: FFmpeg(various) +- **ogg_vorbis.c** + - Ogg Vorbis header (encrypted) [*OGG_encrypted*] + - Ogg Vorbis header [*OGG_VORBIS*] + - Ogg Vorbis header (KOVS) [*OGG_KOVS*] + - *ogg_vorbis* + - Subfiles: *ogg_vorbis* + - *ogg_vorbis_config*: `.ogg .logg .adx .rof .acm .sod .msa .bin .lbin .kvs .kovs .rpgmvo .ogg_ .bgm .gwm .mus .isd .sngw .lse .eno .um3 .u0 + .(external)` + - Subfiles: *ogg_vorbis_config ogg_vorbis_cfg_ovmi ogg_vorbis_tests ogg_vorbis_common ogg_vorbis_tink ogg_vorbis* + - Codecs: OGG OGG_VORBIS +- **ogl.c** + - Shin'en OGL header [*OGL*] + - *ogl*: `.ogl` + - Codecs: VORBIS_custom +- **ogv_3rdeye.c** + - 3rdEye .OGV header [*OGV_3RDEYE*] + - *ogv_3rdeye*: `.ogv` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **omu.c** + - Outrage OMU Header [*OMU*] + - *omu*: `.omu` + - Codecs: PCM16LE +- **opus.c** + - Nintendo Switch OPUS header [*OPUS*] + - *opus_std*: `.opus .lopus .bgm .opu + .psi` + - *opus_n1*: `.opus .lopus` + - *opus_capcom*: `.opus .lopus` + - *opus_nop*: `.nop` + - *opus_shinen*: `.opus .lopus` + - *opus_nus3*: `.opus .lopus` + - *opus_sps_n1*: `.sps .nlsd .at9 .opus .lopus` + - *opus_opusx*: `.opusx` + - *opus_prototype*: `.opus .lopus` + - *opus_opusnx*: `.opus .lopus` + - *opus_nsopus*: `.nsopus` + - *opus_sqex*: `.wav .lwav` + - *opus_rsnd*: `.rsnd` + - Codecs: Opus +- **otm.c** + - Otomedius OTM Header [*OTM*] + - *otm*: `.otm` + - Codecs: PCM16LE +- **p3d.c** + - Radical P3D header [*P3D*] + - *p3d*: `.p3d` + - Codecs: RAD_IMA_mono MPEG XMA +- **pasx.c** + - Premium Agency PASX header [*PASX*] + - *pasx*: `.past .sgb` + - Codecs: XMA +- **pcm_sre.c** + - Capcom .PCM+SRE header [*PCM_SRE*] + - *pcm_sre*: `.pcm + .sre` + - Codecs: PSX +- **pcm_success.c** + - Success PCM header [*PCM_SUCCESS*] + - *pcm_success*: `.pcm` + - Codecs: PSX +- **pc_ast.c** + - Capcom AST (PC) header [*PC_AST*] + - *pc_ast*: `.ast` + - Codecs: PCM16LE +- **pc_mxst.c** + - Lego Island MxSt Header [*PC_MXST*] + - *pc_mxst*: `.mxst` + - Codecs: PCM8_U PCM16LE +- **piff_tpcm.c** + - Tantalus PIFF TPCM header [*PIFF_TPCM*] + - *piff_tpcm*: `.tad` + - Codecs: TANTALUS +- **pona.c** + - Policenauts BGM header [*PONA_3DO*] + - Policenauts BGM header [*PONA_PSX*] + - *pona_3do*: `.pona .sxd` + - *pona_psx*: `.pona` + - Codecs: SDX2 PSX +- **pos.c** + - RIFF WAVE header and .pos for looping [*RIFF_WAVE_POS*] + - *pos*: `.pos + .wav` + - Subfiles: *riff* +- **ppst.c** + - Parappa PPST header [*PPST*] + - *ppst*: `.sng` + - Subfiles: *riff* +- **ps2_2pfs.c** + - Konami 2PFS header [*PS2_2PFS*] + - *ps2_2pfs*: `.sap .2pfs` + - Codecs: PSX +- **ps2_adm.c** + - Dragon Quest V .ADM raw header [*PS2_ADM*] + - *ps2_adm*: `.adm + .(external)` + - Codecs: PSX +- **ps2_ass.c** + - SystemSoft .ASS header [*PS2_ASS*] + - *ps2_ass*: `.ass` + - Codecs: PSX +- **ps2_b1s.c** + - B1S header [*PS2_B1S*] + - *ps2_b1s*: `.b1s` + - Codecs: PSX +- **ps2_bg00.c** + - Falcom BG00 Header [*BG00*] + - *bg00*: `.bg00` + - Codecs: PSX +- **ps2_bmdx.c** + - Beatmania .bmdx header [*PS2_BMDX*] + - *ps2_bmdx*: `.bmdx` + - Codecs: PSX +- **ps2_filp.c** + - Bio Hazard - Gun Survivor FILp Header [*FILP*] + - *filp*: `.filp` + - Codecs: PSX +- **ps2_gbts.c** + - Pop'n'Music 9 Header [*PS2_GBTS*] + - *ps2_gbts*: `.gbts` + - Codecs: PSX +- **ps2_gcm.c** + - Namco GCM header [*PS2_GCM*] + - *ps2_gcm*: `.gcm` + - Codecs: PSX +- **ps2_hgc1.c** + - Knights of the Temple 2 hgC1 Header [*HGC1*] + - *hgc1*: `.hgc1` + - Codecs: PSX +- **ps2_hsf.c** + - Lowrider 'HSF' header [*PS2_HSF*] + - *ps2_hsf*: `.hsf` + - Codecs: PSX +- **ps2_iab.c** + - Runtime .IAB header [*PS2_IAB*] + - *ps2_iab*: `.iab` + - Codecs: PSX +- **ps2_joe.c** + - Asobo Studio .JOE header [*PS2_JOE*] + - *ps2_joe*: `.joe` + - Codecs: PSX +- **ps2_kces.c** + - Konami KCES Header [*PS2_KCES*] + - *ps2_kces*: `.kces` + - Codecs: PSX +- **ps2_mcg.c** + - Gunvari MCG Header [*PS2_MCG*] + - *ps2_mcg*: `.mcg` + - Codecs: PSX +- **ps2_mic.c** + - KOEI .MIC header [*PS2_MIC*] + - *mic_koei*: `.mic` + - Codecs: PSX +- **ps2_mihb.c** + - Sony MultiStream MIC header [*PS2_MIHB*] + - *ps2_mihb*: `.mic .mihb` + - Codecs: PSX +- **ps2_msa.c** + - Success .MSA header [*PS2_MSA*] + - *ps2_msa*: `.msa` + - Codecs: PSX +- **ps2_p2bt.c** + - Pop'n'Music 7 Header [*PS2_P2BT*] + - *ps2_p2bt*: `.p2bt` + - Codecs: PSX +- **ps2_pcm.c** + - Konami KCEJ East .PCM header [*PS2_PCM*] + - *ps2_pcm*: `.pcm` + - Codecs: PCM16LE +- **ps2_rnd.c** + - Knights of the Temple 2 hgC1 Header [*HGC1*] + - *ps2_rnd*: `.rnd` + - Codecs: PSX +- **ps2_sl3.c** + - Atari Melbourne House SL3 header [*SL3*] + - *sl3*: `.ms .sl3` + - Codecs: PSX +- **ps2_snd.c** + - Might and Magic SSND Header [*PS2_SND*] + - *ps2_snd*: `.snd` + - Codecs: DVI_IMA_int PCM16LE +- **ps2_sps.c** + - Ape Escape 2 SPS Header [*PS2_SPS*] + - *ps2_sps*: `.sps` + - Codecs: PCM16LE +- **ps2_va3.c** + - Konami VA3 header [*VA3*] + - *va3*: `.va3` + - Codecs: ATRAC3 +- **ps2_vas.c** + - Konami .VAS header [*PS2_VAS*] + - *ps2_vas*: `.vas` + - *ps2_vas_container*: `.vas` + - Subfiles: *ps2_vas* + - Codecs: PSX +- **ps2_vbk.c** + - PS2 VBK Header [*PS2_VBK*] + - *ps2_vbk*: `.vbk` + - Codecs: PSX +- **ps2_vds_vdm.c** + - Procyon Studio VDS/VDM header [*PS2_VDS_VDM*] + - *ps2_vds_vdm*: `.vds .vdm` + - Codecs: PSX +- **ps2_vgv.c** + - Rune: Viking Warlord VGV Header [*PS2_VGV*] + - *ps2_vgv*: `.vgv` + - Codecs: PSX +- **ps2_vms.c** + - VMS Header [*PS2_VMS*] + - *ps2_vms*: `.vms` + - Codecs: PSX +- **ps2_wad.c** + - WAD header [*PS2_WAD*] + - *ps2_wad*: `.wad` + - Codecs: PSX +- **ps2_wb.c** + - Shooting Love. ~TRIZEAL~ WB header [*PS2_WB*] + - *ps2_wb*: `.wb` + - Codecs: PCM16LE +- **ps2_wmus.c** + - assumed The Warriors Sony ADPCM by .wmus extension [*PS2_WMUS*] + - *ps2_wmus*: `.wmus` + - Codecs: PSX +- **ps2_xa30.c** + - Reflections XA30 PS2 header [*PS2_XA30*] + - *ps2_xa30*: `.xa .xa30` + - Codecs: PSX +- **ps3_past.c** + - SNDP header [*PS3_PAST*] + - *ps3_past*: `.past` + - Codecs: PCM16LE +- **psb.c** + - M2 PSB header [*PSB*] + - *psb*: `.psb` + - Subfiles: *riff vag* + - Codecs: PCM16LE PCM24LE MSADPCM XWMA XMA NGC_DSP Opus +- **psf.c** + - Pivotal PSF header [*PSF*] + - *psf_single*: `.psf .swd` + - *psf_segmented*: `.psf .swd` + - Subfiles: *psf_single* + - *psf_pfsm*: `.psf` + - *sch*: `.sch + .(external)` + - Subfiles: *psf_segmented psf_single* + - Codecs: PSX PSX_pivotal NGC_DSP PCM16BE +- **pwb.c** + - Double Fine WB header [*PWB*] + - *pwb*: `.pwb` + - Codecs: PSX +- **rad.c** + - Traveller's Tales .RAD header [*RAD*] + - *rad*: `.rad` + - Codecs: PCM16LE +- **raw_int.c** + - PS2 .int raw header [*RAW_INT*] + - *raw_int*: `.int .wp2` + - Codecs: PCM16LE +- **raw_pcm.c** + - PC .raw raw header [*RAW_PCM*] + - *raw_pcm*: `.raw` + - Codecs: PCM16LE +- **raw_rsf.c** + - Retro Studios .RSF raw header [*RSF*] + - *raw_rsf*: `.rsf` + - Codecs: G721 +- **raw_s14_sss.c** + - Namco .S14 raw header [*S14*] + - Namco .SSS raw header [*SSS*] + - *raw_s14_sss*: `.sss .s14` + - Codecs: G7221C +- **raw_snds.c** + - PC .snds raw header [*RAW_SNDS*] + - *raw_snds*: `.snds` + - Codecs: SNDS_IMA +- **raw_wavm.c** + - Xbox .wavm raw header [*RAW_WAVM*] + - *raw_wavm*: `.wavm` + - Codecs: XBOX_IMA +- **redspark.c** + - RedSpark Header [*REDSPARK*] + - Codecs: NGC_DSP +- **rfrm.c** + - Retro Studios RFRM header [*RFRM*] + - *rfrm_mpr*: `.csmp` + - *rfrm*: `.csmp` + - Codecs: NGC_DSP +- **riff.c** + - RIFF WAVE header [*RIFF_WAVE*] + - RIFF WAVE header with loop markers [*RIFF_WAVE_labl*] + - RIFF WAVE header with sample looping info [*RIFF_WAVE_smpl*] + - RIFF WAVE header with wsmp looping info [*RIFF_WAVE_wsmp*] + - RIFF WAVE header with .mwv flavoring [*RIFF_WAVE_MWV*] + - RIFX WAVE header [*RIFX_WAVE*] + - RIFX WAVE header with sample looping info [*RIFX_WAVE_smpl*] + - *riff*: `.wav .lwav .xwav .mwv .da .dax .cd .med .snd .adx .adp .xss .xsew .adpcm .adw .wd .(extensionless) .sbv .wvx .str .at3 .rws .aud .at9 .ckd .saf .ima .nsa .pcm .xvag .ogg .logg .p1d .xms .mus .dat .ldat` + - *rifx*: `.wav .lwav` + - Codecs: AICA_int PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int +- **rkv.c** + - Legacy of Kain - Blood Omen 2 RKV PS2 header [*PS2_RKV*] + - Legacy of Kain - Blood Omen 2 RKV GC header [*NGC_RKV*] + - *ps2_rkv*: `.rkv` + - *ngc_rkv*: `.(extensionless) .rkv .bo2` + - Codecs: PSX NGC_DSP +- **rs03.c** + - Retro Studios RS03 header [*DSP_RS03*] + - *rs03*: `.dsp` + - Codecs: NGC_DSP +- **rsd.c** + - Radical RSD header [*RSD*] + - *rsd*: `.rsd .rsp` + - Subfiles: *ogg_vorbis_config* + - Codecs: PCM16LE PCM16BE PSX XBOX_IMA_mch XBOX_IMA NGC_DSP NGC_DSP_subint RAD_IMA OGG FFmpeg(various) ATRAC3 XMA +- **rstm_rockstar.c** + - Rockstar Games RSTM Header [*RSTM_ROCKSTAR*] + - *rstm_rockstar*: `.rsm .rstm` + - Codecs: PSX +- **rwax.c** + - Konami RWAX header [*RWAX*] + - *rwax*: `.rwx` + - Codecs: PCM16LE +- **rws.c** + - RenderWare RWS header [*RWS*] + - *rws*: `.rws` + - Codecs: PCM16_int PCM16BE PCM16LE PSX NGC_DSP XBOX_IMA +- **rwsd.c** + - Nintendo RWSD header (single stream) [*RWSD*] + - *rwsd*: `.brwsd .rwsd` + - Codecs: PCM8 PCM16BE NGC_DSP +- **rws_mono.c** + - RenderWare RWS header [*RWS*] + - *rws_mono*: `.rws` + - Codecs: PSX PCM16BE PCM16LE +- **rxws.c** + - Sony RXWS header [*RXWS*] + - *rxws*: `.xwb .xws + .xwh .xwb` + - Codecs: PSX PCM16LE ATRAC3 +- **s3v.c** + - Konami S3V header [*S3V*] + - *s3v*: `.s3v` + - Codecs: FFmpeg(various) +- **sab.c** + - Sensaura SAB header [*SAB*] + - *sab*: `.sab + .sob` + - Codecs: PCM16LE PSX XBOX_IMA +- **sadf.c** + - Procyon Studio SADF header [*SADF*] + - *sadf*: `.sad .nop .(extensionless)` + - Codecs: NGC_DSP +- **sadl.c** + - Procyon Studio SADL header [*SADL*] + - *sadl*: `.sad` + - Codecs: IMA_int NDS_PROCYON +- **sat_baka.c** + - Konami BAKA header [*SAT_BAKA*] + - *sat_baka*: `.(extensionless) .baka` + - Codecs: PCM16BE +- **sat_dvi.c** + - Konami KCEN DVI. header [*SAT_DVI*] + - *sat_dvi*: `.pcm .dvi` + - Codecs: DVI_IMA_int +- **sat_sap.c** + - VING .SAP header [*SAP*] + - *sat_sap*: `.sap` + - Codecs: PCM16BE +- **sbk.c** + - Team17 SBK header [*SBK*] + - *sbk*: `.sbk` + - Codecs: PCM8_U PCM16LE MS_IMA +- **scd_pcm.c** + - Lunar: Eternal Blue .PCM header [*SCD_PCM*] + - *scd_pcm*: `.pcm` + - Codecs: PCM8_SB +- **sd9.c** + - beatmania IIDX SD9 header [*SD9*] + - *sd9*: `.sd9` + - Codecs: MSADPCM +- **sdf.c** + - Beyond Reality SDF header [*SDF*] + - *sdf*: `.sdf` + - Codecs: PCM16LE PSX NGC_DSP +- **sdrh.c** + - feelplus SDRH header [*SDRH*] + - *sdrh_new*: `.xse` + - *sdrh_old*: `.xse` + - Codecs: PSX MPEG XMA2 ATRAC3 XMA1 +- **sdt.c** + - High Voltage .sdt header [*SDT*] + - *sdt*: `.sdt` + - Codecs: NGC_DSP +- **seb.c** + - Game Arts .SEB header [*SEB*] + - *seb*: `.seb .gms .(extensionless)` + - Codecs: PSX +- **seg.c** + - Stormfront SEG header [*SEG*] + - *seg*: `.seg` + - Codecs: PSX XBOX_IMA NGC_DSP IMA XMA2 +- **sfh.c** + - (container) + - *sfh*: `.at3 .sspr` + - Subfiles: *riff sspr* +- **sfl.c** + - Ogg Vorbis header (SFPL looping) [*OGG_SFL*] + - *sfl_ogg*: `.sfl .ogg + .(external) .ogg` + - Subfiles: *ogg_vorbis* +- **sgxd.c** + - Sony SGXD header [*SGXD*] + - *sgxd*: `.sgb .sgx .sgd + .sgh .sgb` + - Codecs: PCM16BE OGG_VORBIS PSX ATRAC3 PSX_cfg FFmpeg(various) +- **sk_aud.c** + - Silicon Knights AUD header [*SK_AUD*] + - *sk_aud*: `.aud` + - Codecs: VORBIS_custom +- **sli.c** + - (container) + - *sli_loops*: `.sli + .(external)` + - Subfiles: *ogg_opus ogg_vorbis riff* +- **smc_smh.c** + - Genki SMC+SMH header [*SMC_SMH*] + - *smc_smh*: `.smc + .smh` + - Codecs: PSX +- **smk.c** + - RAD Game Tools SMACKER header [*SMACKER*] + - *smk*: `.smk` + - Codecs: FFmpeg(various) +- **smp.c** + - Infernal Engine .smp header [*SMP*] + - *smp*: `.smp .snb` + - Codecs: ATRAC3 NGC_DSP MSADPCM PSX XMA2 +- **smpl.c** + - Skonec SMPL header [*SMPL*] + - *smpl*: `.v0 .v1` + - Codecs: PSX +- **smv.c** + - extreme .SMV header [*SMV*] + - *smv*: `.smv` + - Codecs: PSX +- **sndz.c** + - Sony SNDZ header [*SNDZ*] + - *sndz*: `.szd1 .szd .szd3 + .szd2` + - Codecs: PCM16LE PCM24LE PCMFLOAT HEVAG ATRAC9 +- **spm.c** + - Square SPM header [*SPM*] + - *spm*: `.spm` + - Codecs: PCM16LE +- **spsd.c** + - Sega Naomi SPSD header [*SPSD*] + - *spsd*: `.str .spsd` + - Codecs: PCM16LE PCM8 AICA_int +- **sps_n1.c** + - Nippon Ichi .SPS header [*SPS_N1*] + - *sps_n1*: `.sps` + - Subfiles: *vag riff* + - *sps_n1_segmented*: `.at9 .nlsd` + - Subfiles: *ogg_vorbis opus_std* +- **spt_spd.c** + - SPT+SPD DSP Header [*SPT_SPD*] + - *spt_spd*: `.spd + .spt` + - Codecs: NGC_DSP PCM16BE +- **sqex_scd.c** + - Square Enix SCD header [*SQEX_SCD*] + - *sqex_scd*: `.scd` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG PCM16LE PSX MPEG MSADPCM NGC_DSP XMA ATRAC3 ATRAC9 +- **sqex_sead.c** + - Square Enix SAB header [*SQEX_SAB*] + - Square Enix MAB header [*SQEX_MAB*] + - *sqex_sead*: `.sab .mab .sbin` + - Subfiles: *ogg_vorbis_config hca* + - Codecs: PCM16LE MSADPCM OGG ATRAC9 MPEG +- **sscf.c** + - Square Enix SSCF header [*SSCF*] + - *sscf*: `.scd` + - Codecs: PSX +- **sscf_encrypted.c** + - (container) + - *sscf_encrypted*: `.scd` + - Subfiles: *xma* +- **sspf.c** + - Konami SSPF header [*SSPF*] + - *sspf*: `.ssp` + - Codecs: PCM16BE MTA2 +- **sspr.c** + - (container) + - *sspr*: `.sspr` + - Subfiles: *riff* +- **ster.c** + - ALCHEMY STER header [*STER*] + - *ster*: `.ster .sfs` + - Codecs: PSX +- **sthd.c** + - Dream Factory STHD header [*STHD*] + - *sthd*: `.stx` + - Codecs: XBOX_IMA_int +- **stm.c** + - Angel Studios/Rockstar San Diego STMA header [*STM*] + - *stm*: `.stm .lstm` + - Codecs: NGC_DSP DVI_IMA_int PCM16BE PCM16LE +- **strm_abylight.c** + - Abylight STRM header [*STRM_ABYLIGHT*] + - *strm_abylight*: `.strm` + - Codecs: AAC +- **str_snds.c** + - 3DO SNDS header [*STR_SNDS*] + - *str_snds*: `.str .stream .3do` + - Codecs: SDX2_int SDX2 CBD2_int CBD2 +- **str_wav.c** + - Blitz Games .STR+WAV header [*STR_WAV*] + - *str_wav*: `.str .data .wav .wma .(extensionless) + .(external) .wav .sth` + - Codecs: PSX NGC_DSP XBOX_IMA BLITZ_IMA FFmpeg(various) XMA2 +- **sts.c** + - Alfa System .STS header [*STS*] + - *sts*: `.sts` + - Codecs: NGC_DSP +- **svag_kcet.c** + - Konami SVAG header [*SVAG_KCET*] + - *svag_kcet*: `.svag` + - Codecs: PSX +- **svag_snk.c** + - SNK SVAG header [*SVAG_SNK*] + - *svag_snk*: `.svag` + - Codecs: PSX +- **svg.c** + - High Voltage SVG header [*SVG*] + - *svg*: `.svg` + - Codecs: PSX +- **svs.c** + - Square SVS header [*SVS*] + - *svs*: `.svs` + - Codecs: PSX +- **swav.c** + - Nintendo SWAV header [*SWAV*] + - *swav*: `.swav .adpcm` + - Codecs: PCM8 PCM16LE IMA_int +- **sxd.c** + - Sony SXD header [*SXD*] + - *sxd*: `.sxd .sxd2 .sxd3 + .sxd1` + - Codecs: PSX HEVAG ATRAC9 +- **tac.c** + - tri-Ace Codec header [*TAC*] + - *tac*: `.(extensionless) .aac .laac` + - Codecs: TAC +- **tgc.c** + - Tiger Game.com .4 header [*TGC*] + - *tgc*: `.4` + - Codecs: TGC +- **thp.c** + - Nintendo THP header [*THP*] + - *thp*: `.thp .dsp .mov .(extensionless)` + - Codecs: NGC_DSP +- **tt_ad.c** + - Traveller's Tales AUDIO_DATA header [*TT_AD*] + - *tt_ad*: `.audio_data` + - Codecs: OGG_VORBIS MS_IMA_mono +- **ubi_bao.c** + - Ubisoft BAO header [*UBI_BAO*] + - *ubi_bao_pk*: `.pk .lpk .cpk` + - *ubi_bao_atomic*: `.bao .(extensionless)` + - *ubi_bao_spk*: `.spk` + - *ubi_bao_header*: `(base) + .(external)` + - Codecs: UBI_IMA PCM16LE PSX NGC_DSP XMA ATRAC3 OGG_VORBIS +- **ubi_ckd.c** + - Ubisoft CKD RIFF header [*UBI_CKD*] + - *ubi_ckd*: `.ckd` + - Codecs: NGC_DSP MSADPCM XMA +- **ubi_ckd_cwav.c** + - (container) + - *ubi_ckd_cwav*: `.wav .lwav` + - Subfiles: *bcwav* +- **ubi_hx.c** + - Ubisoft HXx header [*UBI_HX*] + - *ubi_hx*: `.hxd .hxc .hx2 .hxg .hxx .hx3 + .bnh .(external)` + - Codecs: PCM16BE PCM16LE UBI_ADPCM PSX NGC_DSP XBOX_IMA XMA2 ATRAC3 MPEG +- **ubi_jade.c** + - Ubisoft Jade RIFF header [*UBI_JADE*] + - *ubi_jade*: `.waa .wac .wad .wam .wav .lwav` + - Subfiles: *msf* + - *ubi_jade_container*: `.waa .wac .wad .wam .wav .lwav .xma` + - Subfiles: *xma ubi_jade* + - Codecs: XBOX_IMA PSX NGC_DSP MSADPCM +- **ubi_lyn.c** + - Ubisoft LyN RIFF header [*UBI_LYN*] + - *ubi_lyn*: `.sns .wav .lwav .son` + - Subfiles: *ogg_vorbis* + - *ubi_lyn_container*: `.sns .wav .lwav .son` + - Subfiles: *ubi_lyn* + - Codecs: PCM16LE NGC_DSP OGG_VORBIS MPEG MP4/AAC XMA +- **ubi_raki.c** + - Ubisoft RAKI header [*UBI_RAKI*] + - *ubi_raki*: `.rak .ckd` + - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 Opus +- **ubi_sb.c** + - Ubisoft SBx header [*UBI_SB*] + - *ubi_sb*: `.sb0 .sb1 .sb2 .sb3 .sb4 .sb5 .sb6 .sb7` + - *ubi_sm*: `.sm0 .sm1 .sm2 .sm3 .sm4 .sm5 .sm6 .sm7 .lm0 .lm1 .lm2 .lm3 .lm4 .lm5 .lm6 .lm7` + - *ubi_bnm*: `.bnm` + - *ubi_dat*: `.dat` + - *ubi_dat_main*: `(base) + .(external) .osb .kat` + - Subfiles: *kat riff* + - *ubi_bnm_ps2*: `.bnm` + - *ubi_blk*: `.blk + .(external)` + - *ubi_sb_audio*: `(base) + .(external)` + - *ubi_sb_layer*: `(base) + .(external)` + - *ubi_sb_sequence*: `(base) + .(external)` + - *ubi_sb_header*: `(base) + .(external) .kat` + - Codecs: PCM16LE AICA_int UBI_IMA UBI_SCE_IMA UBI_ADPCM PSX XBOX_IMA NGC_DSP ATRAC3 XMA OGG_VORBIS DVI_IMA_int +- **ue4opus.c** + - Epic Games UE4OPUS header [*UE4OPUS*] + - *ue4opus*: `.opus .lopus .ue4opus` + - Codecs: Opus +- **utk.c** + - Maxis UTK header [*UTK*] + - *utk*: `.utk` + - Codecs: EA_MT +- **vab.c** + - Sony VAB header [*VAB*] + - *vab*: `.vh .vab + .vb` + - Codecs: PSX +- **vag.c** + - Sony VAG header (custom) [*VAG_custom*] + - Sony VAG header [*VAG*] + - Acclaim Austin AAAp header [*AAAP*] + - *vag*: `.vag .swag .str .vig .l .r .vas .xa2 .snd` + - *vag_aaap*: `.vag` + - Codecs: PSX HEVAG +- **vai.c** + - Asobo Studio .VAI header [*VAI*] + - *vai*: `.vai` + - Codecs: NGC_DSP +- **vgs.c** + - Guitar Hero VGS Header [*VGS*] + - *vgs*: `.vgs` + - Codecs: PSX_badflags +- **vgs_ps.c** + - Princess Soft VGS header [*VGS_PS*] + - *vgs_ps*: `.vgs` + - Codecs: PSX +- **vid1.c** + - Factor 5 VID1 header [*VID1*] + - *vid1*: `.vid .ogg .logg` + - Codecs: PCM16_int XBOX_IMA NGC_DSP VORBIS_custom +- **vis.c** + - Konami VIS header [*VIS*] + - *vis*: `.vis` + - Codecs: PSX +- **voi.c** + - Irem .VOI header [*VOI*] + - *voi*: `.voi` + - Codecs: PCM16LE +- **vpk.c** + - SCE America VPK Header [*VPK*] + - *vpk*: `.vpk` + - Codecs: PSX +- **vs.c** + - Melbourne House .VS header [*VS*] + - *vs*: `.vs` + - Codecs: PSX +- **vsf.c** + - Square Enix VSF header [*VSF*] + - *vsf*: `.vsf` + - Codecs: PSX +- **vsf_tta.c** + - VSF with SMSS Header [*PS2_VSF_TTA*] + - *ps2_vsf_tta*: `.vsf` + - Codecs: PSX +- **vsv.c** + - Square Enix .vsv Header [*VSV*] + - *vsv*: `.vsv .psh` + - Codecs: PSX +- **vs_square.c** + - Square VS header [*VS_SQUARE*] + - *vs_square*: `.vs` + - Codecs: PSX +- **vs_str.c** + - Square .VS STRx header [*VS_STR*] + - *vs_str*: `.vs .str` + - Codecs: PSX +- **vxn.c** + - Gameloft VXN header [*VXN*] + - *vxn*: `.vxn` + - Codecs: PCM16LE MSADPCM MS_IMA FFmpeg(various) +- **wady.c** + - Marble WADY header [*WADY*] + - *wady*: `.way .(extensionless)` + - Codecs: WADY +- **waf.c** + - KID WAF header [*WAF*] + - *waf*: `.waf` + - Codecs: MSADPCM +- **wave.c** + - EngineBlack .WAVE header [*WAVE*] + - *wave*: `.wave` + - Codecs: IMA_int NGC_DSP +- **wavebatch.c** + - Firebrand Games WBAT header [*WAVEBATCH*] + - *wavebatch*: `.wavebatch` + - Codecs: PCM16BE PCM16LE PCM8 NGC_DSP +- **wave_segmented.c** + - EngineBlack .WAVE header [*WAVE*] + - EngineBlack .WAVE header (segmented) [*WAVE_segmented*] + - *wave_segmented*: `.wave` + - Subfiles: *ogg_vorbis_config* + - Codecs: IMA_int NGC_DSP OGG +- **wbk.c** + - Treyarch WBK header [*WBK*] + - Treyarch NSLB header [*WBK_NSLB*] + - *wbk*: `.wbk` + - *wbk_nslb*: `.wbk` + - Subfiles: *fsb* + - Codecs: NGC_DSP PSX XBOX_IMA IMA XMA +- **wii_bns.c** + - Nintendo BNS header [*WII_BNS*] + - *wii_bns*: `.bin .lbin .bns` + - Codecs: NGC_DSP +- **wii_mus.c** + - mus header [*DSP_WII_MUS*] + - *wii_mus*: `.mus` + - Codecs: NGC_DSP +- **wii_ras.c** + - RAS header [*WII_RAS*] + - *wii_ras*: `.ras` + - Codecs: NGC_DSP +- **wii_sng.c** + - SNG DSP Header [*WII_SNG*] + - *wii_sng*: `.sng` + - Codecs: NGC_DSP +- **wpd.c** + - WPD 'DPW' header [*WPD*] + - *wpd*: `.wpd` + - Codecs: PCM16LE +- **wsi.c** + - Alone in the Dark .WSI header [*DSP_WSI*] + - *wsi*: `.wsi` + - Codecs: NGC_DSP +- **ws_aud.c** + - Westwood Studios .AUD header [*WS_AUD*] + - *ws_aud*: `.aud` + - Codecs: WS IMA_int +- **wv2.c** + - Infogrames North America WAV2 header [*WV2*] + - *wv2*: `.wv2` + - Codecs: DVI_IMA_int +- **wv6.c** + - Gorilla Systems WV6 header [*WV6*] + - *wv6*: `.wv6` + - Codecs: WV6_IMA +- **wvs.c** + - Swingin' Ape .WVS header [*WVS*] + - *wvs_xbox*: `.wvs` + - *wvs_ngc*: `.wvs` + - Codecs: XBOX_IMA NGC_DSP +- **wwise.c** + - Audiokinetic Wwise RIFF header [*WWISE_RIFF*] + - *wwise* + - Subfiles: *wwise_bnk* + - *wwise_bnk*: `.wem .wav .lwav .ogg .logg .xma .bnk` + - Codecs: PCM16BE PCM16LE WWISE_IMA XBOX_IMA VORBIS_custom NGC_DSP XMA XWMA FFmpeg(various) Opus HEVAG ATRAC9 PTADPCM +- **wxd_wxh.c** + - Relic WXD+WXH header [*WXD_WXH*] + - *wxd_wxh*: `.wxd + .wxh` + - Codecs: RELIC +- **xa.c** + - Sony XA header [*XA*] + - *xa*: `.xa .str .pxa .grn .an2 .(extensionless)` + - Codecs: XA8 XA +- **xa2_acclaim.c** + - Acclaim .XA2 Header [*XA2_ACCLAIM*] + - *xa2_acclaim*: `.xa2` + - Codecs: PSX +- **xau.c** + - XPEC XAU header [*XAU*] + - *xau*: `.xau` + - Codecs: PSX XBOX_IMA +- **xau_konami.c** + - Konami XAU header [*XAU_KONAMI*] + - *xau_konami*: `.xau` + - Codecs: PCM16LE +- **xavs.c** + - Reflections XAVS header [*XAVS*] + - *xavs*: `.xav` + - Codecs: PCM16LE +- **xa_04sw.c** + - Reflections 04SW header [*XA_04SW*] + - *xa_04sw*: `.xa` + - Codecs: NGC_DSP +- **xa_xa30.c** + - Reflections XA30 header [*XA_XA30*] + - *xa_xa30*: `.xa .xa30 .e4x` + - Codecs: PCM16LE REF_IMA +- **xbox_ims.c** + - assumed Matrix file by .matx extension [*XBOX_MATX*] + - *xbox_matx*: `.matx` + - Codecs: XBOX_IMA +- **xma.c** + - Microsoft XMA RIFF header [*XMA_RIFF*] + - *xma*: `.xma .xma2 .wav .lwav .nps .str .kmx` + - Codecs: XMA +- **xma_ue3.c** + - Unreal Engine XMA header [*XMA_UE3*] + - *xma_ue3*: `.xma .x360audio .(extensionless)` + - Codecs: XMA +- **xmd.c** + - Konami XMD header [*XMD*] + - *xmd*: `.xmd` + - Codecs: XMD +- **xmu.c** + - Outrage XMU header [*XMU*] + - *xmu*: `.xmu` + - Codecs: XBOX_IMA +- **xnb.c** + - Microsoft XNA Game Studio 4.0 header [*XNB*] + - *xnb*: `.xnb + .(external)` + - Subfiles: *ogg_vorbis riff opus_std ffmpeg* + - Codecs: PCM8_U PCM16LE MSADPCM MS_IMA XMA2 NGC_DSP +- **xopus.c** + - Exient XOPUS header [*XOPUS*] + - *xopus*: `.xopus` + - Codecs: Opus +- **xpcm.c** + - Circus XPCM header [*XPCM*] + - *xpcm*: `.pcm` + - Codecs: PCM16LE CIRCUS_ADPCM CIRCUS_VQ +- **xps.c** + - From Software .XPS+DAT header [*XPS_DAT*] + - *xps_dat*: `.xps + .dat` + - *xps*: `.xps + .dat` + - Subfiles: *riff* + - Codecs: PCM16LE XBOX_IMA +- **xsh_xsd_xss.c** + - Treyarch XSH+XSD/XSS header [*XSH_XSD_XSS*] + - *xsh_xsd_xss*: `.xsh + .(external) .xsd` + - Subfiles: *riff* + - Codecs: XBOX_IMA +- **xss.c** + - Dino Crisis 3 XSS File [*XSS*] + - *xss*: `.xss` + - Codecs: PCM16LE +- **xssb.c** + - Artoon XSSB header [*XSSB*] + - *xssb*: `.bin .lbin` + - Codecs: PCM16LE XBOX_IMA +- **xvag.c** + - Sony XVAG header [*XVAG*] + - *xvag*: `.xvag .(extensionless)` + - Codecs: PSX MPEG ATRAC9 +- **xvas.c** + - Konami .XVAS header [*XVAS*] + - *xvas*: `.xvas` + - Codecs: XBOX_IMA +- **xwav.c** + - feelplus XWAV header [*XWAV*] + - *xwav_new*: `.xwv .vawx` + - *xwav_old*: `.xwv` + - Codecs: PSX XMA2 ATRAC3 +- **xwb.c** + - Microsoft XWB header [*XWB*] + - *xwb*: `.xwb .xna .hwb .bd .(extensionless) + .wbh` + - Subfiles: *riff* + - Codecs: PCM8_U PCM16LE PCM16BE XBOX_IMA MSADPCM XMA1 XMA2 FFmpeg(various) XWMA ATRAC3 OGG_VORBIS NGC_DSP +- **xwc.c** + - Starbreeze XWC header [*XWC*] + - *xwc*: `.xwc` + - Codecs: MPEG XMA2 OGG_VORBIS +- **xwma.c** + - Microsoft XWMA RIFF header [*XWMA*] + - *xwma*: `.xwma .xwm .xma .wma .lwma` + - Codecs: XWMA +- **xwma_konami.c** + - Konami XWMA header [*XWMA_KONAMI*] + - *xwma_konami*: `.xwma` + - Codecs: XWMA +- **xwv_valve.c** + - Half-Life 2 .WAV header [*XBOX_HLWAV*] + - Valve XWV header [*XWV_VALVE*] + - *xbox_hlwav*: `.wav .lwav` + - *xwv_valve*: `.wav .lwav` + - Codecs: PCM16LE XBOX_IMA PCM16BE XMA2 +- **ydsp.c** + - Yuke's YDSP Header [*YDSP*] + - *ydsp*: `.ydsp` + - Codecs: NGC_DSP +- **ymf.c** + - Yuke's .YMF Header [*YMF*] + - *ymf*: `.ymf` + - Codecs: NGC_DSP +- **zsd.c** + - Konami ZSD header [*ZSD*] + - *zsd*: `.zsd` + - Codecs: PCM8 +- **zsnd.c** + - Z-Axis ZSND header [*ZSND*] + - *zsnd*: `.zss .zsm .ens .enm .zsd` + - Codecs: IMA XBOX_IMA PSX NGC_DSP +- **zwv.c** + - (container) + - *zwv*: `.zwv` + - Subfiles: *msf* + +## Supported extras +Reminder of some extra formats and helper files vgmstream supports. They are described +in detail in USAGE.md. + +- artificial headers: + - .txth (text header, adds support to lots of extra formats) + - .genh (generic header, deprecated) +- loop assists: + - .txtm (text map config, for formats that open companion files manually) + - .txtp (text play config, per song segment/layer manipulation) - loop assists: - - .mus (playlist for .acm) - - .pos (loop info for .wav) - - .sli (loop info for .ogg) - - .sfl (loop info for .ogg) + - .mus (playlist for .acm) + - .pos (loop info for .wav) + - .sli (loop info for .ogg) + - .sfl (loop info for .ogg) - other: - - .adxkey (decryption key for .adx) - - .ahxkey (decryption key for .ahx) - - .hcakey (decryption key for .hca) - - .fsbkey (decryption key for .fsb) - - .bnsfkey (decryption key for .bnsf) - - .txtp (per song segment/layer handler and player configuration) + - .adxkey (decryption key for .adx) + - .ahxkey (decryption key for .ahx) + - .hcakey (decryption key for .hca) + - .fsbkey (decryption key for .fsb) + - .bnsfkey (decryption key for .bnsf) -## Supported codec types +## Supported codecs Quick list of most codecs vgmstream supports, including many obscure ones that are used in few games. diff --git a/doc/TXTH.md b/doc/TXTH.md index 397a27e47..1a7ecaf86 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -69,7 +69,7 @@ as explained below, but often will use default values. Accepted codec strings: # * For many PS1/PS2/PS3 games # * Interleave is multiple of 0x10 (default), often +0x1000 # - PSX_bf PlayStation ADPCM with bad flags -# * Variation with garbage data, for rare PS2 games [Fatal Frame (PS2)] +# * Variation with garbage data, for rare PS2 games [Fatal Frame (PS2), namCollection: Tekken (PS2)] # - HEVAG Vita/PS4 ADPCM # * For some Vita/PS4 games # * Interleave is multiple of 0x10 (default) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 1e830ecb4..3cbec0362 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -599,8 +599,8 @@ - + From 5d9b4ed827d9d5a454f2b0a8684db504712a06de Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 22:02:34 +0200 Subject: [PATCH 071/141] cleanup: separte sf code --- src/base/info.c | 2 +- src/base/render.c | 1 - src/libvgmstream.vcxproj | 2 + src/libvgmstream.vcxproj.filters | 6 + src/meta/meta.h | 1 + src/streamfile.c | 189 +----------------------------- src/streamfile.h | 23 +--- src/util/companion_files.c | 3 +- src/util/sf_utils.c | 192 +++++++++++++++++++++++++++++++ src/util/sf_utils.h | 29 +++++ src/vgmstream.c | 1 + 11 files changed, 236 insertions(+), 213 deletions(-) create mode 100644 src/util/sf_utils.c create mode 100644 src/util/sf_utils.h diff --git a/src/base/info.c b/src/base/info.c index 5ee86a476..3f6d90a60 100644 --- a/src/base/info.c +++ b/src/base/info.c @@ -3,7 +3,7 @@ #include "../coding/coding.h" #include "mixing.h" #include "../util/channel_mappings.h" - +#include "../util/sf_utils.h" /*******************************************************************************/ /* TEXT */ diff --git a/src/base/render.c b/src/base/render.c index f5480efa9..a7cc29de7 100644 --- a/src/base/render.c +++ b/src/base/render.c @@ -285,7 +285,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { case layout_blocked_ivaud: case layout_blocked_ea_swvr: case layout_blocked_adm: - case layout_blocked_bdsp: case layout_blocked_ps2_iab: case layout_blocked_vs_str: case layout_blocked_rws: diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 3cbec0362..8484a5057 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -185,6 +185,7 @@ + @@ -745,6 +746,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 7984edc6c..7bfe3e72d 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -380,6 +380,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2056,6 +2059,9 @@ util\Source Files + + util\Source Files + util\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index ba3bbb40a..18cae8af7 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -4,6 +4,7 @@ #include "../vgmstream.h" #include "../util/reader_sf.h" #include "../util/reader_text.h" +#include "../util/sf_utils.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf); diff --git a/src/streamfile.c b/src/streamfile.c index ef1c5e707..8566febfd 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1,8 +1,8 @@ #include "streamfile.h" #include "util.h" #include "vgmstream.h" -#include "util/reader_sf.h" #include "util/paths.h" +#include "util/sf_utils.h" #include /* for dup/fdopen in some systems */ @@ -985,92 +985,10 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size) { /* **************************************************** */ -/* change pathname's extension to another (or add it if extensionless) */ -static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) { - char* extension = (char*)filename_extension(pathname); - //todo safeops - if (extension[0] == '\0') { - strcat(pathname, "."); - strcat(pathname, swap); - } - else { - strcpy(extension, swap); - } -} - STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname) { return sf->open(sf, pathname, STREAMFILE_DEFAULT_BUFFER_SIZE); } -STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) { - char filename[PATH_LIMIT]; - - get_streamfile_name(sf, filename, sizeof(filename)); - - swap_extension(filename, sizeof(filename), ext); - - return open_streamfile(sf, filename); -} - -STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { - char fullname[PATH_LIMIT]; - char partname[PATH_LIMIT]; - char *path, *name, *otherpath; - - if (!sf || !filename || !filename[0]) return NULL; - - get_streamfile_name(sf, fullname, sizeof(fullname)); - - //todo normalize separators in a better way, safeops, improve copying - - /* check for non-normalized paths first (ex. txth) */ - path = strrchr(fullname, '/'); - otherpath = strrchr(fullname, '\\'); - if (otherpath > path) { //todo cast to ptr? - /* foobar makes paths like "(fake protocol)://(windows path with \)". - * Hack to work around both separators, though probably foo_streamfile - * should just return and handle normalized paths without protocol. */ - path = otherpath; - } - - if (path) { - path[1] = '\0'; /* remove name after separator */ - - strcpy(partname, filename); - fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */ - - /* normalize relative paths as don't work ok in some plugins */ - if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */ - name = partname + 2; /* ignore './' */ - } - else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */ - char* pathprev; - - path[0] = '\0'; /* remove last separator so next call works */ - pathprev = strrchr(fullname,DIR_SEPARATOR); - if (pathprev) { - pathprev[1] = '\0'; /* remove prev dir after separator */ - name = partname + 3; /* ignore '../' */ - } - else { /* let plugin handle? */ - path[0] = DIR_SEPARATOR; - name = partname; - } - /* could work with more relative paths but whatevs */ - } - else { - name = partname; - } - - strcat(fullname, name); - } - else { - strcpy(fullname, filename); - } - - return open_streamfile(sf, fullname); -} - STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { char pathname[PATH_LIMIT]; @@ -1084,111 +1002,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { /* ************************************************************************* */ -int check_extensions(STREAMFILE* sf, const char* cmp_exts) { - char filename[PATH_LIMIT]; - const char* ext = NULL; - const char* cmp_ext = NULL; - const char* ststr_res = NULL; - size_t ext_len, cmp_len; - - sf->get_name(sf, filename, sizeof(filename)); - ext = filename_extension(filename); - ext_len = strlen(ext); - - cmp_ext = cmp_exts; - do { - ststr_res = strstr(cmp_ext, ","); - cmp_len = ststr_res == NULL - ? strlen(cmp_ext) /* total length if more not found */ - : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */ - - if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0) - return 1; - - cmp_ext = ststr_res; - if (cmp_ext != NULL) - cmp_ext = cmp_ext + 1; /* skip comma */ - - } while (cmp_ext != NULL); - - return 0; -} - -/* ************************************************************************* */ - -/* copies name as-is (may include full path included) */ -void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) { - sf->get_name(sf, buffer, size); -} - -/* copies the filename without path */ -void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) { - char foldername[PATH_LIMIT]; - const char* path; - - - get_streamfile_name(sf, foldername, sizeof(foldername)); - - //todo Windows CMD accepts both \\ and /, better way to handle this? - path = strrchr(foldername,'\\'); - if (!path) - path = strrchr(foldername,'/'); - if (path != NULL) - path = path+1; - - //todo validate sizes and copy sensible max - if (path) { - strcpy(buffer, path); - } else { - strcpy(buffer, foldername); - } -} - -/* copies the filename without path or extension */ -void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) { - char* ext; - - get_streamfile_filename(sf, buffer, size); - - ext = strrchr(buffer,'.'); - if (ext) { - ext[0] = '\0'; /* remove .ext from buffer */ - } -} - -/* copies path removing name (NULL when if filename has no path) */ -void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) { - const char* path; - - get_streamfile_name(sf, buffer, size); - - path = strrchr(buffer,DIR_SEPARATOR); - if (path!=NULL) path = path+1; /* includes "/" */ - - if (path) { - buffer[path - buffer] = '\0'; - } else { - buffer[0] = '\0'; - } -} - -/* copies extension only */ -void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) { - char filename[PATH_LIMIT]; - const char* extension = NULL; - - get_streamfile_name(sf, filename, sizeof(filename)); - extension = filename_extension(filename); - if (!extension) { - buffer[0] = '\n'; - } - else { - strncpy(buffer, extension, size); //todo use something better - } -} - -/* ************************************************************************* */ - /* debug util, mainly for custom IO testing */ void dump_streamfile(STREAMFILE* sf, int num) { #ifdef VGM_DEBUG_OUTPUT diff --git a/src/streamfile.h b/src/streamfile.h index 476372c34..d3e890918 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -130,15 +130,6 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size); * Just a wrapper, to avoid having to access the STREAMFILE's callbacks directly. */ STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname); -/* Opens a STREAMFILE from a base pathname + new extension - * Can be used to get companion headers. */ -STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext); - -/* Opens a STREAMFILE from a base path + new filename. - * Can be used to get companion files. Relative paths like - * './filename', '../filename', 'dir/filename' also work. */ -STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename); - /* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing. * Uses default buffer size when buffer_size is 0 */ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size); @@ -161,18 +152,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) { } -/* various STREAMFILE helpers functions */ - -/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). - * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */ -int check_extensions(STREAMFILE* sf, const char* cmp_exts); - -/* filename helpers */ -void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size); -void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size); - void dump_streamfile(STREAMFILE* sf, int num); + #endif diff --git a/src/util/companion_files.c b/src/util/companion_files.c index 253b18e3f..b126a49e3 100644 --- a/src/util/companion_files.c +++ b/src/util/companion_files.c @@ -1,7 +1,8 @@ #include "companion_files.h" #include "paths.h" #include "../vgmstream.h" -#include "../util/reader_text.h" +#include "reader_text.h" +#include "sf_utils.h" size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { diff --git a/src/util/sf_utils.c b/src/util/sf_utils.c new file mode 100644 index 000000000..d0cd061ec --- /dev/null +++ b/src/util/sf_utils.c @@ -0,0 +1,192 @@ +#include "sf_utils.h" +#include "../vgmstream.h" +#include "reader_sf.h" +#include "paths.h" + + +/* change pathname's extension to another (or add it if extensionless) */ +static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) { + char* extension = (char*)filename_extension(pathname); + //todo safeops + if (extension[0] == '\0') { + strcat(pathname, "."); + strcat(pathname, swap); + } + else { + strcpy(extension, swap); + } +} + +STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) { + char filename[PATH_LIMIT]; + + get_streamfile_name(sf, filename, sizeof(filename)); + + swap_extension(filename, sizeof(filename), ext); + + return open_streamfile(sf, filename); +} + +STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) { + char fullname[PATH_LIMIT]; + char partname[PATH_LIMIT]; + char *path, *name, *otherpath; + + if (!sf || !filename || !filename[0]) return NULL; + + get_streamfile_name(sf, fullname, sizeof(fullname)); + + //todo normalize separators in a better way, safeops, improve copying + + /* check for non-normalized paths first (ex. txth) */ + path = strrchr(fullname, '/'); + otherpath = strrchr(fullname, '\\'); + if (otherpath > path) { //todo cast to ptr? + /* foobar makes paths like "(fake protocol)://(windows path with \)". + * Hack to work around both separators, though probably foo_streamfile + * should just return and handle normalized paths without protocol. */ + path = otherpath; + } + + if (path) { + path[1] = '\0'; /* remove name after separator */ + + strcpy(partname, filename); + fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */ + + /* normalize relative paths as don't work ok in some plugins */ + if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */ + name = partname + 2; /* ignore './' */ + } + else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */ + char* pathprev; + + path[0] = '\0'; /* remove last separator so next call works */ + pathprev = strrchr(fullname,DIR_SEPARATOR); + if (pathprev) { + pathprev[1] = '\0'; /* remove prev dir after separator */ + name = partname + 3; /* ignore '../' */ + } + else { /* let plugin handle? */ + path[0] = DIR_SEPARATOR; + name = partname; + } + /* could work with more relative paths but whatevs */ + } + else { + name = partname; + } + + strcat(fullname, name); + } + else { + strcpy(fullname, filename); + } + + return open_streamfile(sf, fullname); +} + +/* ************************************************************************* */ + +int check_extensions(STREAMFILE* sf, const char* cmp_exts) { + char filename[PATH_LIMIT]; + const char* ext = NULL; + const char* cmp_ext = NULL; + const char* ststr_res = NULL; + size_t ext_len, cmp_len; + + sf->get_name(sf, filename, sizeof(filename)); + ext = filename_extension(filename); + ext_len = strlen(ext); + + cmp_ext = cmp_exts; + do { + ststr_res = strstr(cmp_ext, ","); + cmp_len = ststr_res == NULL + ? strlen(cmp_ext) /* total length if more not found */ + : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */ + + if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0) + return 1; + + cmp_ext = ststr_res; + if (cmp_ext != NULL) + cmp_ext = cmp_ext + 1; /* skip comma */ + + } while (cmp_ext != NULL); + + return 0; +} + +/* ************************************************************************* */ + +/* copies name as-is (may include full path included) */ +void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) { + sf->get_name(sf, buffer, size); +} + +/* copies the filename without path */ +void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) { + char foldername[PATH_LIMIT]; + const char* path; + + + get_streamfile_name(sf, foldername, sizeof(foldername)); + + //todo Windows CMD accepts both \\ and /, better way to handle this? + path = strrchr(foldername,'\\'); + if (!path) + path = strrchr(foldername,'/'); + if (path != NULL) + path = path+1; + + //todo validate sizes and copy sensible max + if (path) { + strcpy(buffer, path); + } else { + strcpy(buffer, foldername); + } +} + +/* copies the filename without path or extension */ +void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) { + char* ext; + + get_streamfile_filename(sf, buffer, size); + + ext = strrchr(buffer,'.'); + if (ext) { + ext[0] = '\0'; /* remove .ext from buffer */ + } +} + +/* copies path removing name (NULL when if filename has no path) */ +void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) { + const char* path; + + get_streamfile_name(sf, buffer, size); + + path = strrchr(buffer,DIR_SEPARATOR); + if (path!=NULL) path = path+1; /* includes "/" */ + + if (path) { + buffer[path - buffer] = '\0'; + } else { + buffer[0] = '\0'; + } +} + +/* copies extension only */ +void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) { + char filename[PATH_LIMIT]; + const char* extension = NULL; + + get_streamfile_name(sf, filename, sizeof(filename)); + extension = filename_extension(filename); + if (!extension) { + buffer[0] = '\n'; + } + else { + strncpy(buffer, extension, size); //todo use something better + } +} diff --git a/src/util/sf_utils.h b/src/util/sf_utils.h new file mode 100644 index 000000000..c1260bfe5 --- /dev/null +++ b/src/util/sf_utils.h @@ -0,0 +1,29 @@ +#ifndef _SF_UTILS_H +#define _SF_UTILS_H +#include "../streamfile.h" + + + +/* Opens a STREAMFILE from a base pathname + new extension + * Can be used to get companion headers. */ +STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext); + +/* Opens a STREAMFILE from a base path + new filename. + * Can be used to get companion files. Relative paths like + * './filename', '../filename', 'dir/filename' also work. */ +STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename); + +/* various STREAMFILE helpers functions */ + +/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix"). + * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */ +int check_extensions(STREAMFILE* sf, const char* cmp_exts); + +/* filename helpers */ +void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size); +void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size); + +#endif diff --git a/src/vgmstream.c b/src/vgmstream.c index c2b61e784..68deec246 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -12,6 +12,7 @@ #include "base/decode.h" #include "base/render.h" #include "base/mixing.h" +#include "util/sf_utils.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*); From b916b5165a4e095d43fd5d3a1097f6df1ec3f9de Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 25 Jun 2023 23:33:00 +0200 Subject: [PATCH 072/141] cleanup: tweaks --- src/meta/ngc_dsp_std.c | 16 +++++++--------- src/meta/sli.c | 6 +++++- src/vgmstream.c | 9 +++++---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/meta/ngc_dsp_std.c b/src/meta/ngc_dsp_std.c index a15a4b1e3..f44c7a5a6 100644 --- a/src/meta/ngc_dsp_std.c +++ b/src/meta/ngc_dsp_std.c @@ -301,13 +301,13 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std(STREAMFILE* sf) { /* checks */ if (!read_dsp_header_be(&header, 0x00, sf)) - goto fail; + return NULL; /* .dsp: standard * .adp: Dr. Muto/Battalion Wars (GC), Tale of Despereaux (Wii) * (extensionless): Tony Hawk's Downhill Jam (Wii) */ if (!check_extensions(sf, "dsp,adp,")) - goto fail; + return NULL; channels = 1; start_offset = header_size; @@ -418,12 +418,11 @@ VGMSTREAM* init_vgmstream_ngc_dsp_std_le(STREAMFILE* sf) { int i, channels; /* checks */ + if (!read_dsp_header_le(&header, 0x00, sf)) + return NULL; /* .adpcm: LEGO Worlds */ if (!check_extensions(sf, "adpcm")) - goto fail; - - if (!read_dsp_header_le(&header, 0x00, sf)) - goto fail; + return NULL; channels = 1; start_offset = header_size; @@ -503,10 +502,9 @@ VGMSTREAM* init_vgmstream_ngc_mdsp_std(STREAMFILE* sf) { /* checks */ if (!read_dsp_header_be(&header, 0x00, sf)) - goto fail; - + return NULL; if (!check_extensions(sf, "dsp,mdsp")) - goto fail; + return NULL; channels = header.channels==0 ? 1 : header.channels; start_offset = header_size * channels; diff --git a/src/meta/sli.c b/src/meta/sli.c index d8b3ca795..11352e6ff 100644 --- a/src/meta/sli.c +++ b/src/meta/sli.c @@ -12,8 +12,12 @@ VGMSTREAM* init_vgmstream_sli_loops(STREAMFILE* sf) { VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL; /* checks */ + /* V1: fixed to 0x900? + * V2: varies with text size but around 0xC0 */ + if (get_streamfile_size(sf) > 0x2000) + return NULL; if (!check_extensions(sf, "sli")) - goto fail; + return NULL; { /* try with file.ogg/opus/wav.sli=header and file.ogg/opus/wav=data */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 68deec246..fad5ff55a 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -68,7 +68,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_svs, init_vgmstream_riff, init_vgmstream_rifx, - init_vgmstream_pos, init_vgmstream_nwa, init_vgmstream_ea_1snh, init_vgmstream_ea_eacs, @@ -339,7 +338,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_flx, init_vgmstream_mogg, init_vgmstream_kma9, - init_vgmstream_fsb_encrypted, init_vgmstream_xwc, init_vgmstream_atsl, init_vgmstream_sps_n1, @@ -378,7 +376,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_hd3_bd3, init_vgmstream_bnk_sony, init_vgmstream_nus3bank, - init_vgmstream_nus3bank_encrypted, init_vgmstream_sscf, init_vgmstream_dsp_sps_n1, init_vgmstream_dsp_itl_ch, @@ -536,14 +533,18 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mjb_mjh, init_vgmstream_mic_koei, init_vgmstream_seb, - init_vgmstream_sli_loops, init_vgmstream_tgc, + /* need companion files */ + init_vgmstream_pos, + init_vgmstream_sli_loops, /* 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 */ init_vgmstream_dtk, /* semi-raw GC streamed files */ init_vgmstream_mpeg, /* semi-raw MP3 */ init_vgmstream_btsnd, /* semi-headerless */ + init_vgmstream_fsb_encrypted, + init_vgmstream_nus3bank_encrypted, init_vgmstream_encrypted, /* encrypted stuff */ init_vgmstream_raw_rsf, /* raw GC streamed files */ init_vgmstream_raw_int, /* .int raw PCM */ From 55a0b2082a9c5cb80faaac4137d43760ac5c2560 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Wed, 28 Jun 2023 14:20:47 +0300 Subject: [PATCH 073/141] RWS 0x809: DSP-ADPCM and reworked stuff --- src/meta/awd.c | 8 +++---- src/meta/meta.h | 2 +- src/meta/rws_mono.c | 54 +++++++++++++++++++++++++++++---------------- src/vgmstream.c | 2 +- 4 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/meta/awd.c b/src/meta/awd.c index f20f75e6d..29591db9c 100644 --- a/src/meta/awd.c +++ b/src/meta/awd.c @@ -29,7 +29,7 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { data_offset = read_u32(0x08, sf); wavedict_offset = read_u32(0x0C, sf); - //data_size = read_u32(0x14, sf); + //data_size = read_u32(0x14, sf); /* Platform UUIDs in big endian * {FD9D32D3-E179-426A-8424-14720AC7F648}: GameCube * {ACC9EAAA-38FC-1749-AE81-64EADBC79353}: PlayStation 2 @@ -72,20 +72,20 @@ VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf) { /* is at the correct target song index */ if (total_subsongs == target_subsong) { - //entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ + //entry_uuid_offset = read_u32(entry_info_offset + 0x00, sf); /* only used in Burnout games */ entry_name_offset = read_u32(entry_info_offset + 0x04, sf); sample_rate = read_u32(entry_info_offset + 0x10, sf); stream_codec = read_u32(entry_info_offset + 0x14, sf); stream_size = read_u32(entry_info_offset + 0x18, sf); - //bit_depth = read_u8(entry_info_offset + 0x1C, sf); + //bit_depth = read_u8(entry_info_offset + 0x1C, sf); channels = read_u8(entry_info_offset + 0x1D, sf); /* always 1, don't think stereo entries exist */ if (channels != 1) goto fail; /* stores a "00: GCN ADPCM Header" chunk, otherwise empty */ misc_data_offset = read_u32(entry_info_offset + 0x20, sf); - //misc_data_size = read_u32(entry_info_offset + 0x24, sf); + //misc_data_size = read_u32(entry_info_offset + 0x24, sf); /* entry_info_offset + 0x2C to +0x44 has the target format information, * which in most cases would probably be identical to the input format diff --git a/src/meta/meta.h b/src/meta/meta.h index 18cae8af7..a6a9fd935 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -980,7 +980,7 @@ VGMSTREAM* init_vgmstream_ego_dic(STREAMFILE* sf); VGMSTREAM* init_vgmstream_awd(STREAMFILE* sf); -VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf); VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); diff --git a/src/meta/rws_mono.c b/src/meta/rws_mono.c index ea88ccf50..33baea631 100644 --- a/src/meta/rws_mono.c +++ b/src/meta/rws_mono.c @@ -4,27 +4,27 @@ /* RWS - RenderWare Stream (with the tag 0x809) */ -VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; bool big_endian; char header_name[STREAM_NAME_SIZE], stream_name[STREAM_NAME_SIZE]; - int bit_depth = 0, channels = 0, idx, interleave, loop_flag, sample_rate = 0, total_subsongs, target_subsong = sf->stream_index; + int channels = 0, idx, interleave, loop_flag, sample_rate = 0, total_subsongs, target_subsong = sf->stream_index; read_u32_t read_u32; - off_t chunk_offset, header_offset, stream_offset = 0; - size_t chunk_size, header_size, stream_size = 0; + off_t chunk_offset, header_offset, misc_data_offset = 0, stream_name_offset, stream_offset = 0; + size_t chunk_size, header_size, misc_data_size, stream_size = 0; + uint32_t codec_uuid = 0; /* checks */ if (read_u32le(0x00, sf) != 0x809) /* File ID */ goto fail; - /* Burnout 2: Point of Impact (PS2, GCN, Xbox): - * Predecessor to the common 0x80D-0x80F tag rws.c (which is also used in B2) - * with some parts of it later reworked into awd.c seemingly */ + /* Burnout 2: Point of Impact (PS2, GCN, Xbox), Neighbours from Hell (GCN, Xbox): + * Predecessor to the common 0x80D-0x80F tag RWS with some parts reworked into AWD? */ if (!check_extensions(sf, "rws")) goto fail; - /* Uses various chunk IDs across the file: + /* Uses the following chunk IDs across the file: * 0x00000809: File ID * 0x0000080A: File header ID * 0x0000080C: File data ID @@ -63,19 +63,27 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { header_offset = chunk_offset + 0x0C; if (read_u32le(header_offset, sf) != 0x803) /* Stream header ID */ goto fail; - header_size = read_u32le(header_offset + 0x04, sf); /* usually 0xA0 */ + header_size = read_u32le(header_offset + 0x04, sf); sample_rate = read_u32(header_offset + 0x10, sf); stream_size = read_u32(header_offset + 0x18, sf); - bit_depth = read_u8(header_offset + 0x1C, sf); + //bit_depth = read_u8(header_offset + 0x1C, sf); channels = read_u8(header_offset + 0x1D, sf); /* always 1? */ if (channels != 1) goto fail; - /* Assumed misc data offs/size at header_offset + 0x20 to +0x24 - * which is always empty since GCN uses PCM S16BE encoding here */ + //misc_data_offset = read_u32(header_offset + 0x20, sf); /* assumed, but wrong? */ + misc_data_offset = header_offset + 0x3C; + misc_data_size = read_u32(header_offset + 0x24, sf); /* 0x60 in GCN if DSP-ADPCM, otherwise 0 */ - read_string(stream_name, STREAM_NAME_SIZE, header_offset + 0x7C, sf); + codec_uuid = read_u32(header_offset + 0x2C, sf); + + /* (header_offset + 0x3C + misc_data_size) + 0x00 to +0x18 has the target format + * info which in most cases would probably be identical to the input format info */ + + /* misc_data_size * 2 should be 0xC0 if it exists */ + stream_name_offset = header_offset + 0x7C + (misc_data_size * 2); + read_string(stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); stream_offset = header_offset + header_size + 0x0C; if (read_u32le(stream_offset, sf) != 0x804) /* Stream data ID */ @@ -104,19 +112,27 @@ VGMSTREAM* init_vgmstream_rws_mono(STREAMFILE* sf) { vgmstream->num_streams = total_subsongs; vgmstream->interleave_block_size = interleave; - /* Likely unreliable, but currently only can be tested with Burnout 2 */ - switch (bit_depth) { - case 4: /* PS-ADPCM, normally DSP-ADPCM would be 4 too (as is in awd.c) but GCN uses PCM */ + /* Seems to be the same as in rws.c, maybe merge the two switches into one function? */ + switch (codec_uuid) { + case 0xD01BD217: /* {D01BD217-3587-4EED-B9D9-B8E86EA9B995}: PCM Signed 16-bit */ + vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); + vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + break; + + case 0xD9EA9798: /* {D9EA9798-BBBC-447B-96B2-654759102E16}: PSX-ADPCM */ vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); vgmstream->coding_type = coding_PSX; break; - case 16: /* PCM Signed 16-bit */ - vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); - vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + case 0xF86215B0: /* {F86215B0-31D5-4C29-BD37-CDBF9BD10C53}: DSP-ADPCM */ + vgmstream->num_samples = dsp_bytes_to_samples(stream_size, channels); + dsp_read_coefs_be(vgmstream, sf, misc_data_offset + 0x1C, 0); + dsp_read_hist_be(vgmstream, sf, misc_data_offset + 0x40, 0); + vgmstream->coding_type = coding_NGC_DSP; break; default: + VGM_LOG("RWS: unknown codec 0x%08x\n", codec_uuid); goto fail; } diff --git a/src/vgmstream.c b/src/vgmstream.c index fad5ff55a..f864a90be 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -521,8 +521,8 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_s_p_sth, init_vgmstream_utf_ahx, init_vgmstream_ego_dic, - init_vgmstream_rws_mono, init_vgmstream_awd, + init_vgmstream_rws_809, init_vgmstream_pwb, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ From e08e3fb7e7ea3ebe9e99ef65027d1fe83054671a Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Wed, 28 Jun 2023 14:44:09 +0300 Subject: [PATCH 074/141] Separating RWS 0x809 and RWS 0x80D variant C --- doc/FORMATS.md | 12 ++++++------ src/libvgmstream.vcxproj | 4 ++-- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/{rws_mono.c => rws_809.c} | 4 ++-- src/meta/{rws.c => rws_80d.c} | 0 5 files changed, 13 insertions(+), 13 deletions(-) rename src/meta/{rws_mono.c => rws_809.c} (97%) rename src/meta/{rws.c => rws_80d.c} (100%) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 581549678..2f2ea7d59 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -1330,18 +1330,18 @@ different internally (encrypted, different versions, etc) and not always can be - Konami RWAX header [*RWAX*] - *rwax*: `.rwx` - Codecs: PCM16LE -- **rws.c** +- **rws_809.c** - RenderWare RWS header [*RWS*] - - *rws*: `.rws` + - *rws_809*: `.rws` + - Codecs: PSX NGC_DSP PCM16BE PCM16LE +- **rws_80d.c** + - RenderWare RWS header [*RWS*] + - *rws_80d*: `.rws` - Codecs: PCM16_int PCM16BE PCM16LE PSX NGC_DSP XBOX_IMA - **rwsd.c** - Nintendo RWSD header (single stream) [*RWSD*] - *rwsd*: `.brwsd .rwsd` - Codecs: PCM8 PCM16BE NGC_DSP -- **rws_mono.c** - - RenderWare RWS header [*RWS*] - - *rws_mono*: `.rws` - - Codecs: PSX PCM16BE PCM16LE - **rxws.c** - Sony RXWS header [*RXWS*] - *rxws*: `.xwb .xws + .xwh .xwb` diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 8484a5057..c4513674d 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -599,9 +599,9 @@ - + + - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 7bfe3e72d..202b8f69d 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1618,13 +1618,13 @@ meta\Source Files - + meta\Source Files - + meta\Source Files - + meta\Source Files diff --git a/src/meta/rws_mono.c b/src/meta/rws_809.c similarity index 97% rename from src/meta/rws_mono.c rename to src/meta/rws_809.c index 33baea631..e4cca9585 100644 --- a/src/meta/rws_mono.c +++ b/src/meta/rws_809.c @@ -81,7 +81,7 @@ VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf) { /* (header_offset + 0x3C + misc_data_size) + 0x00 to +0x18 has the target format * info which in most cases would probably be identical to the input format info */ - /* misc_data_size * 2 should be 0xC0 if it exists */ + /* (misc_data_size * 2) should be 0xC0 if it exists */ stream_name_offset = header_offset + 0x7C + (misc_data_size * 2); read_string(stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); @@ -112,7 +112,7 @@ VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf) { vgmstream->num_streams = total_subsongs; vgmstream->interleave_block_size = interleave; - /* Seems to be the same as in rws.c, maybe merge the two switches into one function? */ + /* Seems to be the same as in rws_80d.c, maybe merge the two switches into one function? */ switch (codec_uuid) { case 0xD01BD217: /* {D01BD217-3587-4EED-B9D9-B8E86EA9B995}: PCM Signed 16-bit */ vgmstream->num_samples = pcm16_bytes_to_samples(stream_size, channels); diff --git a/src/meta/rws.c b/src/meta/rws_80d.c similarity index 100% rename from src/meta/rws.c rename to src/meta/rws_80d.c From 596aa76076fe1eac9ff892494496a6ff626e72b6 Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 22:59:22 +0200 Subject: [PATCH 075/141] Fix some .lsf [Agaju, Chicane (Gizmondo))] --- src/base/decode.c | 8 ++--- src/meta/lsf.c | 92 ++++++++++++++++++++++++++++++++++------------- src/vgmstream.c | 19 +++++----- 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/src/base/decode.c b/src/base/decode.c index f5feaa3dc..f55c3275c 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -449,7 +449,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { return 28; case coding_PSX_cfg: case coding_PSX_pivotal: - return (vgmstream->interleave_block_size - 0x01) * 2; /* size 0x01 header */ + return (vgmstream->frame_size - 0x01) * 2; /* size 0x01 header */ case coding_EA_XA: case coding_EA_XA_int: @@ -669,7 +669,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) { return 0x10; case coding_PSX_cfg: case coding_PSX_pivotal: - return vgmstream->interleave_block_size; + return vgmstream->frame_size; case coding_EA_XA: return 0x1E; @@ -998,14 +998,14 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ for (ch = 0; ch < vgmstream->channels; ch++) { decode_psx_configurable(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do, - vgmstream->interleave_block_size, vgmstream->codec_config); + vgmstream->frame_size, vgmstream->codec_config); } break; case coding_PSX_pivotal: for (ch = 0; ch < vgmstream->channels; ch++) { decode_psx_pivotal(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do, - vgmstream->interleave_block_size); + vgmstream->frame_size); } break; case coding_HEVAG: diff --git a/src/meta/lsf.c b/src/meta/lsf.c index 94f7741d9..f1446e7a1 100644 --- a/src/meta/lsf.c +++ b/src/meta/lsf.c @@ -1,43 +1,85 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* .lsf - from Atod games [Fastlane Street Racing (iPhone), Chicane Street Racing prototype (Gizmondo)] */ -VGMSTREAM * init_vgmstream_lsf_n1nj4n(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t file_size; +/* .lsf - from Gizmondo Studios Helsingborg/Atod AB games [Chicane Street Racing (Gizmondo), Fastlane Street Racing (iOS)] */ +VGMSTREAM* init_vgmstream_lsf_n1nj4n(STREAMFILE *sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, data_size, loop_start = 0, loop_end = 0; + int channels, loop_flag, sample_rate; + bool is_v2 = false; /* checks */ - if (!check_extensions(streamFile, "lsf")) - goto fail; + if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("!n1nj4n\0")) + is_v2 = false; + else if ((read_u64be(0x00, sf) & 0xFFFFFFFFFFFFFF00) == get_id64be("n1nj4n!\0")) + is_v2 = true; /* some files in Agaju: The Sacred Path (Gizmondo) */ + else + return NULL; - if (read_32bitBE(0x00, streamFile) != 0x216E316E || // "!n1n" - read_32bitBE(0x04, streamFile) != 0x6A346E00) // "j4n\0" - goto fail; + /* .lsf: actual extension, exe strings seem to call this format "LSF" as well */ + if (!check_extensions(sf, "lsf")) + return NULL; - file_size = get_streamfile_size(streamFile); - if (read_32bitLE(0x0C, streamFile) + 0x10 != file_size) - goto fail; + uint8_t flags = read_u8(0x07, sf); + uint32_t offset = 0x08; + + if (flags & 0x01) { + loop_start = read_u32le(offset + 0x00,sf); + loop_end = read_u32le(offset + 0x04,sf); + offset += 0x08; + } + + if ((flags & 0x01) && (flags & 0x02)) { + //00: loop hist related? + offset += 0x04; + } - loop_flag = 0; - channel_count = 1; - start_offset = 0x10; + if (flags & 0x02) { + int count = read_u32le(offset + 0x00,sf); /* not channels */ + // per entry: + // 00: channel related? + // 04: null? + // 0c: ~0x3130? + offset += 0x04 + 0x0c * count; + } + sample_rate = read_u32le(offset + 0x00, sf); + data_size = read_u32le(offset + 0x04, sf); + offset += 0x08; + start_offset = offset; + + if (start_offset + data_size != get_streamfile_size(sf)) + goto fail; + + channels = 1; + loop_flag = loop_end > 0; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_LSF_N1NJ4N; - vgmstream->sample_rate = read_32bitLE(0x08, streamFile); - vgmstream->num_samples = (file_size-0x10)/0x1c*0x1b*2; - vgmstream->coding_type = coding_LSF; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x1c; + vgmstream->sample_rate = sample_rate; + + if (is_v2) { + vgmstream->coding_type = coding_PSX_cfg; + vgmstream->layout_type = layout_none; + vgmstream->frame_size = 0x10; + } + else { + /* custom codec but basically obfuscted PSX-cfg */ + vgmstream->coding_type = coding_LSF; + vgmstream->layout_type = layout_interleave; //TODO: flat but decoder doesn't handle it + vgmstream->interleave_block_size = 0x1c; + vgmstream->frame_size = 0x1c; /* fixed but used below */ + } + + vgmstream->num_samples = ps_cfg_bytes_to_samples(data_size, vgmstream->frame_size, channels); + vgmstream->loop_start_sample = ps_cfg_bytes_to_samples(loop_start, vgmstream->frame_size, channels); + vgmstream->loop_end_sample = ps_cfg_bytes_to_samples(loop_end, vgmstream->frame_size, channels); - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/src/vgmstream.c b/src/vgmstream.c index f864a90be..958120afe 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -1149,13 +1149,6 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o return 1; #endif - if ((vgmstream->coding_type == coding_PSX_cfg || - vgmstream->coding_type == coding_PSX_pivotal) && - (vgmstream->interleave_block_size == 0 || vgmstream->interleave_block_size > 0x50)) { - VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->interleave_block_size); - goto fail; - } - if ((vgmstream->coding_type == coding_CRI_ADX || vgmstream->coding_type == coding_CRI_ADX_enc_8 || vgmstream->coding_type == coding_CRI_ADX_enc_9 || @@ -1168,16 +1161,24 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck || vgmstream->coding_type == coding_MSADPCM_int || - vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono + vgmstream->coding_type == coding_MS_IMA || vgmstream->coding_type == coding_MS_IMA_mono || + vgmstream->coding_type == coding_PSX_cfg || vgmstream->coding_type == coding_PSX_pivotal ) && vgmstream->frame_size == 0) { vgmstream->frame_size = vgmstream->interleave_block_size; } + if ((vgmstream->coding_type == coding_PSX_cfg || + vgmstream->coding_type == coding_PSX_pivotal) && + (vgmstream->frame_size == 0 || vgmstream->frame_size > 0x50)) { + VGM_LOG("VGMSTREAM: PSX-cfg decoder with wrong frame size %x\n", vgmstream->frame_size); + goto fail; + } + if ((vgmstream->coding_type == coding_MSADPCM || vgmstream->coding_type == coding_MSADPCM_ck || vgmstream->coding_type == coding_MSADPCM_int) && - (vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) { + (vgmstream->frame_size == 0 || vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) { VGM_LOG("VGMSTREAM: MSADPCM decoder with wrong frame size %x\n", vgmstream->frame_size); goto fail; } From 1b06bf45d2c8aa3b2ac5d783360828ffcfaff780 Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:02:10 +0200 Subject: [PATCH 076/141] Fix some .seg [Eragon (X360)] --- src/meta/seg.c | 57 ++++++++++++++++++++++++++----------------- src/util/endianness.h | 5 ++++ 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/meta/seg.c b/src/meta/seg.c index 756c92834..43780ba37 100644 --- a/src/meta/seg.c +++ b/src/meta/seg.c @@ -6,11 +6,10 @@ /* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t data_size; + uint32_t start_offset, data_size; + int loop_flag, channels; uint32_t codec; - int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL; + read_u32_t read_u32; /* checks */ @@ -19,19 +18,16 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { if (!check_extensions(sf, "seg")) goto fail; - codec = read_32bitBE(0x04,sf); - /* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */ - if (guess_endian32(0x08,sf)) { - read_32bit = read_32bitBE; - } else { - read_32bit = read_32bitLE; - } + codec = read_u32be(0x04,sf); + /* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Eragon X360, Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */ + read_u32 = guess_read_u32(0x08, sf); + /* 0x0c: file size */ - data_size = read_32bit(0x10, sf); /* including interleave padding */ + data_size = read_u32(0x10, sf); /* including interleave padding */ /* 0x14: null */ - loop_flag = read_32bit(0x20,sf); /* rare */ - channel_count = read_32bit(0x24,sf); + loop_flag = read_u32(0x20,sf); /* rare */ + channels = read_u32(0x24,sf); /* 0x28: extradata 1 entries (0x08 per entry, unknown) */ /* 0x2c: extradata 1 offset */ /* 0x30: extradata 2 entries (0x10 or 0x14 per entry, seek/hist table?) */ @@ -41,12 +37,12 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; vgmstream->meta_type = meta_SEG; - vgmstream->sample_rate = read_32bit(0x18,sf); - vgmstream->num_samples = read_32bit(0x1c,sf); + vgmstream->sample_rate = read_u32(0x18,sf); + vgmstream->num_samples = read_u32(0x1c,sf); if (loop_flag) { vgmstream->loop_start_sample = 0; vgmstream->loop_end_sample = vgmstream->num_samples; @@ -86,14 +82,29 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { #ifdef VGM_USE_FFMPEG case 0x78623300: { /* "xb3\0" */ - int block_size = 0x4000; + /* no apparent flag */ + if (read_u32be(start_offset, sf) == 0) { + /* Eragon (PC) */ + start_offset += 0x20A; /* one frame */ - vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->sample_rate, block_size, 0); - if (!vgmstream->codec_data) goto fail; - vgmstream->coding_type = coding_FFmpeg; - vgmstream->layout_type = layout_none; + mpeg_custom_config cfg = {0}; + + vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, channels, MPEG_STANDARD, &cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->layout_type = layout_none; + } + else { + /* The Spiderwick Chronicles (X360) */ + int block_size = 0x4000; + + vgmstream->codec_data = init_ffmpeg_xma2_raw(sf, start_offset, data_size, vgmstream->num_samples, vgmstream->channels, vgmstream->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, sf, start_offset,data_size, 0, 0,0); /* samples are ok */ + } - xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */ break; } #endif diff --git a/src/util/endianness.h b/src/util/endianness.h index 762d63e1b..ef67ef055 100644 --- a/src/util/endianness.h +++ b/src/util/endianness.h @@ -3,6 +3,7 @@ #include "../streamfile.h" #include "reader_get.h" +#include "reader_sf.h" typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*); typedef int32_t (*read_s32_t)(off_t, STREAMFILE*); @@ -25,4 +26,8 @@ static inline int guess_endian32(off_t offset, STREAMFILE* sf) { return get_u32le(buf) > get_u32be(buf) ? 1 : 0; } +static inline read_u32_t guess_read_u32(off_t offset, STREAMFILE* sf) { + return guess_endian32(0x08,sf) ? read_u32be : read_u32le; +} + #endif From 279b2994d2881007ce816415848641f5606067ca Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:04:03 +0200 Subject: [PATCH 077/141] Fix some broken .bnk [Fat Princess (PS3)] --- src/meta/bnk_sony.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 0d92f4f47..56b66314d 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -11,7 +11,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { uint32_t start_offset, stream_offset, name_offset = 0; uint32_t stream_size, interleave = 0; int channels = 0, loop_flag, sample_rate, big_endian; - int loop_start = 0, loop_end = 0; + int32_t loop_start = 0, loop_end = 0; uint32_t center_note, center_fine, flags; uint32_t atrac9_info = 0; @@ -43,7 +43,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { if (!check_extensions(sf, "bnk")) return NULL; - uint32_t sblk_offset, sblk_size, data_offset, data_size, zlsd_size = 0; + uint32_t sblk_offset, data_offset, data_size; int parts, sblk_version; parts = read_u32(0x04,sf); @@ -51,17 +51,19 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { return NULL; /* in theory a bank can contain multiple blocks */ + /* section sizes don't include padding (sometimes aligned to 0x10/0x800) */ sblk_offset = read_u32(0x08,sf); - sblk_size = read_u32(0x0c,sf); + //sblk_size = read_u32(0x0c,sf); data_offset = read_u32(0x10,sf); data_size = read_u32(0x14,sf); - if (sblk_offset >= 0x20) { - /* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */ - //zlsd_offset = read_u32(0x18,sf); - zlsd_size = read_u32(0x1c,sf); - } - - if (sblk_offset + sblk_size + data_size + zlsd_size != get_streamfile_size(sf)) + + /* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */ + //if (sblk_offset >= 0x20) { + // zlsd_offset = read_u32(0x18,sf); + // zlsd_size = read_u32(0x1c,sf); + //} + + if (sblk_offset > 0x20) return NULL; /* SE banks, also used for music. Most table fields seems reserved/defaults and @@ -231,7 +233,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { } - //;VGM_LOG("BNK: subsongs %i, table2_entry=%lx, table3_entry=%lx\n", total_subsongs,table2_entry_offset,table3_entry_offset); + //;VGM_LOG("BNK: subsongs %i, table2_entry=%x, table3_entry=%x\n", total_subsongs,table2_entry_offset,table3_entry_offset); if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; /* this means some subsongs repeat streams, that can happen in some sfx banks, whatevs */ @@ -322,6 +324,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { break; default: + VGM_LOG("BNK: missing version\n"); goto fail; } @@ -469,8 +472,10 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x02: /* ATRAC9 mono */ case 0x05: /* ATRAC9 stereo */ - if (read_u32(start_offset+0x08,sf) + 0x08 != extradata_size) /* repeat? */ + if (read_u32(start_offset+0x08,sf) + 0x08 != extradata_size) { /* repeat? */ + VGM_LOG("BNK: unknown subtype\n"); goto fail; + } channels = (type == 0x02) ? 1 : 2; atrac9_info = read_u32be(start_offset+0x0c,sf); @@ -493,8 +498,10 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x0f: case 0x10: type = read_u16(start_offset+0x00,sf); - if (read_u32(start_offset+0x04,sf) != 0x01) /* type? */ + if (read_u32(start_offset+0x04,sf) != 0x01) { /* type? */ + VGM_LOG("BNK: unknown subtype\n"); goto fail; + } extradata_size = 0x10 + read_u32(start_offset+0x08,sf); /* 0x80 for AT9, 0x10 for PCM/PS-ADPCM */ /* 0x0c: null? */ From aac716866d0f76890054475f22ebcbb1f705beef Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:04:36 +0200 Subject: [PATCH 078/141] Remove .bd3 extension (use .hd3) Uses .hd3 as the base file for cleaner parsing --- src/formats.c | 2 +- src/meta/hd3_bd3.c | 221 +++++++++++++++++++++------------------------ 2 files changed, 102 insertions(+), 121 deletions(-) diff --git a/src/formats.c b/src/formats.c index ad8041922..c464597f2 100644 --- a/src/formats.c +++ b/src/formats.c @@ -99,7 +99,6 @@ static const char* extension_list[] = { "bcstm", "bcwav", "bcv", //txth/reserved [The Bigs (PSP)] - "bd3", "bfstm", "bfwav", "bg00", @@ -216,6 +215,7 @@ static const char* extension_list[] = { "h4m", "hab", "hca", + "hd3", "hdr", "hdt", "hgc1", diff --git a/src/meta/hd3_bd3.c b/src/meta/hd3_bd3.c index c69f2ad94..44e0cc6f1 100644 --- a/src/meta/hd3_bd3.c +++ b/src/meta/hd3_bd3.c @@ -1,120 +1,101 @@ -#include "meta.h" -#include "../coding/coding.h" - - /* HD3+BD3 - Sony PS3 bank format [Elevator Action Deluxe (PS3), R-Type Dimensions (PS3)] */ -VGMSTREAM * init_vgmstream_hd3_bd3(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * streamHeader = NULL; - off_t start_offset; - int channel_count, loop_flag, sample_rate; - size_t interleave, stream_size; - int total_subsongs, target_subsong = streamFile->stream_index; - - - /* checks */ - if (!check_extensions(streamFile, "bd3")) - goto fail; - - streamHeader = open_streamfile_by_ext(streamFile,"hd3"); - if (!streamHeader) goto fail; - - if (read_32bitBE(0x00,streamHeader) != 0x50334844) /* "P3HD" */ - goto fail; - - /* 0x04: section size (not including first 0x08) */ - /* 0x08: version? 0x00020000 */ - /* 0x10: "P3PG" offset (seems mostly empty and contains number of subsongs towards the end) */ - /* 0x14: "P3TN" offset (some kind of config?) */ - /* 0x18: "P3VA" offset (VAG headers) */ - { - off_t section_offset = read_32bitBE(0x18,streamHeader); - off_t header_offset; - size_t section_size; - int i, entries, is_bgm = 0; - - if (read_32bitBE(section_offset+0x00,streamHeader) != 0x50335641) /* "P3VA" */ - goto fail; - section_size = read_32bitBE(section_offset+0x04,streamHeader); /* (not including first 0x08) */ - /* 0x08 size of all subsong headers + 0x10 */ - - entries = read_32bitBE(section_offset+0x14,streamHeader); - /* often there is an extra subsong than written, but may be padding instead */ - if (read_32bitBE(section_offset + 0x20 + entries*0x10 + 0x04,streamHeader)) /* has sample rate */ - entries += 1; - - if (entries * 0x10 > section_size) /* just in case, padding after entries is possible */ - goto fail; - - /* autodetect use of N bank entries as channels [Elevator Action Deluxe (PS3)] */ - if (entries > 1) { - size_t channel_size = read_32bitBE(section_offset+0x20+0x08,streamHeader); - is_bgm = 1; - - for (i = 1; i < entries; i++) { - size_t next_size = read_32bitBE(section_offset+0x20+(i*0x10)+0x08,streamHeader); - if (channel_size != next_size) { - is_bgm = 0; - break; - } - } - } - - if (is_bgm) { - total_subsongs = 1; - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - header_offset = section_offset+0x20+(0)*0x10; - start_offset = read_32bitBE(header_offset+0x00,streamHeader); /* 0x00 */ - sample_rate = read_32bitBE(header_offset+0x04,streamHeader); - stream_size = get_streamfile_size(streamFile); - if (read_32bitBE(header_offset+0x0c,streamHeader) != -1) - goto fail; - - channel_count = entries; - interleave = stream_size / channel_count; - } - else { - total_subsongs = entries; - if (target_subsong == 0) target_subsong = 1; - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - - header_offset = section_offset+0x20+(target_subsong-1)*0x10; - start_offset = read_32bitBE(header_offset+0x00,streamHeader); - sample_rate = read_32bitBE(header_offset+0x04,streamHeader); - stream_size = read_32bitBE(header_offset+0x08,streamHeader); - if (read_32bitBE(header_offset+0x0c,streamHeader) != -1) - goto fail; - - channel_count = 1; - interleave = 0; - } - } - - loop_flag = 0; - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = ps_bytes_to_samples(stream_size, channel_count); - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; - - vgmstream->meta_type = meta_HD3_BD3; - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = (channel_count == 1) ? layout_none : layout_interleave; - vgmstream->interleave_block_size = interleave; - - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; - - close_streamfile(streamHeader); - return vgmstream; -fail: - close_streamfile(streamHeader); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + /* HD3+BD3 - Sony PS3 bank format [Elevator Action Deluxe (PS3), R-Type Dimensions (PS3)] */ +VGMSTREAM* init_vgmstream_hd3_bd3(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + uint32_t stream_offset, stream_size; + int channels, loop_flag, sample_rate, interleave; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00,sf, "P3HD")) + return NULL; + if (!check_extensions(sf, "hd3")) + return NULL; + + sb = open_streamfile_by_ext(sf,"bd3"); + if (!sf) goto fail; + + /* 0x04: section size (not including first 0x08) */ + /* 0x08: version? 0x00020000 */ + /* 0x10: "P3PG" offset (seems mostly empty and contains number of subsongs towards the end) */ + /* 0x14: "P3TN" offset (some kind of config/volumes/etc?) */ + /* 0x18: "P3VA" offset (VAG headers) */ + { + uint32_t section_offset = read_u32be(0x18,sf); + uint32_t section_size; + int entries; + + if (!is_id32be(section_offset+0x00,sf, "P3VA")) + goto fail; + section_size = read_u32be(section_offset+0x04,sf); /* (not including first 0x08) */ + /* 0x08 size of all subsong headers + 0x10 */ + + entries = read_u32be(section_offset+0x14,sf); + /* often there is an extra subsong than written, but may be padding instead */ + if (read_u32be(section_offset + 0x20 + entries*0x10 + 0x04,sf)) /* has sample rate */ + entries += 1; + + if (entries * 0x10 > section_size) /* just in case, padding after entries is possible */ + goto fail; + + /* very often subsongs make stereo pairs (even with many), this detects simple cases */ //TODO check if there is some flag or remove hack + bool is_bgm = false; + if (entries == 2) { + uint32_t curr_size = read_u32be(section_offset+0x20+(0*0x10)+0x08,sf); + uint32_t next_size = read_u32be(section_offset+0x20+(1*0x10)+0x08,sf); + is_bgm = (curr_size == next_size); + } + + if (is_bgm) { + total_subsongs = 1; + channels = entries; + } + else { + total_subsongs = entries; + channels = 1; + } + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; + + uint32_t header_offset = section_offset+0x20+(target_subsong-1)*0x10; + stream_offset = read_u32be(header_offset+0x00,sf); + sample_rate = read_u32be(header_offset+0x04,sf); + stream_size = read_u32be(header_offset+0x08,sf) * channels; + interleave = stream_size / channels; + if (read_s32be(header_offset+0x0c,sf) != -1) + goto fail; + } + + loop_flag = 0; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = ps_bytes_to_samples(stream_size, channels); + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + vgmstream->meta_type = meta_HD3_BD3; + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = (channels == 1) ? layout_none : layout_interleave; + vgmstream->interleave_block_size = interleave; + + if (!vgmstream_open_stream(vgmstream, sb, stream_offset)) + goto fail; + + close_streamfile(sb); + return vgmstream; +fail: + close_streamfile(sb); + close_vgmstream(vgmstream); + return NULL; +} From e1c7c380930fb6c1cbb1e8572cb1acc872f58ce0 Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:06:25 +0200 Subject: [PATCH 079/141] Add .imf extension [Colors (Gizmondo)] --- src/formats.c | 1 + src/meta/mpeg.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/formats.c b/src/formats.c index c464597f2..1bbb26fdb 100644 --- a/src/formats.c +++ b/src/formats.c @@ -249,6 +249,7 @@ static const char* extension_list[] = { "ilv", //txth/reserved [Star Wars Episode III (PS2)] "ima", "imc", + "imf", "imx", "int", "is14", diff --git a/src/meta/mpeg.c b/src/meta/mpeg.c index 0e6de8ab3..95b08de02 100644 --- a/src/meta/mpeg.c +++ b/src/meta/mpeg.c @@ -34,8 +34,11 @@ VGMSTREAM* init_vgmstream_mpeg(STREAMFILE* sf) { /* .mp3/mp2: standard * .lmp3/lmp2: for plugins - * .mus: Marc Ecko's Getting Up (PC) */ - if (!check_extensions(sf, "mp3,mp2,lmp3,lmp2,mus")) + * .mus: Marc Ecko's Getting Up (PC) + * .imf: Colors (Gizmondo) + * .aix: Classic Compendium 2 (Gizmondo) + * (extensionless): Interstellar Flames 2 (Gizmondo) */ + if (!check_extensions(sf, "mp3,mp2,lmp3,lmp2,mus,imf,aix,,")) goto fail; loop_flag = 0; From a4484b5082347a6bf443deaad1a410fe535682a4 Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:09:48 +0200 Subject: [PATCH 080/141] cleanup: ps2_msa to msa --- src/formats.c | 6 +-- src/libvgmstream.vcxproj | 4 +- src/libvgmstream.vcxproj.filters | 12 +++--- src/meta/meta.h | 2 +- src/meta/msa.c | 62 +++++++++++++++++++++++++++++++ src/meta/ps2_msa.c | 63 -------------------------------- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 8 files changed, 76 insertions(+), 77 deletions(-) create mode 100644 src/meta/msa.c delete mode 100644 src/meta/ps2_msa.c diff --git a/src/formats.c b/src/formats.c index 1bbb26fdb..29e936fcb 100644 --- a/src/formats.c +++ b/src/formats.c @@ -845,7 +845,7 @@ static const coding_info coding_info_list[] = { {coding_TGC, "Tiger Game.com 4-bit ADPCM"}, {coding_NDS_PROCYON, "Procyon Studio Digital Sound Elements NDS 4-bit APDCM"}, {coding_L5_555, "Level-5 0x555 4-bit ADPCM"}, - {coding_LSF, "lsf 4-bit ADPCM"}, + {coding_LSF, "Gizmondo Studios Helsingborg LSF 4-bit ADPCM"}, {coding_MTAF, "Konami MTAF 4-bit ADPCM"}, {coding_MTA2, "Konami MTA2 4-bit ADPCM"}, {coding_MC3, "Paradigm MC3 3-bit ADPCM"}, @@ -1174,7 +1174,7 @@ static const meta_info meta_info_list[] = { {meta_SSS, "Namco .SSS raw header"}, {meta_PS2_GCM, "Namco GCM header"}, {meta_SMPL, "Skonec SMPL header"}, - {meta_PS2_MSA, "Success .MSA header"}, + {meta_MSA, "Success .MSA header"}, {meta_VOI, "Irem .VOI header"}, {meta_NGC_PDT, "Hudson .PDT header"}, {meta_NGC_RKV, "Legacy of Kain - Blood Omen 2 RKV GC header"}, @@ -1208,7 +1208,7 @@ static const meta_info meta_info_list[] = { {meta_VGS_PS, "Princess Soft VGS header"}, {meta_PS2_IAB, "Runtime .IAB header"}, {meta_VS_STR, "Square .VS STRx header"}, - {meta_LSF_N1NJ4N, ".lsf !n1nj4n header"}, + {meta_LSF_N1NJ4N, "Gizmondo Studios Helsingborg LSF header"}, {meta_XWAV, "feelplus XWAV header"}, {meta_RAW_SNDS, "PC .snds raw header"}, {meta_PS2_WMUS, "assumed The Warriors Sony ADPCM by .wmus extension"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index c4513674d..8411cadd7 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -484,6 +484,7 @@ + @@ -562,7 +563,6 @@ - @@ -599,9 +599,9 @@ + - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 202b8f69d..f774e7d42 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1273,6 +1273,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1507,9 +1510,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1618,13 +1618,13 @@ meta\Source Files - + meta\Source Files - + meta\Source Files - + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index a6a9fd935..cd4e0c19f 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -443,7 +443,7 @@ VGMSTREAM * init_vgmstream_ps2_gcm(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_smpl(STREAMFILE* sf); -VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_msa(STREAMFILE* sf); VGMSTREAM* init_vgmstream_voi(STREAMFILE* sf); diff --git a/src/meta/msa.c b/src/meta/msa.c new file mode 100644 index 000000000..2c8683d91 --- /dev/null +++ b/src/meta/msa.c @@ -0,0 +1,62 @@ +#include "meta.h" +#include "../coding/coding.h" + +/* MSA - from Sucess games [Psyvariar -Complete Edition- (PS2), Konohana Pack: 3tsu no Jikenbo (PS2)]*/ +VGMSTREAM* init_vgmstream_msa(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, data_size, channel_size, file_size; + int loop_flag, channels; + + + /* checks */ + if (read_u32be(0x00,sf) != 0x00000000 || read_u32be(0x08,sf) != 0x00000000) + return NULL; + if (!check_extensions(sf, "msa")) + return NULL; + + loop_flag = 0; + channels = 2; + start_offset = 0x14; + + file_size = get_streamfile_size(sf); + data_size = read_u32le(0x04,sf); /* wrong, see below */ + channel_size = read_u32le(0x0c,sf); /* also wrong like data_size */ + + if (!ps_check_format(sf, start_offset, 0x100)) + return NULL; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_MSA; + vgmstream->sample_rate = read_s32le(0x10,sf); + if (vgmstream->sample_rate == 0) /* ex. Psyvariar's AME.MSA */ + vgmstream->sample_rate = 44100; + vgmstream->num_samples = ps_bytes_to_samples(data_size, channels); + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + + if (channel_size) /* Konohana Pack */ + vgmstream->interleave_block_size = 0x6000; + else /* Psyvariar */ + vgmstream->interleave_block_size = 0x4000; + + /* MSAs are strangely truncated, so manually calculate samples. + * Data after last usable block is always silence or garbage. */ + if (data_size > file_size) { + uint32_t usable_size = file_size - start_offset; + usable_size -= usable_size % (vgmstream->interleave_block_size * channels); /* block-aligned */ + vgmstream->num_samples = ps_bytes_to_samples(usable_size, channels); + } + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/ps2_msa.c b/src/meta/ps2_msa.c deleted file mode 100644 index c54146b5c..000000000 --- a/src/meta/ps2_msa.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "meta.h" -#include "../coding/coding.h" - -/* MSA - from Sucess games [Psyvariar -Complete Edition- (PS2), Konohana Pack: 3tsu no Jikenbo (PS2)]*/ -VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - off_t start_offset; - int loop_flag, channel_count; - size_t data_size, channel_size, file_size; - - - /* checks */ - if (!check_extensions(streamFile, "msa")) - goto fail; - if (read_32bitBE(0x00,streamFile) != 0x00000000) - goto fail; - if (read_32bitBE(0x08,streamFile) != 0x00000000) - goto fail; - - loop_flag = 0; - channel_count = 2; - start_offset = 0x14; - - file_size = get_streamfile_size(streamFile); - data_size = read_32bitLE(0x04,streamFile); /* wrong, see below */ - channel_size = read_32bitLE(0x0c,streamFile); /* also wrong like data_size */ - - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - vgmstream->meta_type = meta_PS2_MSA; - vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - if (vgmstream->sample_rate == 0) /* ex. Psyvariar's AME.MSA */ - vgmstream->sample_rate = 44100; - vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count); - - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_interleave; - - if (channel_size) /* Konohana Pack */ - vgmstream->interleave_block_size = 0x6000; - else /* Psyvariar */ - vgmstream->interleave_block_size = 0x4000; - /* (could also test first frame in various interleaves, as it's always 0'ed) */ - - /* MSAs are strangely truncated, so manually calculate samples. - * Data after last usable block is always silence or garbage. */ - if (data_size > file_size) { - off_t usable_size = file_size - start_offset; - usable_size -= usable_size % (vgmstream->interleave_block_size*channel_count);/* block-aligned */ - vgmstream->num_samples = ps_bytes_to_samples(usable_size, channel_count);//usable_size * 28 / (16*channel_count); - } - - if (!vgmstream_open_stream(vgmstream, streamFile, start_offset)) - goto fail; - return vgmstream; - -fail: - close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index 958120afe..a72613381 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -206,7 +206,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_bnsf, init_vgmstream_ps2_gcm, init_vgmstream_smpl, - init_vgmstream_ps2_msa, + init_vgmstream_msa, init_vgmstream_voi, init_vgmstream_ngc_rkv, init_vgmstream_dsp_ddsp, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 37d1a7861..2e75428c9 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -461,7 +461,7 @@ typedef enum { meta_SSS, /* raw Siren 14, 48kbit stereo */ meta_PS2_GCM, /* NamCollection */ meta_SMPL, - meta_PS2_MSA, /* Psyvariar -Complete Edition- */ + meta_MSA, meta_VOI, meta_P3D, /* Prototype P3D */ meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */ From afec01d6fdcff726f21f9e47871e37675d722b3e Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:19:54 +0200 Subject: [PATCH 081/141] Remove .lrmb extension (use .lrmh) Uses .lrmh as the base file for cleaner parsing --- src/formats.c | 2 +- src/meta/lrmd.c | 63 ++++++++++++++++++++++++++----------------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/src/formats.c b/src/formats.c index 29e936fcb..52930fd1d 100644 --- a/src/formats.c +++ b/src/formats.c @@ -316,7 +316,7 @@ static const char* extension_list[] = { "lpcm", "lpk", "lps", - "lrmb", + "lrmh", "lse", "lsf", "lstm", //fake extension for .stm diff --git a/src/meta/lrmd.c b/src/meta/lrmd.c index 4792884ec..a5a1ab3c5 100644 --- a/src/meta/lrmd.c +++ b/src/meta/lrmd.c @@ -3,9 +3,10 @@ #include "lrmd_streamfile.h" /* LRMD - Sony/SCEI's format (Loco Roco Music Data?) [LocoRoco 2 (PSP), LocoRoco: Midnight Carnival (PSP)] */ -VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { - VGMSTREAM * vgmstream = NULL; - STREAMFILE * sf_h = NULL, *temp_sf = NULL; +VGMSTREAM* init_vgmstream_lrmd(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + STREAMFILE* temp_sf = NULL; off_t stream_offset, section1_offset, section2_offset, basename_offset, subname_offset; size_t stream_size, max_chunk, block_size = 0, chunk_start, chunk_size; int loop_flag, channel_count, sample_rate, layers; @@ -14,39 +15,41 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { /* checks */ - if (!check_extensions(sf, "lrmb")) - goto fail; - sf_h = open_streamfile_by_ext(sf, "lrmh"); - if (!sf_h) goto fail; - - - if (read_u32be(0x00, sf_h) != 0x4C524D44) /* "LRMD" */ - goto fail; + if (!is_id32be(0x00, sf, "LRMD")) + return NULL; /* 0x00: version 1? */ /* 0x08: header size */ /* 0x0c: body size */ - if (read_u32be(0x10, sf_h) != 0x52455144) /* "REQD" */ - goto fail; + if (!is_id32be(0x10, sf, "REQD")) + return NULL; /* 0x14: chunk size */ /* 0x18: null? */ /* 0x1c: 1? */ + + /* .lrmh+lrmb: actual extensions */ + if (!check_extensions(sf, "lrmh")) + goto fail; + + sb = open_streamfile_by_ext(sf, "lrmb"); + if (!sb) goto fail; + /* 0x20: null */ - basename_offset = read_u32le(0x24, sf_h); - if (read_u16le(0x28, sf_h) != 0x4000) { /* pitch? */ + basename_offset = read_u32le(0x24, sf); + if (read_u16le(0x28, sf) != 0x4000) { /* pitch? */ VGM_LOG("LRMD: unknown value\n"); goto fail; } - max_chunk = read_u16le(0x2a, sf_h); - num_samples = read_u32le(0x2c, sf_h); + max_chunk = read_u16le(0x2a, sf); + num_samples = read_u32le(0x2c, sf); /* 0x30: null? */ /* 0x34: data size for all layers */ - layers = read_u32le(0x38, sf_h); - section1_offset = read_u32le(0x3c, sf_h); + layers = read_u32le(0x38, sf); + section1_offset = read_u32le(0x3c, sf); /* 0x40: lip table entries */ /* 0x44: lip table offset */ /* 0x48: section2 flag */ - section2_offset = read_u32le(0x4c, sf_h); + section2_offset = read_u32le(0x4c, sf); /* 0x40: section3 flag */ /* 0x44: section3 (unknown) */ @@ -68,11 +71,11 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { int layer_channels; /* not too sure but needed for LR2's muihouse last 3 layers */ - layer_channels = read_u8(header_offset + 0x0d, sf_h) != 0 ? 1 : 2; + layer_channels = read_u8(header_offset + 0x0d, sf) != 0 ? 1 : 2; if (i + 1 == target_subsong) { /* 0x00: null */ - subname_offset = read_u32le(header_offset + 0x04, sf_h); + subname_offset = read_u32le(header_offset + 0x04, sf); /* 0x08: unk */ /* 0x0c: flags? */ /* 0x10: null? */ @@ -94,9 +97,9 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { /* section2: loops */ /* 0x00: offset to "loop" name */ if (section2_offset > 0) { - loop_end = read_u32le(section2_offset + 0x04, sf_h); - loop_start = read_u32le(section2_offset + 0x08, sf_h); - loop_flag = read_u32le(section2_offset + 0x0c, sf_h); + loop_end = read_u32le(section2_offset + 0x04, sf); + loop_start = read_u32le(section2_offset + 0x08, sf); + loop_flag = read_u32le(section2_offset + 0x0c, sf); } else { loop_end = 0; @@ -106,7 +109,7 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { /* data de-interleave */ - temp_sf = setup_lrmd_streamfile(sf, block_size, chunk_start, chunk_size); + temp_sf = setup_lrmd_streamfile(sb, block_size, chunk_start, chunk_size); if (!temp_sf) goto fail; stream_offset = 0x00; @@ -142,23 +145,23 @@ VGMSTREAM * init_vgmstream_lrmd(STREAMFILE *sf) { /* name custom main + layer name */ { - int name_len = read_string(vgmstream->stream_name, STREAM_NAME_SIZE - 1, basename_offset, sf_h); + int name_len = read_string(vgmstream->stream_name, STREAM_NAME_SIZE - 1, basename_offset, sf); strcat(vgmstream->stream_name, "/"); name_len++; - read_string(vgmstream->stream_name + name_len, STREAM_NAME_SIZE - name_len, subname_offset, sf_h); + read_string(vgmstream->stream_name + name_len, STREAM_NAME_SIZE - name_len, subname_offset, sf); } if (!vgmstream_open_stream(vgmstream, temp_sf, stream_offset)) goto fail; - close_streamfile(sf_h); + close_streamfile(sb); close_streamfile(temp_sf); return vgmstream; fail: - close_streamfile(sf_h); + close_streamfile(sb); close_streamfile(temp_sf); close_vgmstream(vgmstream); return NULL; From 6024d32a6e3a1812c97fd2db25eedc94b241535b Mon Sep 17 00:00:00 2001 From: bnnm Date: Fri, 30 Jun 2023 23:22:36 +0200 Subject: [PATCH 082/141] cleanup: stm to stma --- src/formats.c | 2 +- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 2 +- src/meta/meta.h | 2 +- src/meta/{stm.c => stma.c} | 6 +++--- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) rename src/meta/{stm.c => stma.c} (96%) diff --git a/src/formats.c b/src/formats.c index 52930fd1d..ad1cb1de8 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1261,7 +1261,7 @@ static const meta_info meta_info_list[] = { {meta_EA_BNK, "Electronic Arts BNK header"}, {meta_SK_AUD, "Silicon Knights AUD header"}, {meta_AHX, "CRI AHX header"}, - {meta_STM, "Angel Studios/Rockstar San Diego STMA header"}, + {meta_STMA, "Angel Studios/Rockstar San Diego STMA header"}, {meta_BINK, "RAD Game Tools Bink header"}, {meta_EA_SNU, "Electronic Arts SNU header"}, {meta_AWC, "Rockstar AWC header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 8411cadd7..6511f92df 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -642,7 +642,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f774e7d42..f78b80a9b 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1747,7 +1747,7 @@ meta\Source Files - + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index cd4e0c19f..771369c86 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -615,7 +615,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_sk_aud(STREAMFILE * streamFile); -VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_stma(STREAMFILE* sf); VGMSTREAM * init_vgmstream_awc(STREAMFILE * streamFile); diff --git a/src/meta/stm.c b/src/meta/stma.c similarity index 96% rename from src/meta/stm.c rename to src/meta/stma.c index d766deef9..33988bcae 100644 --- a/src/meta/stm.c +++ b/src/meta/stma.c @@ -2,7 +2,7 @@ #include "../coding/coding.h" /* STM - from Angel Studios/Rockstar San Diego games [Red Dead Revolver (PS2), Spy Hunter 2 (PS2/Xbox)] */ -VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_stma(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset; int loop_flag = 0, channel_count; @@ -65,7 +65,7 @@ VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) { if (!vgmstream) goto fail; vgmstream->sample_rate = read_32bit(0xc,sf); - vgmstream->meta_type = meta_STM; + vgmstream->meta_type = meta_STMA; vgmstream->layout_type = (channel_count > 1) ? layout_interleave : layout_none; switch(bps) { @@ -109,7 +109,7 @@ VGMSTREAM* init_vgmstream_stm(STREAMFILE* sf) { } - if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; return vgmstream; diff --git a/src/vgmstream.c b/src/vgmstream.c index a72613381..dbd4b1d94 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -305,7 +305,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ea_mpf_mus, init_vgmstream_ea_schl_fixed, init_vgmstream_sk_aud, - init_vgmstream_stm, + init_vgmstream_stma, init_vgmstream_ea_snu, init_vgmstream_awc, init_vgmstream_opus_std, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 2e75428c9..01e232e84 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -544,7 +544,7 @@ typedef enum { meta_TXTH, /* generic text header */ meta_SK_AUD, /* Silicon Knights .AUD (Eternal Darkness GC) */ meta_AHX, - meta_STM, /* Angel Studios/Rockstar San Diego Games */ + meta_STMA, meta_BINK, /* RAD Game Tools BINK audio/video */ meta_EA_SNU, /* Electronic Arts SNU (Dead Space) */ meta_AWC, /* Rockstar AWC (GTA5, RDR) */ From fc6efd7afa2f0e079adcbe05ccbe8ee63ccffb91 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 1 Jul 2023 00:47:55 +0200 Subject: [PATCH 083/141] Remove fake extension .bh2pcm (use .dat + TXTH) --- src/formats.c | 1 - src/libvgmstream.vcxproj | 1 - src/libvgmstream.vcxproj.filters | 3 -- src/meta/meta.h | 2 - src/meta/ngc_bh2pcm.c | 87 -------------------------------- src/vgmstream.c | 1 - src/vgmstream_types.h | 1 - 7 files changed, 96 deletions(-) delete mode 100644 src/meta/ngc_bh2pcm.c diff --git a/src/formats.c b/src/formats.c index ad1cb1de8..8d17e398a 100644 --- a/src/formats.c +++ b/src/formats.c @@ -104,7 +104,6 @@ static const char* extension_list[] = { "bg00", "bgm", "bgw", - "bh2pcm", "bigrp", "bik", "bika", //fake extension for .bik (to be removed) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 6511f92df..35a59e1e1 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -508,7 +508,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index f78b80a9b..9cf33c329 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1345,9 +1345,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 771369c86..69b455cfa 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -275,8 +275,6 @@ VGMSTREAM * init_vgmstream_xmu(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_xvas(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_sat_sap(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile); diff --git a/src/meta/ngc_bh2pcm.c b/src/meta/ngc_bh2pcm.c deleted file mode 100644 index 9fe0d3f77..000000000 --- a/src/meta/ngc_bh2pcm.c +++ /dev/null @@ -1,87 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* BH2PCM (from Bio Hazard 2) */ -VGMSTREAM * init_vgmstream_ngc_bh2pcm(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int channel_count; - int format_detect; - int loop_flag; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bh2pcm",filename_extension(filename))) goto fail; - -#if 0 - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x00000000) - goto fail; -#endif - - loop_flag = 0; - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - format_detect=read_32bitLE(0x00,streamFile); - switch (format_detect) { - case 1: - start_offset = 0x20; - channel_count = 2; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 32000; - vgmstream->num_samples = read_32bitLE(0x04,streamFile)/2; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x04,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile); - } - break; - case 0: - start_offset = 0x20; - channel_count = 1; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 32000; - vgmstream->num_samples = read_32bitLE(0x0C,streamFile); - vgmstream->layout_type = layout_none; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x08,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x0C,streamFile); - } - break; - default: - goto fail; - } - - vgmstream->coding_type = coding_PCM16BE; - vgmstream->meta_type = meta_NGC_BH2PCM; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index dbd4b1d94..866e40a71 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -115,7 +115,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_dc_str_v2, init_vgmstream_xmu, init_vgmstream_xvas, - init_vgmstream_ngc_bh2pcm, init_vgmstream_sat_sap, init_vgmstream_dc_idvi, init_vgmstream_ps2_rnd, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 01e232e84..028730216 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -348,7 +348,6 @@ typedef enum { meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ meta_DC_STR, /* SEGA Stream Asset Builder */ meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */ - meta_NGC_BH2PCM, /* Bio Hazard 2 */ meta_SAP, meta_DC_IDVI, /* Eldorado Gate */ meta_KRAW, /* Geometry Wars - Galaxies */ From e8f495f15ea953ea72a0daf8f040bf9de232bfaa Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 1 Jul 2023 01:32:43 +0200 Subject: [PATCH 084/141] cleanup: tweak formats generator --- .github/formats-info.py | 133 +- doc/FORMATS.md | 3534 +++++++++++++++++++-------------------- doc/TXTH.md | 4 +- 3 files changed, 1879 insertions(+), 1792 deletions(-) diff --git a/.github/formats-info.py b/.github/formats-info.py index e7f74ae2a..03c525c5d 100644 --- a/.github/formats-info.py +++ b/.github/formats-info.py @@ -3,19 +3,23 @@ import glob, os, re -#TODO maybe sort by meta order list in vgmstream.c -#TODO fix ??? descriptions #TODO fix some "ext + ext" exts -#TODO improve some ubi formats +#TODO improve dsp/ubi/ea formats #TODO detect subfile/init_x calls that aren't VGMSTREAM * init_ #TODO detect MPEG_x, OPUS_x subtypes -#TODO ignore some check extensions -#TODO include common idstrings (first is_id32be() / is_id32le / get_id32be / get_id32be) +#TODO ignore some check extensions? +#TODO maybe include common idstrings (first is_id32be() / is_id32le / get_id32be / get_id32be) # > after first valid init? -META_FILES = '../**/meta/*.c' -FORMAT_FILES = '../**/formats.c' -IS_PRINT_INFO = False #false = write +META_SRC = '../**/meta/*.c' +FORMAT_SRC = '../**/formats.c' +SORT_SRC = '../**/vgmstream.c' +FORMAT_DOC = '../**/FORMATS.md' +DUMP_DOC = 'formats-info.md' +IS_SORT = True #sorts metas lines based on LIST_SRC +IS_PRINT_DOC = False #echo list +IS_DUMP_DOC = False #creates DUMP_DOC +IS_UPDATE_DOC = True #updates FORMAT_DOC #VGMSTREAM * init_vgmstream_9tav(STREAMFILE *sf) #allow static since it's used in some cases RE_INIT = re.compile(r"VGMSTREAM[ ]*\*[ ]*init_vgmstream_([A-Za-z0-9_]+)\(.+\)") @@ -41,10 +45,13 @@ # formats.c extract RE_FORMATS_META = re.compile(r"{meta_([A-Z0-9][A-Za-z0-9_]+)[ ]*,[ ]* \"(.+)\"[ ]*}") +# vgmstream.c meta call extract +RE_SORT_INIT = re.compile(r"[ ]+init_vgmstream_([A-Za-z0-9_]+),") + FILES_SKIP = [ 'txth.c','txtp.c','genh.c', 'silence.c', 'mp4_faac.c', 'deblock_streamfile.c', - 'ps_headerless.c', 'zwdsp.c', 'ngc_bh2pcm.c', + 'ps_headerless.c', 'zwdsp.c', ] EXT_RENAMES = {'...': '(any)', '': '(extensionless)'} @@ -53,8 +60,7 @@ CODING_IGNORES = ['coding_type', 'coding_t', 'FFmpeg', 'SILENCE'] SUBFILES_IGNORES = ['subkey', 'silence', 'silence_container'] - -# various codecs that +# detect better various codecs that use a generic coding_XXX INIT_CODECS = { re.compile(r'init_ffmpeg_aac\('): 'AAC', re.compile(r'init_ffmpeg_xwma\('): 'XWMA', @@ -86,6 +92,7 @@ def is_used(self): class MetaFile: def __init__(self, file): self.fileinfo = os.path.basename(file) + self.order = 9999 # divide each file into sub-metas since some .c have a bunch of them self.curr = MetaInit('default') #shouldn't be used but... self.inits = [self.curr] @@ -132,6 +139,7 @@ class App: def __init__(self): self.infos = [] self.desc_metas = {} + self.lines = [] def extract_extensions(self, line): @@ -160,7 +168,7 @@ def extract_codecs(self, line): def parse_files(self): infos = self.infos - files = glob.glob(META_FILES, recursive=True) + files = glob.glob(META_SRC, recursive=True) for file in files: info = MetaFile(file) with open(file, 'r', encoding='utf-8') as f: @@ -201,7 +209,8 @@ def parse_files(self): def parse_formats(self): desc_metas = self.desc_metas - files = glob.glob(FORMAT_FILES, recursive=True) + + files = glob.glob(FORMAT_SRC, recursive=True) for file in files: with open(file, 'r', encoding='utf-8') as f: for line in f: @@ -210,13 +219,41 @@ def parse_formats(self): continue meta, desc = items[0] desc_metas[meta] = desc - - def print(self): + def sort_files(self): + inits_order = {} + + # get process list order + files = glob.glob(SORT_SRC, recursive=True) + order = 0 + for file in files: + with open(file, 'r', encoding='utf-8') as f: + for line in f: + items = self.extract_regex(line, RE_SORT_INIT) + if not items or len(items) != 1: + continue + init = items[0] + inits_order[init] = order + order += 1 + + # update (could be done on first pass or maybe in sort() but it's a bit specialized) + infos = self.infos + for info in infos: + for init in info.inits: + order = inits_order.get(init.name) + #print(init, order) + if order is not None and info.order > order: + info.order = order + + infos.sort(key=lambda x: x.order) #, reverse=True + + + def prepare_results(self): desc_metas = self.desc_metas infos = self.infos - lines = [] + + lines = self.lines for info in infos: #info.sort() if info.fileinfo in FILES_SKIP: @@ -228,7 +265,6 @@ def print(self): # fileinfo += " (%s)" % (metas) lines.append(fileinfo) - if info.metas: for meta in info.metas: desc = desc_metas.get(meta, '???') @@ -267,16 +303,67 @@ def print(self): #lines.append('') - if IS_PRINT_INFO: - print('\n'.join(lines)) - else: - with open('formats-info.md', 'w', encoding='utf-8') as f: - f.write('\n'.join(lines)) + + def update_doc(self): + new_lines = self.lines + + files = glob.glob(FORMAT_DOC, recursive=True) + if not files: + print("format doc (%s) not found" % FORMAT_DOC) + return + + doc_lines = [] + file = files[0] + with open(file, 'r', encoding='utf-8') as f: + is_updating = False + for line in f: + line = line.strip() + + # find list section, add all current lines and ignore old ones until next section + if line.startswith('### List'): + is_updating = True + doc_lines.append(line) + doc_lines += new_lines + doc_lines.append('') + continue + + # next section + if is_updating and line.startswith('#'): + is_updating = False + + if not is_updating: + doc_lines.append(line) + + with open(file, 'w', encoding='utf-8', newline='\n') as f: + f.write('\n'.join(doc_lines)) + + + def dump_doc(self): + lines = self.lines + + with open(DUMP_DOC, 'w', encoding='utf-8') as f: + f.write('\n'.join(lines)) + + + def print_doc(self): + lines = self.lines + print('\n'.join(lines)) + def process(self): self.parse_files() self.parse_formats() - self.print() + if IS_SORT: + self.sort_files() + + self.prepare_results() + + if IS_PRINT_DOC: + self.print_doc() + if IS_DUMP_DOC: + self.dump_doc() + if IS_UPDATE_DOC: + self.update_doc() App().process() diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 2f2ea7d59..28cc1d8d3 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -2,7 +2,7 @@ ## Supported formats The following list is auto-generated, and may be missing a few things, but should give -you an idea of what vgmstream supports. +you an idea of what vgmstream supports. Keep in mind that while the extension is the most obvious way to identify files, different formats can reuse them (a `.wav` could be a standard Windows WAV, or many @@ -24,72 +24,6 @@ a supported that don't play feel free to report. Often it means the format may b different internally (encrypted, different versions, etc) and not always can be fixed. ### List -- **208.c** - - Ocean .208 header [*208*] - - *208*: `.208` - - Codecs: PCM8_U -- **2dx9.c** - - beatmania IIDX 2DX9 header [*2DX9*] - - *2dx9*: `.2dx9` - - Codecs: MSADPCM -- **9tav.c** - - Konami 9TAV header [*9TAV*] - - *9tav*: `.9tav` - - Codecs: ATRAC9 -- **a2m.c** - - Artificial Mind & Movement A2M header [*A2M*] - - *a2m*: `.int` - - Codecs: PSX -- **aac_triace.c** - - tri-Ace AAC header [*AAC_TRIACE*] - - *aac_triace*: `.aac .laac` - - Codecs: XMA2 ATRAC3 ATRAC9 MSADPCM ASKA OGG_VORBIS -- **aax.c** - - CRI AAX header [*AAX*] - - *aax*: `.aax .(extensionless)` - - Subfiles: *hca adx* -- **acb.c** - - (container) - - *acb*: `.acb` - - Subfiles: *cpk_memory awb_memory* -- **acm.c** - - InterPlay ACM Header [*ACM*] - - *acm*: `.acm .tun .wavc` - - Codecs: ACM -- **acx.c** - - (container) - - *acx*: `.acx` - - Subfiles: *adx* -- **adm3.c** - - Crankcase ADM3 header [*ADM3*] - - *adm3*: `.wem` - - Codecs: APPLE_IMA4 -- **adpcm_capcom.c** - - Capcom .ADPCM header [*ADPCM_CAPCOM*] - - *adpcm_capcom*: `.adpcm .mca` - - Codecs: NGC_DSP -- **adp_konami.c** - - Konami ADP header [*ADP_KONAMI*] - - *adp_konami*: `.adp` - - Codecs: OKI4S -- **adp_qd.c** - - Quantic Dream .ADP header [*QD_ADP*] - - *adp_qd*: `.adp` - - Codecs: QD_IMA -- **adp_wildfire.c** - - Wildfire ADP! header [*ADP_WILDFIRE*] - - *adp_wildfire*: `.adp` - - Codecs: DVI_IMA_int -- **ads.c** - - Sony ADS header [*ADS*] - - *ads*: `.ads .ss2 .pcm .adx .(extensionless) .800` - - *ads_container*: `.ads .cads` - - Subfiles: *ads* - - Codecs: PCM16LE DVI_IMA_int PSX -- **ads_midway.c** - - Midway ADS header [*ADS_MIDWAY*] - - *ads_midway*: `.ads` - - Codecs: NGC_DSP XBOX_IMA_int - **adx.c** - CRI ADX header type 03 [*ADX_03*] - CRI ADX header type 04 [*ADX_04*] @@ -98,125 +32,10 @@ different internally (encrypted, different versions, etc) and not always can be - Subfiles: *adx_subkey* - *adx_subkey*: `.adx .adp + .(external)` - Codecs: CRI_ADX_fixed CRI_ADX CRI_ADX_exp CRI_ADX_enc_8 CRI_ADX_enc_9 -- **adx_monster.c** - - Monster Games .ADX header [*ADX_MONSTER*] - - *adx_monster*: `.adx` - - Codecs: NGC_DSP -- **afc.c** - - Nintendo .AFC header [*AFC*] - - *afc*: `.afc .stx` - - Codecs: NGC_AFC -- **agsc.c** - - Retro Studios AGSC header [*AGSC*] - - *agsc*: `.agsc` - - Codecs: NGC_DSP -- **ahv.c** - - Amuze AHV header [*AHV*] - - *ahv*: `.ahv` - - Codecs: PSX -- **ahx.c** - - CRI AHX header [*AHX*] - - *ahx*: `.ahx` - - Codecs: MPEG -- **aifc.c** - - Apple AIFF-C (Audio Interchange File Format) header [*AIFC*] - - Apple AIFF (Audio Interchange File Format) header [*AIFF*] - - *aifc*: `.aif .laif .wav .lwav .(extensionless) .aifc .laifc .afc .cbd2 .bgm .fda .n64 .xa .aiff .laiff .acm .adp .ai .pcm` - - Codecs: SDX2 CBD2 DVI_IMA_int APPLE_IMA4 RELIC VADPCM PCM8 PCM16BE XA -- **aif_asobo.c** - - Asobo Studio .AIF header [*AIF_ASOBO*] - - *aif_asobo*: `.aif .laif` - - Codecs: XBOX_IMA -- **aix.c** - - CRI AIX header [*AIX*] - - *aix*: `.aix` - - Subfiles: *adx* -- **akb.c** - - Square Enix AKB header [*AKB*] - - *akb*: `.akb` - - Subfiles: *ogg_vorbis_config* - - *akb2*: `.akb` - - Subfiles: *ogg_vorbis_config* - - Codecs: MSADPCM OGG FFmpeg(various) PCM16LE -- **alp.c** - - High Voltage ALP header [*ALP*] - - *alp*: `.tun .pcm` - - Codecs: HV_IMA -- **ao.c** - - AlphaOgg .AO header [*AO*] - - *ao*: `.ao` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG -- **apc.c** - - Cryo APC header [*APC*] - - *apc*: `.apc` - - Codecs: IMA -- **apple_caff.c** - - Apple Core Audio Format File header [*CAFF*] - - *apple_caff*: `.caf` - - Codecs: PCM8 APPLE_IMA4 -- **asf.c** - - Argonaut ASF header [*ASF*] - - *asf*: `.asf .lasf` - - Codecs: ASF -- **ast.c** - - Nintendo .AST header [*AST*] - - *ast*: `.ast` - - Codecs: NGC_AFC PCM16BE -- **astb.c** - - Capcom ASTB header [*ASTB*] - - *astb*: `.ast` - - Codecs: XMA -- **ast_mmv.c** - - Marvelous AST header [*AST_MMV*] - - *ast_mmv*: `.ast` - - Codecs: PSX -- **ast_mv.c** - - MicroVision AST header [*AST_MV*] - - *ast_mv*: `.ast` - - Codecs: PSX -- **atsl.c** - - (container) - - *atsl*: `.atsl .atsl3 .atsl4 .atslx` - - Subfiles: *ogg_vorbis riff xma ktac ktss* -- **atx.c** - - (container) - - *atx*: `.atx + .(external)` - - Subfiles: *riff* -- **aus.c** - - Capcom AUS Header [*AUS*] - - *aus*: `.aus` - - Codecs: XBOX_IMA PSX -- **awb.c** - - (container) - - *awb* - - Subfiles: *awb_memory* - - *awb_memory*: `.awb .afs2 + .acb .(external)` - - Subfiles: *adx_subkey hca_subkey vag riff bcwav ngc_dsp_std dsp_cwac mp4_aac_ffmpeg* -- **awc.c** - - Rockstar AWC header [*AWC*] - - *awc*: `.awc` - - Codecs: PCM16BE PCM16LE AWC_IMA XMA2 MPEG VORBIS_custom -- **awd.c** - - RenderWare Audio Wave Dictionary header [*AWD*] - - *awd*: `.awd .hwd .lwd` - - Codecs: PSX PCM16LE NGC_DSP XBOX_IMA -- **baf.c** - - Bizarre Creations .baf header [*BAF*] - - *baf*: `.baf` - - Codecs: PCM16LE PSX_cfg XMA1 -- **bar.c** - - Guitar Hero III Mobile .bar [*GH3_BAR*] - - *bar*: `.bar` - - Codecs: IMA -- **bcstm.c** - - Nintendo CSTM Header [*CSTM*] - - *bcstm*: `.bcstm` - - Codecs: PCM8 PCM16LE NGC_DSP NW_IMA -- **bfstm.c** - - Nintendo FSTM Header [*FSTM*] - - *bfstm*: `.bfstm` - - Codecs: PCM8 PCM16BE PCM16LE NGC_DSP +- **brstm.c** + - Nintendo RSTM header [*RSTM*] + - *brstm*: `.brstm .brstmspm` + - Codecs: PCM8 PCM16BE NGC_DSP - **bfwav.c** - Nintendo RWAV header [*RWAV*] - Nintendo FWAV header [*FWAV*] @@ -227,177 +46,156 @@ different internally (encrypted, different versions, etc) and not always can be - *brwar*: `.rwar` - Subfiles: *brwav* - Codecs: PCM8 PCM16BE PCM16LE NGC_DSP NW_IMA -- **bgw.c** - - Square Enix .BGW header [*FFXI_BGW*] - - Square Enix .SPW header [*FFXI_SPW*] - - *bgw*: `.bgw` - - *spw*: `.spw` - - Codecs: PSX_cfg ATRAC3 PCM16LE -- **bigrp.c** - - Inti Creates .BIGRP header [*BIGRP*] - - *bigrp*: `.bigrp` - - Codecs: ICE_RANGE ICE_DCT -- **bik.c** - - RAD Game Tools Bink header [*BINK*] - - *bik*: `.bik .bik2 .bk2 .ps3 .xmv .xen .vid .bika` - - Codecs: FFmpeg(various) -- **bkhd.c** - - Audiokinetic Wwise FX header [*WWISE_FX*] - - *bkhd*: `.bnk` - - Subfiles: *wwise_bnk bkhd_fx* - - *bkhd_fx*: `.wem .bnk` - - Codecs: PCMFLOAT -- **bmp_konami.c** - - Konami BMP header [*BMP_KONAMI*] - - *bmp_konami*: `.bin .lbin` - - Codecs: OKI4S -- **bnk_relic.c** - - Relic BNK header [*BNK_RELIC*] - - *bnk_relic*: `.bnk` - - Codecs: RELIC -- **bnk_sony.c** - - Sony BNK header [*BNK_SONY*] - - *bnk_sony*: `.bnk` - - Codecs: ATRAC9 PCM16BE PCM16LE PSX HEVAG -- **bnsf.c** - - Namco Bandai BNSF header [*BNSF*] - - *bnsf*: `.bnsf + .(external)` - - Codecs: G7221C G719 -- **brstm.c** - - Nintendo RSTM header [*RSTM*] - - *brstm*: `.brstm .brstmspm` - - Codecs: PCM8 PCM16BE NGC_DSP -- **bsf.c** - - (container) - - *bsf*: `.bsf` - - Subfiles: *ngc_dsp_std vag riff* -- **btsnd.c** - - Nintendo Wii U Menu Boot Sound [*WIIU_BTSND*] - - *btsnd*: `.btsnd` - - Codecs: PCM16BE -- **bwav.c** - - Nintendo BWAV header [*BWAV*] - - *bwav*: `.bwav` - - Subfiles: *opus_std* - - Codecs: PCM16LE NGC_DSP -- **bw_mp3_riff.c** - - (container) - - *bw_mp3_riff* - - Subfiles: *riff* - - *bw_riff_mp3* - - Subfiles: *mpeg* -- **caf.c** - - tri-Crescendo CAF Header [*CAF*] - - *caf*: `.caf .cfn .(extensionless)` - - Codecs: NGC_DSP -- **ck.c** - - Cricket Audio CKS header [*CKS*] - - Cricket Audio CKB header [*CKB*] - - *cks*: `.cks` - - *ckb*: `.ckb` - - Codecs: PCM16LE PCM8 MSADPCM_ck -- **compresswave.c** - - CompressWave .cwav header [*COMPRESSWAVE*] - - *compresswave*: `.cwav` - - Codecs: COMPRESSWAVE -- **cpk.c** - - (container) - - *cpk* - - Subfiles: *cpk_memory* - - *cpk_memory*: `.awb + .acb` - - Subfiles: *hca bcwav adx* -- **cps.c** - - tri-Crescendo CPS Header [*CPS*] - - *cps*: `.cps` - - Codecs: PCM16BE PSX -- **csb.c** - - CRI ADPCM_WII header [*UTF_DSP*] - - *csb*: `.csb` - - Subfiles: *aax utf_ahx utf_dsp* - - *utf_dsp*: `.aax .(extensionless)` - - *utf_ahx*: `.aax .(extensionless)` - - Subfiles: *ahx* +- **nds_strm.c** + - Nintendo STRM header [*STRM*] + - *nds_strm*: `.strm` + - Codecs: PCM8 PCM16LE NDS_IMA +- **afc.c** + - Nintendo .AFC header [*AFC*] + - *afc*: `.afc .stx` + - Codecs: NGC_AFC +- **ast.c** + - Nintendo .AST header [*AST*] + - *ast*: `.ast` + - Codecs: NGC_AFC PCM16BE +- **halpst.c** + - HAL Laboratory HALPST header [*HALPST*] + - *halpst*: `.hps` + - Codecs: NGC_DSP +- **rs03.c** + - Retro Studios RS03 header [*DSP_RS03*] + - *rs03*: `.dsp` - Codecs: NGC_DSP +- **ngc_dsp_std.c** + - Nintendo DSP header [*DSP_STD*] + - Intelligent Systems STM header [*DSP_STM*] + - Single DSP header stereo by .mpdsp extension [*DSP_MPDSP*] + - Double DSP header stereo by _lr.dsp extension [*DSP_JETTERS*] + - Double DSP header stereo by .mss extension [*DSP_MSS*] + - Double DSP header stereo by .gcm extension [*DSP_GCM*] + - Namco IDSP header [*IDSP_NAMCO*] + - Procyon Studio SADB header [*DSP_SADB*] + - Traveller's Tales IDSP header [*IDSP_TT*] + - Next Level IDSP header [*IDSP_NL*] + - .WSD header [*DSP_WII_WSD*] + - .DDSP header [*DSP_DDSP*] + - Sumo Digital iSWS header [*WII_WAS*] + - Infogrames .DSP header [*DSP_STR_IG*] + - XIII dsp header [*DSP_XIII*] + - Icon Games NDP header [*WII_NDP*] + - Cabelas games .DSP header [*DSP_CABELAS*] + - Acclaim Austin AAAp DSP header [*NGC_DSP_AAAP*] + - Capcom DSPW header [*DSP_DSPW*] + - IADP Header [*NGC_DSP_IADP*] + - Bethesda .mcadpcm header [*DSP_MCADPCM*] + - UE4 Switch Audio header [*DSP_SWITCH_AUDIO*] + - .VAG DSP header [*DSP_VAG*] + - .ITL DSP header [*DSP_ITL*] + - AQUASTYLE ADPY header [*DSP_ADPY*] + - AQUASTYLE ADPX header [*DSP_ADPX*] + - LucasArts .DS2 header [*DSP_DS2*] + - Infernal .ITL DSP header [*DSP_ITL_i*] + - Square Enix DSP header [*DSP_SQEX*] + - Koei Tecmo WiiVoice header [*DSP_WIIVOICE*] + - Exient WIIADPCM header [*DSP_WIIADPCM*] + - CRI CWAC header [*DSP_CWAC*] + - TOSE .IDSP header [*IDSP_TOSE*] + - Kuju London .KWA header [*DSP_KWA*] + - Koei Tecmo APEX header [*DSP_APEX*] + - *ngc_dsp_std*: `.dsp .adp .(extensionless)` + - *ngc_dsp_std_le*: `.adpcm` + - *ngc_mdsp_std*: `.dsp .mdsp` + - *ngc_dsp_stm*: `.stm .lstm .dsp` + - *ngc_mpdsp*: `.mpdsp .ste` + - *ngc_dsp_std_int*: `.dsp .mss .gcm` + - *idsp_namco*: `.idsp` + - *sadb*: `.sad` + - *idsp_tt*: `.gcm .idsp .wua` + - *idsp_nl*: `.idsp` + - *wii_wsd*: `.wsd` + - *dsp_ddsp*: `.adp .ddsp .wav .lwav` + - *wii_was*: `.was .dsp .isws` + - *dsp_str_ig*: `.str` + - *dsp_xiii*: `.dsp` + - *dsp_ndp*: `.nds .ndp` + - *dsp_cabelas*: `.dsp` + - *ngc_dsp_aaap*: `.dsp` + - *dsp_dspw*: `.dspw` + - *ngc_dsp_iadp*: `.adp .iadp` + - *dsp_mcadpcm*: `.mcadpcm` + - *dsp_switch_audio*: `.switch_audio .dsp` + - *dsp_sps_n1*: `.vag .nlsd` + - *dsp_itl_ch*: `.itl` + - *dsp_adpy*: `.adpcmx` + - *dsp_adpx*: `.adpcmx` + - *dsp_ds2*: `.ds2 .dsp` + - *dsp_itl*: `.itl .dsp` + - *dsp_sqex*: `.wav .lwav` + - *dsp_wiivoice*: `.dsp` + - *dsp_wiiadpcm*: `.adpcm` + - *dsp_cwac*: `.dsp` + - *idsp_tose*: `.idsp` + - *dsp_kwa*: `.kwa` + - *dsp_apex*: `.dsp` + - Codecs: NGC_DSP NGC_DSP_subint - **csmp.c** - Retro Studios CSMP header [*CSMP*] - *csmp*: `.csmp` - Codecs: NGC_DSP +- **rfrm.c** + - Retro Studios RFRM header [*RFRM*] + - *rfrm_mpr*: `.csmp` + - *rfrm*: `.csmp` + - Codecs: NGC_DSP - **cstr.c** - Namco Cstr header [*DSP_CSTR*] - *cstr*: `.dsp` - Codecs: NGC_DSP -- **cxs.c** - - tri-Crescendo CXS header [*CXS*] - - *cxs*: `.cxs` - - Codecs: XMA2 -- **dcs_wav.c** - - In Utero DCS+WAV header [*DCS_WAV*] - - *dcs_wav*: `.dcs + .wav` - - Codecs: AICA_int -- **dc_asd.c** - - ASD Header [*DC_ASD*] - - *dc_asd*: `.asd` - - Codecs: PCM16LE -- **dc_idvi.c** - - Capcom IDVI header [*DC_IDVI*] - - *dc_idvi*: `.dvi .idvi` - - Codecs: DVI_IMA_int -- **dc_kcey.c** - - Konami KCEY KCEYCOMP header [*DC_KCEY*] - - *dc_kcey*: `.pcm .kcey` - - Codecs: DVI_IMA -- **dc_str.c** - - Sega Stream Asset Builder header [*DC_STR*] - - variant of Sega Stream Asset Builder header [*DC_STR_V2*] - - *dc_str*: `.str` - - *dc_str_v2*: `.str` - - Codecs: AICA_int PCM16LE -- **dec.c** - - Falcom DEC RIFF header [*DEC*] - - *dec*: `.dec .de2 + .(external)` - - Codecs: MSADPCM -- **derf.c** - - Xilam DERF header [*DERF*] - - *derf*: `.adp` - - Codecs: DERF -- **diva.c** - - Sega DIVA header [*DIVA*] - - *diva*: `.diva` - - Codecs: DVI_IMA -- **dmsg_segh.c** - - (container) - - *dmsg*: `.sgt .dmsg` - - Subfiles: *riff* -- **dsb.c** - - (container) - - *dsb*: `.dsb` - - Subfiles: *bnsf* -- **dsf.c** - - Ocean DSF header [*DSF*] - - *dsf*: `.dsf` - - Codecs: DSA -- **ea_1snh.c** - - Electronic Arts EACS header [*EA_EACS*] - - Electronic Arts 1SNh header [*EA_1SNH*] - - *ea_1snh*: `.asf .lasf .sng .as4 .cnk .uv .tgq .tgv .(extensionless)` - - *ea_eacs*: `.eas .bnk .as4` - - Codecs: PCM8_int PCM16_int ULAW_int DVI_IMA PSX -- **ea_eaac.c** - - Electronic Arts SNR+SNS header [*EA_SNR_SNS*] - - Electronic Arts SPS header [*EA_SPS*] - - Electronic Arts SNU header [*EA_SNU*] - - *ea_snr_sns*: `.snr` - - *ea_sps*: `.sps` - - *ea_snu*: `.snu` - - *ea_abk_eaac*: `.abk + .ast` - - *ea_sbr*: `.sbr + .sbs` - - *ea_hdr_sth_dat*: `.hdr + .sth .dat .mus .(external)` - - *ea_mpf_mus_eaac*: `.mpf + .(external)` - - *ea_tmx*: `.tmx` - - Subfiles: *gin* - - *ea_sbr_harmony*: `.sbr + .sbs` - - *eaaudiocore_header*: `(base) + .sns` - - Codecs: PCM16_int EA_XAS_V1 MPEG NGC_DSP SPEEX ATRAC9 Opus XMA1 XMA2 +- **gcsw.c** + - MileStone GCSW header [*GCSW*] + - *gcsw*: `.gcw` + - Codecs: PCM16BE +- **ads.c** + - Sony ADS header [*ADS*] + - *ads*: `.ads .ss2 .pcm .adx .(extensionless) .800` + - *ads_container*: `.ads .cads` + - Subfiles: *ads* + - Codecs: PCM16LE DVI_IMA_int PSX +- **nps.c** + - Namco NPSF header [*NPS*] + - *nps*: `.nps .npsf` + - Codecs: PSX +- **xa.c** + - Sony XA header [*XA*] + - *xa*: `.xa .str .pxa .grn .an2 .(extensionless)` + - Codecs: XA8 XA +- **rxws.c** + - Sony RXWS header [*RXWS*] + - *rxws*: `.xwb .xws + .xwh .xwb` + - Codecs: PSX PCM16LE ATRAC3 +- **exst.c** + - Sony EXST header [*EXST*] + - *exst*: `.sts .sts_cp3 .x + .int_cp3 .int` + - Codecs: PSX +- **svag_kcet.c** + - Konami SVAG header [*SVAG_KCET*] + - *svag_kcet*: `.svag` + - Codecs: PSX +- **vag.c** + - Sony VAG header (custom) [*VAG_custom*] + - Sony VAG header [*VAG*] + - Acclaim Austin AAAp header [*AAAP*] + - *vag*: `.vag .swag .str .vig .l .r .vas .xa2 .snd` + - *vag_aaap*: `.vag` + - Codecs: PSX HEVAG +- **ild.c** + - Tose ILD header [*ILD*] + - *ild*: `.ild` + - Codecs: PSX +- **ngc_str_cauldron.c** + - Cauldron .STR header [*DSP_STR*] + - *ngc_str*: `.str` + - Codecs: NGC_DSP - **ea_schl.c** - Electronic Arts BNK header [*EA_BNK*] - Electronic Arts SCHl header (variable) [*EA_SCHL*] @@ -411,85 +209,103 @@ different internally (encrypted, different versions, etc) and not always can be - *ea_map_mus*: `.map .lin .mpf` - *ea_mpf_mus*: `.mpf + .(external)` - Codecs: EA_XA EA_XA_int EA_XA_V2 PCM8_int PCM16_int PCM8 PCM16LE PCM16BE PSX XBOX_IMA_int NGC_DSP VADPCM MPEG EA_MT ATRAC3 -- **ea_schl_fixed.c** - - Electronic Arts SCHl header (fixed) [*EA_SCHL_fixed*] - - *ea_schl_fixed*: `.asf .lasf .cnk` - - Codecs: PCM8 PCM16BE PCM16LE DVI_IMA PSX -- **ea_swvr.c** - - Electronic Arts SWVR header [*EA_SWVR*] - - *ea_swvr*: `.stream .str` - - Codecs: PSX NGC_DSP PCM8_U_int -- **ea_wve_ad10.c** - - Electronic Arts WVE (Ad10) header [*EA_WVE_AD10*] - - *ea_wve_ad10*: `.wve .mov` - - Codecs: PSX PCM8_U_int -- **ea_wve_au00.c** - - Electronic Arts WVE (au00) header [*EA_WVE_AU00*] - - *ea_wve_au00*: `.wve .fsv` - - Codecs: EA_XA_int PSX_cfg -- **ego_dic.c** - - Codemasters DIC1 header [*DIC1*] - - *ego_dic*: `.dic + .(external)` - - Codecs: PCM16LE ULAW XBOX_IMA OGG_VORBIS -- **encrypted.c** - - (container) - - *encrypted_ogg_tpf*: `.ogg .logg` +- **caf.c** + - tri-Crescendo CAF Header [*CAF*] + - *caf*: `.caf .cfn .(extensionless)` + - Codecs: NGC_DSP +- **vpk.c** + - SCE America VPK Header [*VPK*] + - *vpk*: `.vpk` + - Codecs: PSX +- **ogg_vorbis.c** + - Ogg Vorbis header (encrypted) [*OGG_encrypted*] + - Ogg Vorbis header [*OGG_VORBIS*] + - Ogg Vorbis header (KOVS) [*OGG_KOVS*] + - *ogg_vorbis* - Subfiles: *ogg_vorbis* - - *encrypted_mp3_tpf*: `.mp3` - - Subfiles: *ffmpeg* - - *encrypted_riff*: `.bgm .mse .koe` - - Subfiles: *riff* - - *encrypted_rpgmvo_riff*: `.rpgmvo` - - Subfiles: *riff* - - *encrypted_mc161*: `.mus` + - *ogg_vorbis_config*: `.ogg .logg .adx .rof .acm .sod .msa .bin .lbin .kvs .kovs .rpgmvo .ogg_ .bgm .gwm .mus .isd .sngw .lse .eno .um3 .u0 + .(external)` + - Subfiles: *ogg_vorbis_config ogg_vorbis_cfg_ovmi ogg_vorbis_tests ogg_vorbis_common ogg_vorbis_tink ogg_vorbis* + - Codecs: OGG OGG_VORBIS +- **sfl.c** + - Ogg Vorbis header (SFPL looping) [*OGG_SFL*] + - *sfl_ogg*: `.sfl .ogg + .(external) .ogg` - Subfiles: *ogg_vorbis* -- **esf.c** - - Eurocom ESF header [*ESF*] - - *esf*: `.esf` - - Codecs: DVI_IMA PCM8_U PCM16LE -- **exakt_sc.c** - - assumed Activision / EXAKT SC by extension [*EXAKT_SC*] - - *exakt_sc*: `.sc` - - Codecs: SASSC -- **excitebots.c** - - Excitebots .sfx header [*EB_SFX*] - - assumed Excitebots .sf0 by extension [*EB_SF0*] - - *eb_sfx*: `.sfx` - - *eb_sf0*: `.sf0` - - Codecs: PCM16BE NGC_DSP -- **exst.c** - - Sony EXST header [*EXST*] - - *exst*: `.sts .sts_cp3 .x + .int_cp3 .int` +- **ps2_bmdx.c** + - Beatmania .bmdx header [*PS2_BMDX*] + - *ps2_bmdx*: `.bmdx` - Codecs: PSX -- **ezw.c** - - EZ2DJ EZWAVE header [*EZW*] - - *ezw*: `.ezw` +- **wsi.c** + - Alone in the Dark .WSI header [*DSP_WSI*] + - *wsi*: `.wsi` + - Codecs: NGC_DSP +- **aifc.c** + - Apple AIFF-C (Audio Interchange File Format) header [*AIFC*] + - Apple AIFF (Audio Interchange File Format) header [*AIFF*] + - *aifc*: `.aif .laif .wav .lwav .(extensionless) .aifc .laifc .afc .cbd2 .bgm .fda .n64 .xa .aiff .laiff .acm .adp .ai .pcm` + - Codecs: SDX2 CBD2 DVI_IMA_int APPLE_IMA4 RELIC VADPCM PCM8 PCM16BE XA +- **str_snds.c** + - 3DO SNDS header [*STR_SNDS*] + - *str_snds*: `.str .stream .3do` + - Codecs: SDX2_int SDX2 CBD2_int CBD2 +- **ws_aud.c** + - Westwood Studios .AUD header [*WS_AUD*] + - *ws_aud*: `.aud` + - Codecs: WS IMA_int +- **ahx.c** + - CRI AHX header [*AHX*] + - *ahx*: `.ahx` + - Codecs: MPEG +- **ivb.c** + - IVB/BVII header [*PS2_IVB*] + - *ivb*: `.ivb` + - Codecs: PSX +- **svs.c** + - Square SVS header [*SVS*] + - *svs*: `.svs` + - Codecs: PSX +- **riff.c** + - RIFF WAVE header [*RIFF_WAVE*] + - RIFF WAVE header with loop markers [*RIFF_WAVE_labl*] + - RIFF WAVE header with sample looping info [*RIFF_WAVE_smpl*] + - RIFF WAVE header with wsmp looping info [*RIFF_WAVE_wsmp*] + - RIFF WAVE header with .mwv flavoring [*RIFF_WAVE_MWV*] + - RIFX WAVE header [*RIFX_WAVE*] + - RIFX WAVE header with sample looping info [*RIFX_WAVE_smpl*] + - *riff*: `.wav .lwav .xwav .mwv .da .dax .cd .med .snd .adx .adp .xss .xsew .adpcm .adw .wd .(extensionless) .sbv .wvx .str .at3 .rws .aud .at9 .ckd .saf .ima .nsa .pcm .xvag .ogg .logg .p1d .xms .mus .dat .ldat` + - *rifx*: `.wav .lwav` + - Codecs: AICA_int PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int +- **nwa.c** + - VisualArt's NWA header (NWAINFO.INI looping) [*NWA_NWAINFOINI*] + - VisualArt's NWA header (Gameexe.ini looping) [*NWA_GAMEEXEINI*] + - VisualArt's NWA header [*NWA*] + - *nwa*: `.nwa + .(external)` + - Codecs: PCM8 PCM16LE NWA +- **ea_1snh.c** + - Electronic Arts EACS header [*EA_EACS*] + - Electronic Arts 1SNh header [*EA_1SNH*] + - *ea_1snh*: `.asf .lasf .sng .as4 .cnk .uv .tgq .tgv .(extensionless)` + - *ea_eacs*: `.eas .bnk .as4` + - Codecs: PCM8_int PCM16_int ULAW_int DVI_IMA PSX +- **xss.c** + - Dino Crisis 3 XSS File [*XSS*] + - *xss*: `.xss` - Codecs: PCM16LE -- **fag.c** - - Radical .FAG Header [*FAG*] - - *fag*: `.fag` +- **ps2_sl3.c** + - Atari Melbourne House SL3 header [*SL3*] + - *sl3*: `.ms .sl3` - Codecs: PSX -- **fda.c** - - Relic FDA header [*FDA*] - - *fda*: `.fda` - - Codecs: RELIC -- **ffdl.c** - - (container) - - *ffdl*: `.ogg .logg .mp4 .lmp4 .bin .(extensionless)` - - Subfiles: *ogg_vorbis mp4_aac_ffmpeg* -- **ffmpeg.c** - - FFmpeg supported format (check log) [*FFMPEG_faulty*] - - FFmpeg supported format [*FFMPEG*] - - *ffmpeg*: `.(any) .at3` - - Codecs: FFmpeg(various) -- **ffw.c** - - Freedom Fighters BGM header [*FFW*] - - *ffw*: `.ffw` - - Codecs: PCM16BE -- **flx.c** - - Ultima IX .FLX header [*PC_FLX*] - - *flx*: `.flx` - - Codecs: PCM16LE EA_XA EA_XA_int EA_MT +- **ps2_hgc1.c** + - Knights of the Temple 2 hgC1 Header [*HGC1*] + - *hgc1*: `.hgc1` + - Codecs: PSX +- **aus.c** + - Capcom AUS Header [*AUS*] + - *aus*: `.aus` + - Codecs: XBOX_IMA PSX +- **rws_80d.c** + - RenderWare RWS header [*RWS*] + - *rws*: `.rws` + - Codecs: PCM16_int PCM16BE PCM16LE PSX NGC_DSP XBOX_IMA - **fsb.c** - FMOD FSB1 header [*FSB1*] - FMOD FSB2 header [*FSB2*] @@ -503,91 +319,31 @@ different internally (encrypted, different versions, etc) and not always can be - FMOD FSB5 header [*FSB5*] - *fsb5*: `.fsb .snd` - Codecs: PCM8_U PCM16BE PCM16LE PCMFLOAT NGC_DSP NGC_DSP_subint FSB_IMA XBOX_IMA PSX HEVAG XMA2 MPEG CELT_FSB ATRAC9 XWMA VORBIS_custom FADPCM Opus -- **fsb5_fev.c** - - (container) - - *fsb5_fev_bank*: `.bank` - - Subfiles: *fsb5 fsb_encrypted* -- **fsb_encrypted.c** - - (container) - - *fsb_encrypted*: `.fsb .ps3 .xen` - - Subfiles: *fsb fsb5* -- **fwse.c** - - MT Framework FWSE header [*FWSE*] - - *fwse*: `.fwse` - - Codecs: MTF_IMA -- **g1l.c** - - Koei Tecmo WiiBGM Header [*KT_WIIBGM*] - - *kt_g1l*: `.g1l` - - *kt_wiibgm_offset*: `.g1l .dsp` - - Codecs: NGC_DSP_subint -- **gca.c** - - GCA DSP Header [*GCA*] - - *gca*: `.gca` - - Codecs: NGC_DSP -- **gcsw.c** - - MileStone GCSW header [*GCSW*] - - *gcsw*: `.gcw` - - Codecs: PCM16BE -- **gcub.c** - - Sega GCub header [*GCUB*] - - *gcub*: `.wav .lwav .gcub` - - Codecs: NGC_DSP_subint NGC_DSP -- **ghs.c** - - Hexadrive GHS/S_P_STH header [*GHS*] - - *ghs*: `.gtd` - - *s_p_sth*: `.gtd` - - Subfiles: *msf* - - Codecs: XMA ATRAC9 -- **gin.c** - - Electronic Arts Gnsu header [*GIN*] - - *gin*: `.gin` - - Codecs: EA_XAS_V0 -- **gsp_gsb.c** - - Tecmo GSP+GSB Header [*GSP_GSB*] - - *gsp_gsb*: `.gsb + .gsp` - - Codecs: NGC_DSP ATRAC3 XMA -- **h4m.c** - - Hudson HVQM4 header [*H4M*] - - *h4m*: `.h4m .hvqm` - - Codecs: H4M_IMA -- **halpst.c** - - HAL Laboratory HALPST header [*HALPST*] - - *halpst*: `.hps` - - Codecs: NGC_DSP -- **hca.c** - - CRI HCA header [*HCA*] - - *hca* - - Subfiles: *hca_subkey* - - *hca_subkey*: `.hca` - - Codecs: CRI_HCA -- **hd3_bd3.c** - - Sony HD3+BD3 header [*HD3_BD3*] - - *hd3_bd3*: `.bd3 + .hd3` +- **rwax.c** + - Konami RWAX header [*RWAX*] + - *rwax*: `.rwx` + - Codecs: PCM16LE +- **xwb.c** + - Microsoft XWB header [*XWB*] + - *xwb*: `.xwb .xna .hwb .bd .(extensionless) + .wbh` + - Subfiles: *riff* + - Codecs: PCM8_U PCM16LE PCM16BE XBOX_IMA MSADPCM XMA1 XMA2 FFmpeg(various) XWMA ATRAC3 OGG_VORBIS NGC_DSP +- **ps2_xa30.c** + - Reflections XA30 PS2 header [*PS2_XA30*] + - *ps2_xa30*: `.xa .xa30` - Codecs: PSX -- **his.c** - - Her Interactive HIS header [*HIS*] - - *his*: `.his` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG PCM8_U PCM16LE OGG_VORBIS -- **hxd.c** - - Tecmo HXD Header [*HXD*] - - *hxd*: `.hxd + .bd .str .at3` +- **musc.c** + - Krome MUSC header [*MUSC*] + - *musc*: `.mus .musc` + - Codecs: PSX +- **musx.c** + - Eurocom MUSX header [*MUSX*] + - *musx*: `.sfx .musx` + - Codecs: PSX DAT4_IMA DVI_IMA_int XBOX_IMA NGC_DSP PCM16BE PCM16LE +- **ps2_filp.c** + - Bio Hazard - Gun Survivor FILp Header [*FILP*] + - *filp*: `.filp` - Codecs: PSX -- **idsp_ie.c** - - Inevitable Entertainment IDSP Header [*IDSP_IE*] - - *idsp_ie*: `.idsp` - - Codecs: NGC_DSP -- **idtech.c** - - id Software MZRT header [*MZRT*] - - id Software BSNF header [*BSNF*] - - *mzrt_v0*: `.idwav .idmsf .idxma` - - *mzrt_v1*: `.idmsf` - - *bsnf*: `.bsnd + .(external)` - - Codecs: PCM16LE MSADPCM XMA MPEG XMA2 OGG_VORBIS ATRAC9 -- **ifs.c** - - (container) - - *ifs*: `.ifs` - - Subfiles: *bmp_konami* - **ikm.c** - MiCROViSiON IKM header [*IKM*] - *ikm_pc* @@ -596,1105 +352,866 @@ different internally (encrypted, different versions, etc) and not always can be - Subfiles: *riff* - *ikm*: `.ikm` - Codecs: PSX OGG -- **ild.c** - - Tose ILD header [*ILD*] - - *ild*: `.ild` +- **ster.c** + - ALCHEMY STER header [*STER*] + - *ster*: `.ster .sfs` - Codecs: PSX -- **ima.c** - - Blitz Games .IMA header [*IMA*] - - *ima*: `.ima` - - Codecs: BLITZ_IMA -- **imc.c** - - iNiS .IMC header [*IMC*] - - *imc*: `.imc` - - *imc_container*: `.imc` - - Subfiles: *imc* +- **ps2_bg00.c** + - Falcom BG00 Header [*BG00*] + - *bg00*: `.bg00` - Codecs: PSX -- **imuse.c** - - LucasArts iMUSE header [*IMUSE*] - - *imuse*: `.imx .imc .wav .lwav` - - Codecs: IMUSE -- **ios_psnd.c** - - PSND Header [*IOS_PSND*] - - *ios_psnd*: `.psnd` - - Codecs: PCM16LE -- **isb.c** - - Creative ISACT header [*ISB*] - - *isb*: `.isb` - - Subfiles: *msf* - - Codecs: PCM8_U PCM16LE XBOX_IMA OGG_VORBIS XMA -- **ish_isd.c** - - ISH+ISD DSP Header [*ISH_ISD*] - - *ish_isd*: `.isd + .ish` - - Codecs: NGC_DSP -- **ivag.c** - - Namco IVAG header [*IVAG*] - - *ivag*: `.ivag` +- **sat_dvi.c** + - Konami KCEN DVI. header [*SAT_DVI*] + - *sat_dvi*: `.pcm .dvi` + - Codecs: DVI_IMA_int +- **dc_kcey.c** + - Konami KCEY KCEYCOMP header [*DC_KCEY*] + - *dc_kcey*: `.pcm .kcey` + - Codecs: DVI_IMA +- **rstm_rockstar.c** + - Rockstar Games RSTM Header [*RSTM_ROCKSTAR*] + - *rstm_rockstar*: `.rsm .rstm` - Codecs: PSX -- **ivaud.c** - - Rockstar .ivaud header [*IVAUD*] - - *ivaud*: `.ivaud .(extensionless)` - - Codecs: PCM16LE XMA1 MPEG IMA_int -- **ivb.c** - - IVB/BVII header [*PS2_IVB*] - - *ivb*: `.ivb` +- **acm.c** + - InterPlay ACM Header [*ACM*] + - *acm*: `.acm .tun .wavc` + - Codecs: ACM +- **mus_acm.c** + - InterPlay MUS ACM header [*MUS_ACM*] + - *mus_acm*: `.mus` + - Subfiles: *acm ogg_vorbis* +- **ps2_kces.c** + - Konami KCES Header [*PS2_KCES*] + - *ps2_kces*: `.kces` - Codecs: PSX -- **jstm.c** - - JSTM Header [*PS2_JSTM*] - - *jstm*: `.stm .jstm` - - Codecs: PCM16LE -- **kat.c** - - Sega KAT header [*KAT*] - - *kat*: `.kat` - - Codecs: AICA_int PCM8 PCM16LE -- **kma9.c** - - Koei Tecmo KMA9 header [*KMA9*] - - *kma9*: `.km9` - - Codecs: ATRAC9 -- **knon.c** - - Paon KNON header [*KNON*] - - *knon*: `.str .asr` - - Codecs: NGC_DSP PCM16BE -- **kraw.c** - - Geometry Wars: Galaxies KRAW header [*KRAW*] - - *kraw*: `.kraw` - - Codecs: PCM16BE -- **ktac.c** - - Koei Tecmo KTAC header [*KTAC*] - - *ktac*: `.ktac` - - Codecs: MP4/AAC -- **ktsc.c** - - (container) - - *ktsc*: `.ktsl2asbin .asbin` - - Subfiles: *ktsr* -- **ktsr.c** - - Koei Tecmo KTSR header [*KTSR*] - - *ktsr*: `.ktsl2asbin .asbin` - - Subfiles: *riff ogg_vorbis ktss* - - Codecs: MSADPCM_int NGC_DSP ATRAC9 -- **ktss.c** - - Koei Tecmo KTSS header [*KTSS*] - - *ktss*: `.kns .kno .ktss` - - Codecs: NGC_DSP Opus -- **kwb.c** - - Koei Tecmo WaveBank header [*KWB*] - - *kwb*: `.wbd .wb2 .sed + .wbh .whd .wh2` - - *xws*: `.xws` - - *koei_wavebank* - - Subfiles: *msf dsp_apex* - - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 -- **lopu_fb.c** - - French-Bread LOPU header [*LOPU_FB*] - - *lopu_fb*: `.lopus` - - Codecs: Opus -- **lpcm_fb.c** - - French-Bread LPCM header [*LPCM_FB*] - - *lpcm_fb*: `.ladpcm` - - Codecs: NGC_DSP -- **lpcm_shade.c** - - Shade LPCM header [*LPCM_SHADE*] - - *lpcm_shade*: `.w .lpcm` +- **hxd.c** + - Tecmo HXD Header [*HXD*] + - *hxd*: `.hxd + .bd .str .at3` + - Codecs: PSX +- **vsv.c** + - Square Enix .vsv Header [*VSV*] + - *vsv*: `.vsv .psh` + - Codecs: PSX +- **ps2_pcm.c** + - Konami KCEJ East .PCM header [*PS2_PCM*] + - *ps2_pcm*: `.pcm` - Codecs: PCM16LE +- **rkv.c** + - Legacy of Kain - Blood Omen 2 RKV PS2 header [*PS2_RKV*] + - Legacy of Kain - Blood Omen 2 RKV GC header [*NGC_RKV*] + - *ps2_rkv*: `.rkv` + - *ngc_rkv*: `.(extensionless) .rkv .bo2` + - Codecs: PSX NGC_DSP +- **ps2_vas.c** + - Konami .VAS header [*PS2_VAS*] + - *ps2_vas*: `.vas` + - *ps2_vas_container*: `.vas` + - Subfiles: *ps2_vas* + - Codecs: PSX - **lp_ap_lep.c** - Konami LP/AP/LEP header [*LP_AP_LEP*] - *lp_ap_lep*: `.bin .lbin .lp .lep .ap` - Codecs: PCM16LE PSX -- **lrmd.c** - - Sony LRMD header [*LRMD*] - - *lrmd*: `.lrmb + .lrmh` - - Codecs: ATRAC3 -- **lsf.c** - - .lsf !n1nj4n header [*LSF_N1NJ4N*] - - *lsf_n1nj4n*: `.lsf` - - Codecs: LSF -- **mattel_hyperscan.c** - - Mattel Hyperscan KVAG [*HYPERSCAN_KVAG*] - - *hyperscan_kvag*: `.bvg` - - Codecs: DVI_IMA -- **maxis_xa.c** - - Maxis XA Header [*MAXIS_XA*] - - *maxis_xa*: `.xa` - - Codecs: MAXIS_XA -- **mc3.c** - - Paradigm MC3 header [*MC3*] - - *mc3*: `.mc3` - - Codecs: MC3 -- **mca.c** - - Capcom MCA header [*MCA*] - - *mca*: `.mca` +- **sdt.c** + - High Voltage .sdt header [*SDT*] + - *sdt*: `.sdt` - Codecs: NGC_DSP -- **mib_mih.c** - - Sony MultiStream MIH+MIB header [*MIB_MIH*] - - *mib_mih*: `.mib + .mih` +- **aix.c** + - CRI AIX header [*AIX*] + - *aix*: `.aix` + - Subfiles: *adx* +- **ngc_tydsp.c** + - .tydsp Header [*NGC_TYDSP*] + - *ngc_tydsp*: `.tydsp` + - Codecs: NGC_DSP +- **wvs.c** + - Swingin' Ape .WVS header [*WVS*] + - *wvs_xbox*: `.wvs` + - *wvs_ngc*: `.wvs` + - Codecs: XBOX_IMA NGC_DSP +- **xbox_ims.c** + - assumed Matrix file by .matx extension [*XBOX_MATX*] + - *xbox_matx*: `.matx` + - Codecs: XBOX_IMA +- **dec.c** + - Falcom DEC RIFF header [*DEC*] + - *dec*: `.dec .de2 + .(external)` + - Codecs: MSADPCM +- **vs.c** + - Melbourne House .VS header [*VS*] + - *vs*: `.vs` - Codecs: PSX -- **mjb_mjh.c** - - Sony MultiStream MJH+MJB header [*MJB_MJH*] - - *mjb_mjh*: `.mjb + .mjh .mjb` +- **dc_str.c** + - Sega Stream Asset Builder header [*DC_STR*] + - variant of Sega Stream Asset Builder header [*DC_STR_V2*] + - *dc_str*: `.str` + - *dc_str_v2*: `.str` + - Codecs: AICA_int PCM16LE +- **xmu.c** + - Outrage XMU header [*XMU*] + - *xmu*: `.xmu` + - Codecs: XBOX_IMA +- **xvas.c** + - Konami .XVAS header [*XVAS*] + - *xvas*: `.xvas` + - Codecs: XBOX_IMA +- **sat_sap.c** + - VING .SAP header [*SAP*] + - *sat_sap*: `.sap` + - Codecs: PCM16BE +- **dc_idvi.c** + - Capcom IDVI header [*DC_IDVI*] + - *dc_idvi*: `.dvi .idvi` + - Codecs: DVI_IMA_int +- **ps2_rnd.c** + - Knights of the Temple 2 hgC1 Header [*HGC1*] + - *ps2_rnd*: `.rnd` - Codecs: PSX -- **mn_str.c** - - Mini Ninjas 'STR' header [*MN_STR*] - - *mn_str*: `.mnstr` +- **kraw.c** + - Geometry Wars: Galaxies KRAW header [*KRAW*] + - *kraw*: `.kraw` + - Codecs: PCM16BE +- **omu.c** + - Outrage OMU Header [*OMU*] + - *omu*: `.omu` - Codecs: PCM16LE -- **mogg.c** - - Harmonix Music Systems MOGG Vorbis [*MOGG*] - - *mogg*: `.mogg` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG -- **mp4.c** - - MP4/AAC header [*MP4*] - - *mp4_aac_ffmpeg*: `.mp4 .m4a .m4v .lmp4 .bin .lbin .msd` - - Codecs: FFmpeg(various) -- **mpeg.c** - - MPEG header [*MPEG*] - - *mpeg*: `.mp3 .mp2 .lmp3 .lmp2 .mus` - - Codecs: MPEG -- **msb_msh.c** - - Sony MultiStream MSH+MSB header [*MSB_MSH*] - - *msb_msh*: `.msb + .msh` +- **xa2_acclaim.c** + - Acclaim .XA2 Header [*XA2_ACCLAIM*] + - *xa2_acclaim*: `.xa2` - Codecs: PSX -- **msf.c** - - Sony MSF header [*MSF*] - - *msf*: `.msf .msa .at3 .mp3 .str` - - Codecs: PCM16BE PCM16LE PSX ATRAC3 FFmpeg(various) -- **msf_banpresto.c** - - (container) - - *msf_banpresto_wmsf*: `.msf` - - Subfiles: *msf* - - *msf_banpresto_2msf*: `.at9` - - Subfiles: *riff* -- **msf_konami.c** - - Konami MSF header [*MSF_KONAMI*] - - *msf_konami*: `.msf` +- **idsp_ie.c** + - Inevitable Entertainment IDSP Header [*IDSP_IE*] + - *idsp_ie*: `.idsp` + - Codecs: NGC_DSP +- **ymf.c** + - Yuke's .YMF Header [*YMF*] + - *ymf*: `.ymf` + - Codecs: NGC_DSP +- **sadl.c** + - Procyon Studio SADL header [*SADL*] + - *sadl*: `.sad` + - Codecs: IMA_int NDS_PROCYON +- **fag.c** + - Radical .FAG Header [*FAG*] + - *fag*: `.fag` - Codecs: PSX -- **msf_tamasoft.c** - - Tama-Soft MSF header [*MSF_TAMASOFT*] - - *msf_tamasoft*: `.msf` +- **ps2_mihb.c** + - Sony MultiStream MIC header [*PS2_MIHB*] + - *ps2_mihb*: `.mic .mihb` + - Codecs: PSX +- **ngc_pdt.c** + - Hudson .PDT header [*NGC_PDT*] + - *ngc_pdt*: `.pdt` + - *ngc_pdt_split*: `.pdt` + - Codecs: NGC_DSP +- **wii_mus.c** + - mus header [*DSP_WII_MUS*] + - *wii_mus*: `.mus` + - Codecs: NGC_DSP +- **dc_asd.c** + - ASD Header [*DC_ASD*] + - *dc_asd*: `.asd` - Codecs: PCM16LE -- **mss.c** - - Guerilla MCSS header [*MSS*] - - *mss*: `.mss` - - Codecs: XBOX_IMA PSX -- **msv.c** - - Sony MultiStream MSV header [*MSV*] - - *msv*: `.msv .msvp` +- **spsd.c** + - Sega Naomi SPSD header [*SPSD*] + - *spsd*: `.str .spsd` + - Codecs: PCM16LE PCM8 AICA_int +- **rsd.c** + - Radical RSD header [*RSD*] + - *rsd*: `.rsd .rsp` + - Subfiles: *ogg_vorbis_config* + - Codecs: PCM16LE PCM16BE PSX XBOX_IMA_mch XBOX_IMA NGC_DSP NGC_DSP_subint RAD_IMA OGG FFmpeg(various) ATRAC3 XMA +- **bgw.c** + - Square Enix .BGW header [*FFXI_BGW*] + - Square Enix .SPW header [*FFXI_SPW*] + - *bgw*: `.bgw` + - *spw*: `.spw` + - Codecs: PSX_cfg ATRAC3 PCM16LE +- **ps2_ass.c** + - SystemSoft .ASS header [*PS2_ASS*] + - *ps2_ass*: `.ass` - Codecs: PSX -- **mta2.c** - - Konami MTA2 header [*MTA2*] - - *mta2*: `.mta2` - - *mta2_container*: `.dbm .bgm .mta2` - - Subfiles: *mta2* - - Codecs: MTA2 -- **mtaf.c** - - Konami MTAF header [*MTAF*] - - *mtaf*: `.mtaf` - - Codecs: MTAF +- **ubi_jade.c** + - Ubisoft Jade RIFF header [*UBI_JADE*] + - *ubi_jade*: `.waa .wac .wad .wam .wav .lwav` + - Subfiles: *msf* + - *ubi_jade_container*: `.waa .wac .wad .wam .wav .lwav .xma` + - Subfiles: *xma ubi_jade* + - Codecs: XBOX_IMA PSX NGC_DSP MSADPCM +- **seg.c** + - Stormfront SEG header [*SEG*] + - *seg*: `.seg` + - Codecs: PSX XBOX_IMA NGC_DSP IMA MPEG XMA2 +- **nds_strm_ffta2.c** + - Final Fantasy Tactics A2 RIFF Header [*NDS_STRM_FFTA2*] + - *nds_strm_ffta2*: `.bin .strm` + - Codecs: FFTA2_IMA +- **knon.c** + - Paon KNON header [*KNON*] + - *knon*: `.str .asr` + - Codecs: NGC_DSP PCM16BE +- **gca.c** + - GCA DSP Header [*GCA*] + - *gca*: `.gca` + - Codecs: NGC_DSP +- **spt_spd.c** + - SPT+SPD DSP Header [*SPT_SPD*] + - *spt_spd*: `.spd + .spt` + - Codecs: NGC_DSP PCM16BE +- **ish_isd.c** + - ISH+ISD DSP Header [*ISH_ISD*] + - *ish_isd*: `.isd + .ish` + - Codecs: NGC_DSP +- **gsp_gsb.c** + - Tecmo GSP+GSB Header [*GSP_GSB*] + - *gsp_gsb*: `.gsb + .gsp` + - Codecs: NGC_DSP ATRAC3 XMA +- **ydsp.c** + - Yuke's YDSP Header [*YDSP*] + - *ydsp*: `.ydsp` + - Codecs: NGC_DSP +- **ngc_ssm.c** + - SSM DSP Header [*NGC_SSM*] + - *ngc_ssm*: `.ssm` + - Codecs: NGC_DSP +- **ps2_joe.c** + - Asobo Studio .JOE header [*PS2_JOE*] + - *ps2_joe*: `.joe` + - Codecs: PSX +- **vgs.c** + - Guitar Hero VGS Header [*VGS*] + - *vgs*: `.vgs` + - Codecs: PSX_badflags +- **dcs_wav.c** + - In Utero DCS+WAV header [*DCS_WAV*] + - *dcs_wav*: `.dcs + .wav` + - Codecs: AICA_int - **mul.c** - Crystal Dynamics .MUL header [*MUL*] - *mul*: `.mul .emff` - Subfiles: *fsb* - Codecs: PSX NGC_DSP CD_IMA XMA1 -- **mups.c** - - (container) - - *mups*: `.mups .(extensionless)` - - Subfiles: *ogg_vorbis* -- **musc.c** - - Krome MUSC header [*MUSC*] - - *musc*: `.mus .musc` +- **thp.c** + - Nintendo THP header [*THP*] + - *thp*: `.thp .dsp .mov .(extensionless)` + - Codecs: NGC_DSP +- **sts.c** + - Alfa System .STS header [*STS*] + - *sts*: `.sts` + - Codecs: NGC_DSP +- **ps2_p2bt.c** + - Pop'n'Music 7 Header [*PS2_P2BT*] + - *ps2_p2bt*: `.p2bt` + - Codecs: PSX +- **ps2_gbts.c** + - Pop'n'Music 9 Header [*PS2_GBTS*] + - *ps2_gbts*: `.gbts` + - Codecs: PSX +- **wii_sng.c** + - SNG DSP Header [*WII_SNG*] + - *wii_sng*: `.sng` + - Codecs: NGC_DSP +- **aax.c** + - CRI AAX header [*AAX*] + - *aax*: `.aax .(extensionless)` + - Subfiles: *hca adx* +- **csb.c** + - CRI ADPCM_WII header [*UTF_DSP*] + - *csb*: `.csb` + - Subfiles: *aax utf_ahx utf_dsp* + - *utf_dsp*: `.aax .(extensionless)` + - *utf_ahx*: `.aax .(extensionless)` + - Subfiles: *ahx* + - Codecs: NGC_DSP +- **ngc_ffcc_str.c** + - Final Fantasy: Crystal Chronicles STR header [*FFCC_STR*] + - *ngc_ffcc_str*: `.str` + - Codecs: NGC_DSP +- **sat_baka.c** + - Konami BAKA header [*SAT_BAKA*] + - *sat_baka*: `.(extensionless) .baka` + - Codecs: PCM16BE +- **swav.c** + - Nintendo SWAV header [*SWAV*] + - *swav*: `.swav .adpcm` + - Codecs: PCM8 PCM16LE IMA_int +- **vsf.c** + - Square Enix VSF header [*VSF*] + - *vsf*: `.vsf` - Codecs: PSX -- **musx.c** - - Eurocom MUSX header [*MUSX*] - - *musx*: `.sfx .musx` - - Codecs: PSX DAT4_IMA DVI_IMA_int XBOX_IMA NGC_DSP PCM16BE PCM16LE -- **mus_acm.c** - - InterPlay MUS ACM header [*MUS_ACM*] - - *mus_acm*: `.mus` - - Subfiles: *acm ogg_vorbis* -- **mus_vc.c** - - Vicious Cycle .MUS header [*MUS_VC*] - - *mus_vc*: `.mus` - - Codecs: NGC_DSP XBOX_IMA -- **myspd.c** - - Punchers Impact .MYSPD header [*MYSPD*] - - *myspd*: `.myspd` - - Codecs: IMA_int -- **naac.c** - - Namco NAAC header [*NAAC*] - - *naac*: `.naac` - - Codecs: AAC -- **naomi_adpcm.c** - - NAOMI/NAOMI2 Arcade games ADPCM header [*NAOMI_ADPCM*] - - *naomi_adpcm*: `.adpcm` - - Codecs: AICA_int -- **nds_hwas.c** - - Vicarious Visions HWAS header [*NDS_HWAS*] - - *nds_hwas*: `.hwas` - - Codecs: IMA_int - **nds_rrds.c** - Ridger Racer DS Header [*NDS_RRDS*] - *nds_rrds*: `.(extensionless) .rrds` - Codecs: IMA_int -- **nds_strm.c** - - Nintendo STRM header [*STRM*] - - *nds_strm*: `.strm` - - Codecs: PCM8 PCM16LE NDS_IMA -- **nds_strm_ffta2.c** - - Final Fantasy Tactics A2 RIFF Header [*NDS_STRM_FFTA2*] - - *nds_strm_ffta2*: `.bin .strm` - - Codecs: FFTA2_IMA -- **ngc_adpdtk.c** - - Nintendo DTK raw header [*DTK*] - - *dtk*: `.dtk .adp .trk .wav .lwav` - - Codecs: NGC_DTK -- **ngc_dsp_konami.c** - - Konami DSP header [*NGC_DSP_KONAMI*] - - *ngc_dsp_konami*: `.dsp` - - Codecs: NGC_DSP -- **ngc_dsp_mpds.c** - - MPDS DSP header [*NGC_DSP_MPDS*] - - *ngc_dsp_mpds*: `.dsp .mds` - - Codecs: NGC_DSP -- **ngc_dsp_std.c** - - Nintendo DSP header [*DSP_STD*] - - Intelligent Systems STM header [*DSP_STM*] - - Single DSP header stereo by .mpdsp extension [*DSP_MPDSP*] - - Double DSP header stereo by _lr.dsp extension [*DSP_JETTERS*] - - Double DSP header stereo by .mss extension [*DSP_MSS*] - - Double DSP header stereo by .gcm extension [*DSP_GCM*] - - Namco IDSP header [*IDSP_NAMCO*] - - Procyon Studio SADB header [*DSP_SADB*] - - Traveller's Tales IDSP header [*IDSP_TT*] - - Next Level IDSP header [*IDSP_NL*] - - .WSD header [*DSP_WII_WSD*] - - .DDSP header [*DSP_DDSP*] - - Sumo Digital iSWS header [*WII_WAS*] - - Infogrames .DSP header [*DSP_STR_IG*] - - XIII dsp header [*DSP_XIII*] - - Icon Games NDP header [*WII_NDP*] - - Cabelas games .DSP header [*DSP_CABELAS*] - - Acclaim Austin AAAp DSP header [*NGC_DSP_AAAP*] - - Capcom DSPW header [*DSP_DSPW*] - - IADP Header [*NGC_DSP_IADP*] - - Bethesda .mcadpcm header [*DSP_MCADPCM*] - - UE4 Switch Audio header [*DSP_SWITCH_AUDIO*] - - .VAG DSP header [*DSP_VAG*] - - .ITL DSP header [*DSP_ITL*] - - AQUASTYLE ADPY header [*DSP_ADPY*] - - AQUASTYLE ADPX header [*DSP_ADPX*] - - LucasArts .DS2 header [*DSP_DS2*] - - Infernal .ITL DSP header [*DSP_ITL_i*] - - Square Enix DSP header [*DSP_SQEX*] - - Koei Tecmo WiiVoice header [*DSP_WIIVOICE*] - - Exient WIIADPCM header [*DSP_WIIADPCM*] - - CRI CWAC header [*DSP_CWAC*] - - TOSE .IDSP header [*IDSP_TOSE*] - - Kuju London .KWA header [*DSP_KWA*] - - Koei Tecmo APEX header [*DSP_APEX*] - - *ngc_dsp_std*: `.dsp .adp .(extensionless)` - - *ngc_dsp_std_le*: `.adpcm` - - *ngc_mdsp_std*: `.dsp .mdsp` - - *ngc_dsp_stm*: `.stm .lstm .dsp` - - *ngc_mpdsp*: `.mpdsp .ste` - - *ngc_dsp_std_int*: `.dsp .mss .gcm` - - *idsp_namco*: `.idsp` - - *sadb*: `.sad` - - *idsp_tt*: `.gcm .idsp .wua` - - *idsp_nl*: `.idsp` - - *wii_wsd*: `.wsd` - - *dsp_ddsp*: `.adp .ddsp .wav .lwav` - - *wii_was*: `.was .dsp .isws` - - *dsp_str_ig*: `.str` - - *dsp_xiii*: `.dsp` - - *dsp_ndp*: `.nds .ndp` - - *dsp_cabelas*: `.dsp` - - *ngc_dsp_aaap*: `.dsp` - - *dsp_dspw*: `.dspw` - - *ngc_dsp_iadp*: `.adp .iadp` - - *dsp_mcadpcm*: `.mcadpcm` - - *dsp_switch_audio*: `.switch_audio .dsp` - - *dsp_sps_n1*: `.vag .nlsd` - - *dsp_itl_ch*: `.itl` - - *dsp_adpy*: `.adpcmx` - - *dsp_adpx*: `.adpcmx` - - *dsp_ds2*: `.ds2 .dsp` - - *dsp_itl*: `.itl .dsp` - - *dsp_sqex*: `.wav .lwav` - - *dsp_wiivoice*: `.dsp` - - *dsp_wiiadpcm*: `.adpcm` - - *dsp_cwac*: `.dsp` - - *idsp_tose*: `.idsp` - - *dsp_kwa*: `.kwa` - - *dsp_apex*: `.dsp` - - Codecs: NGC_DSP NGC_DSP_subint -- **ngc_dsp_ygo.c** - - Konami custom DSP Header [*DSP_YGO*] - - *dsp_ygo*: `.dsp` - - Codecs: NGC_DSP -- **ngc_ffcc_str.c** - - Final Fantasy: Crystal Chronicles STR header [*FFCC_STR*] - - *ngc_ffcc_str*: `.str` +- **vsf_tta.c** + - VSF with SMSS Header [*PS2_VSF_TTA*] + - *ps2_vsf_tta*: `.vsf` + - Codecs: PSX +- **ads_midway.c** + - Midway ADS header [*ADS_MIDWAY*] + - *ads_midway*: `.ads` + - Codecs: NGC_DSP XBOX_IMA_int +- **ps2_mcg.c** + - Gunvari MCG Header [*PS2_MCG*] + - *ps2_mcg*: `.mcg` + - Codecs: PSX +- **zsd.c** + - Konami ZSD header [*ZSD*] + - *zsd*: `.zsd` + - Codecs: PCM8 +- **vgs_ps.c** + - Princess Soft VGS header [*VGS_PS*] + - *vgs_ps*: `.vgs` + - Codecs: PSX +- **redspark.c** + - RedSpark Header [*REDSPARK*] - Codecs: NGC_DSP +- **ivaud.c** + - Rockstar .ivaud header [*IVAUD*] + - *ivaud*: `.ivaud .(extensionless)` + - Codecs: PCM16LE XMA1 MPEG IMA_int +- **ps2_sps.c** + - Ape Escape 2 SPS Header [*PS2_SPS*] + - *ps2_sps*: `.sps` + - Codecs: PCM16LE +- **nds_hwas.c** + - Vicarious Visions HWAS header [*NDS_HWAS*] + - *nds_hwas*: `.hwas` + - Codecs: IMA_int - **ngc_lps.c** - Rave Master LPS Header [*NGC_LPS*] - *ngc_lps*: `.lps` - Codecs: NGC_DSP -- **ngc_nst_dsp.c** - - Animaniacs NST header [*NGC_NST_DSP*] - - *ngc_nst_dsp*: `.dsp` - - Codecs: NGC_DSP -- **ngc_pdt.c** - - Hudson .PDT header [*NGC_PDT*] - - *ngc_pdt*: `.pdt` - - *ngc_pdt_split*: `.pdt` +- **ps2_snd.c** + - Might and Magic SSND Header [*PS2_SND*] + - *ps2_snd*: `.snd` + - Codecs: DVI_IMA_int PCM16LE +- **naomi_adpcm.c** + - NAOMI/NAOMI2 Arcade games ADPCM header [*NAOMI_ADPCM*] + - *naomi_adpcm*: `.adpcm` + - Codecs: AICA_int +- **sd9.c** + - beatmania IIDX SD9 header [*SD9*] + - *sd9*: `.sd9` + - Codecs: MSADPCM +- **2dx9.c** + - beatmania IIDX 2DX9 header [*2DX9*] + - *2dx9*: `.2dx9` + - Codecs: MSADPCM +- **ngc_dsp_ygo.c** + - Konami custom DSP Header [*DSP_YGO*] + - *dsp_ygo*: `.dsp` - Codecs: NGC_DSP +- **ps2_vgv.c** + - Rune: Viking Warlord VGV Header [*PS2_VGV*] + - *ps2_vgv*: `.vgv` + - Codecs: PSX +- **gcub.c** + - Sega GCub header [*GCUB*] + - *gcub*: `.wav .lwav .gcub` + - Codecs: NGC_DSP_subint NGC_DSP +- **maxis_xa.c** + - Maxis XA Header [*MAXIS_XA*] + - *maxis_xa*: `.xa` + - Codecs: MAXIS_XA - **ngc_sck_dsp.c** - The Scorpion King SCK Header [*NGC_SCK_DSP*] - *ngc_sck_dsp*: `.dsp + .sck` - Codecs: NGC_DSP -- **ngc_ssm.c** - - SSM DSP Header [*NGC_SSM*] - - *ngc_ssm*: `.ssm` - - Codecs: NGC_DSP -- **ngc_str_cauldron.c** - - Cauldron .STR header [*DSP_STR*] - - *ngc_str*: `.str` - - Codecs: NGC_DSP -- **ngc_tydsp.c** - - .tydsp Header [*NGC_TYDSP*] - - *ngc_tydsp*: `.tydsp` - - Codecs: NGC_DSP -- **nps.c** - - Namco NPSF header [*NPS*] - - *nps*: `.nps .npsf` - - Codecs: PSX -- **nub.c** - - Namco NUB header [*NUB*] - - *nub*: `.nub .nub2 + .(external)` - - Subfiles: *nub_xma nub_wav nub_vag nub_at3 nub_dsp nub_idsp nub_is14 function* - - *nub_wav*: `.wav .lwav` - - *nub_vag*: `.vag` - - *nub_at3*: `.at3` - - Subfiles: *riff* - - *nub_xma*: `.xma` - - *nub_dsp*: `.dsp` - - Subfiles: *ngc_dsp_std* - - *nub_idsp*: `.idsp` - - Subfiles: *idsp_namco* - - *nub_is14*: `.is14` - - Subfiles: *bnsf* - - Codecs: PCM16BE PSX XMA -- **nus3audio.c** - - (container) - - *nus3audio*: `.nus3audio` - - Subfiles: *idsp_namco opus_nus3 riff bnsf* -- **nus3bank.c** - - (container) - - *nus3bank*: `.nub2 .nus3bank` - - Subfiles: *idsp_namco opus_nus3 riff bnsf ivag xma nus3bank_encrypted* - - *nus3bank_encrypted*: `.nus3bank .xma` - - Subfiles: *xma* -- **nwa.c** - - VisualArt's NWA header (NWAINFO.INI looping) [*NWA_NWAINFOINI*] - - VisualArt's NWA header (Gameexe.ini looping) [*NWA_GAMEEXEINI*] - - VisualArt's NWA header [*NWA*] - - *nwa*: `.nwa + .(external)` - - Codecs: PCM8 PCM16LE NWA -- **nwav.c** - - Chunsoft NWAV header [*NWAV*] - - *nwav*: `.nwav .(extensionless)` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG -- **nxa.c** - - Entergram NXA header [*NXA*] - - *opus_nxa*: `.nxa` - - Codecs: Opus -- **nxap.c** - - Nex NXAP header [*NXAP*] - - *nxap*: `.adp` - - Codecs: NXAP -- **ogg_opus.c** - - Ogg Opus header [*OGG_OPUS*] - - *ogg_opus*: `.opus .lopus .ogg .logg .bgm` - - Codecs: FFmpeg(various) -- **ogg_vorbis.c** - - Ogg Vorbis header (encrypted) [*OGG_encrypted*] - - Ogg Vorbis header [*OGG_VORBIS*] - - Ogg Vorbis header (KOVS) [*OGG_KOVS*] - - *ogg_vorbis* - - Subfiles: *ogg_vorbis* - - *ogg_vorbis_config*: `.ogg .logg .adx .rof .acm .sod .msa .bin .lbin .kvs .kovs .rpgmvo .ogg_ .bgm .gwm .mus .isd .sngw .lse .eno .um3 .u0 + .(external)` - - Subfiles: *ogg_vorbis_config ogg_vorbis_cfg_ovmi ogg_vorbis_tests ogg_vorbis_common ogg_vorbis_tink ogg_vorbis* - - Codecs: OGG OGG_VORBIS -- **ogl.c** - - Shin'en OGL header [*OGL*] - - *ogl*: `.ogl` - - Codecs: VORBIS_custom -- **ogv_3rdeye.c** - - 3rdEye .OGV header [*OGV_3RDEYE*] - - *ogv_3rdeye*: `.ogv` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG -- **omu.c** - - Outrage OMU Header [*OMU*] - - *omu*: `.omu` - - Codecs: PCM16LE -- **opus.c** - - Nintendo Switch OPUS header [*OPUS*] - - *opus_std*: `.opus .lopus .bgm .opu + .psi` - - *opus_n1*: `.opus .lopus` - - *opus_capcom*: `.opus .lopus` - - *opus_nop*: `.nop` - - *opus_shinen*: `.opus .lopus` - - *opus_nus3*: `.opus .lopus` - - *opus_sps_n1*: `.sps .nlsd .at9 .opus .lopus` - - *opus_opusx*: `.opusx` - - *opus_prototype*: `.opus .lopus` - - *opus_opusnx*: `.opus .lopus` - - *opus_nsopus*: `.nsopus` - - *opus_sqex*: `.wav .lwav` - - *opus_rsnd*: `.rsnd` - - Codecs: Opus -- **otm.c** - - Otomedius OTM Header [*OTM*] - - *otm*: `.otm` - - Codecs: PCM16LE -- **p3d.c** - - Radical P3D header [*P3D*] - - *p3d*: `.p3d` - - Codecs: RAD_IMA_mono MPEG XMA -- **pasx.c** - - Premium Agency PASX header [*PASX*] - - *pasx*: `.past .sgb` - - Codecs: XMA -- **pcm_sre.c** - - Capcom .PCM+SRE header [*PCM_SRE*] - - *pcm_sre*: `.pcm + .sre` - - Codecs: PSX -- **pcm_success.c** - - Success PCM header [*PCM_SUCCESS*] - - *pcm_success*: `.pcm` - - Codecs: PSX -- **pc_ast.c** - - Capcom AST (PC) header [*PC_AST*] - - *pc_ast*: `.ast` - - Codecs: PCM16LE +- **apple_caff.c** + - Apple Core Audio Format File header [*CAFF*] + - *apple_caff*: `.caf` + - Codecs: PCM8 APPLE_IMA4 - **pc_mxst.c** - Lego Island MxSt Header [*PC_MXST*] - *pc_mxst*: `.mxst` - Codecs: PCM8_U PCM16LE -- **piff_tpcm.c** - - Tantalus PIFF TPCM header [*PIFF_TPCM*] - - *piff_tpcm*: `.tad` - - Codecs: TANTALUS +- **sab.c** + - Sensaura SAB header [*SAB*] + - *sab*: `.sab + .sob` + - Codecs: PCM16LE PSX XBOX_IMA +- **wii_bns.c** + - Nintendo BNS header [*WII_BNS*] + - *wii_bns*: `.bin .lbin .bns` + - Codecs: NGC_DSP - **pona.c** - Policenauts BGM header [*PONA_3DO*] - Policenauts BGM header [*PONA_PSX*] - *pona_3do*: `.pona .sxd` - *pona_psx*: `.pona` - Codecs: SDX2 PSX -- **pos.c** - - RIFF WAVE header and .pos for looping [*RIFF_WAVE_POS*] - - *pos*: `.pos + .wav` - - Subfiles: *riff* -- **ppst.c** - - Parappa PPST header [*PPST*] - - *ppst*: `.sng` - - Subfiles: *riff* -- **ps2_2pfs.c** - - Konami 2PFS header [*PS2_2PFS*] - - *ps2_2pfs*: `.sap .2pfs` - - Codecs: PSX -- **ps2_adm.c** - - Dragon Quest V .ADM raw header [*PS2_ADM*] - - *ps2_adm*: `.adm + .(external)` - - Codecs: PSX -- **ps2_ass.c** - - SystemSoft .ASS header [*PS2_ASS*] - - *ps2_ass*: `.ass` - - Codecs: PSX -- **ps2_b1s.c** - - B1S header [*PS2_B1S*] - - *ps2_b1s*: `.b1s` - - Codecs: PSX -- **ps2_bg00.c** - - Falcom BG00 Header [*BG00*] - - *bg00*: `.bg00` - - Codecs: PSX -- **ps2_bmdx.c** - - Beatmania .bmdx header [*PS2_BMDX*] - - *ps2_bmdx*: `.bmdx` - - Codecs: PSX -- **ps2_filp.c** - - Bio Hazard - Gun Survivor FILp Header [*FILP*] - - *filp*: `.filp` +- **xwv_valve.c** + - Half-Life 2 .WAV header [*XBOX_HLWAV*] + - Valve XWV header [*XWV_VALVE*] + - *xbox_hlwav*: `.wav .lwav` + - *xwv_valve*: `.wav .lwav` + - Codecs: PCM16LE XBOX_IMA PCM16BE XMA2 +- **myspd.c** + - Punchers Impact .MYSPD header [*MYSPD*] + - *myspd*: `.myspd` + - Codecs: IMA_int +- **his.c** + - Her Interactive HIS header [*HIS*] + - *his*: `.his` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG PCM8_U PCM16LE OGG_VORBIS +- **ast_mmv.c** + - Marvelous AST header [*AST_MMV*] + - *ast_mmv*: `.ast` - Codecs: PSX -- **ps2_gbts.c** - - Pop'n'Music 9 Header [*PS2_GBTS*] - - *ps2_gbts*: `.gbts` +- **ast_mv.c** + - MicroVision AST header [*AST_MV*] + - *ast_mv*: `.ast` - Codecs: PSX +- **dmsg_segh.c** + - (container) + - *dmsg*: `.sgt .dmsg` + - Subfiles: *riff* +- **ngc_dsp_konami.c** + - Konami DSP header [*NGC_DSP_KONAMI*] + - *ngc_dsp_konami*: `.dsp` + - Codecs: NGC_DSP +- **ps2_wb.c** + - Shooting Love. ~TRIZEAL~ WB header [*PS2_WB*] + - *ps2_wb*: `.wb` + - Codecs: PCM16LE +- **bnsf.c** + - Namco Bandai BNSF header [*BNSF*] + - *bnsf*: `.bnsf + .(external)` + - Codecs: G7221C G719 - **ps2_gcm.c** - Namco GCM header [*PS2_GCM*] - *ps2_gcm*: `.gcm` - Codecs: PSX -- **ps2_hgc1.c** - - Knights of the Temple 2 hgC1 Header [*HGC1*] - - *hgc1*: `.hgc1` - - Codecs: PSX -- **ps2_hsf.c** - - Lowrider 'HSF' header [*PS2_HSF*] - - *ps2_hsf*: `.hsf` - - Codecs: PSX -- **ps2_iab.c** - - Runtime .IAB header [*PS2_IAB*] - - *ps2_iab*: `.iab` - - Codecs: PSX -- **ps2_joe.c** - - Asobo Studio .JOE header [*PS2_JOE*] - - *ps2_joe*: `.joe` - - Codecs: PSX -- **ps2_kces.c** - - Konami KCES Header [*PS2_KCES*] - - *ps2_kces*: `.kces` - - Codecs: PSX -- **ps2_mcg.c** - - Gunvari MCG Header [*PS2_MCG*] - - *ps2_mcg*: `.mcg` - - Codecs: PSX -- **ps2_mic.c** - - KOEI .MIC header [*PS2_MIC*] - - *mic_koei*: `.mic` - - Codecs: PSX -- **ps2_mihb.c** - - Sony MultiStream MIC header [*PS2_MIHB*] - - *ps2_mihb*: `.mic .mihb` - - Codecs: PSX -- **ps2_msa.c** - - Success .MSA header [*PS2_MSA*] - - *ps2_msa*: `.msa` +- **smpl.c** + - Skonec SMPL header [*SMPL*] + - *smpl*: `.v0 .v1` - Codecs: PSX -- **ps2_p2bt.c** - - Pop'n'Music 7 Header [*PS2_P2BT*] - - *ps2_p2bt*: `.p2bt` +- **msa.c** + - Success .MSA header [*MSA*] + - *msa*: `.msa` - Codecs: PSX -- **ps2_pcm.c** - - Konami KCEJ East .PCM header [*PS2_PCM*] - - *ps2_pcm*: `.pcm` +- **voi.c** + - Irem .VOI header [*VOI*] + - *voi*: `.voi` - Codecs: PCM16LE -- **ps2_rnd.c** - - Knights of the Temple 2 hgC1 Header [*HGC1*] - - *ps2_rnd*: `.rnd` +- **p3d.c** + - Radical P3D header [*P3D*] + - *p3d*: `.p3d` + - Codecs: RAD_IMA_mono MPEG XMA +- **ngc_dsp_mpds.c** + - MPDS DSP header [*NGC_DSP_MPDS*] + - *ngc_dsp_mpds*: `.dsp .mds` + - Codecs: NGC_DSP +- **ea_swvr.c** + - Electronic Arts SWVR header [*EA_SWVR*] + - *ea_swvr*: `.stream .str` + - Codecs: PSX NGC_DSP PCM8_U_int +- **ps2_b1s.c** + - B1S header [*PS2_B1S*] + - *ps2_b1s*: `.b1s` - Codecs: PSX -- **ps2_sl3.c** - - Atari Melbourne House SL3 header [*SL3*] - - *sl3*: `.ms .sl3` +- **ps2_wad.c** + - WAD header [*PS2_WAD*] + - *ps2_wad*: `.wad` - Codecs: PSX -- **ps2_snd.c** - - Might and Magic SSND Header [*PS2_SND*] - - *ps2_snd*: `.snd` - - Codecs: DVI_IMA_int PCM16LE -- **ps2_sps.c** - - Ape Escape 2 SPS Header [*PS2_SPS*] - - *ps2_sps*: `.sps` +- **lpcm_shade.c** + - Shade LPCM header [*LPCM_SHADE*] + - *lpcm_shade*: `.w .lpcm` - Codecs: PCM16LE -- **ps2_va3.c** - - Konami VA3 header [*VA3*] - - *va3*: `.va3` - - Codecs: ATRAC3 -- **ps2_vas.c** - - Konami .VAS header [*PS2_VAS*] - - *ps2_vas*: `.vas` - - *ps2_vas_container*: `.vas` - - Subfiles: *ps2_vas* - - Codecs: PSX -- **ps2_vbk.c** - - PS2 VBK Header [*PS2_VBK*] - - *ps2_vbk*: `.vbk` - - Codecs: PSX -- **ps2_vds_vdm.c** - - Procyon Studio VDS/VDM header [*PS2_VDS_VDM*] - - *ps2_vds_vdm*: `.vds .vdm` - - Codecs: PSX -- **ps2_vgv.c** - - Rune: Viking Warlord VGV Header [*PS2_VGV*] - - *ps2_vgv*: `.vgv` - - Codecs: PSX - **ps2_vms.c** - VMS Header [*PS2_VMS*] - *ps2_vms*: `.vms` - Codecs: PSX -- **ps2_wad.c** - - WAD header [*PS2_WAD*] - - *ps2_wad*: `.wad` - - Codecs: PSX -- **ps2_wb.c** - - Shooting Love. ~TRIZEAL~ WB header [*PS2_WB*] - - *ps2_wb*: `.wb` +- **xau.c** + - XPEC XAU header [*XAU*] + - *xau*: `.xau` + - Codecs: PSX XBOX_IMA +- **bar.c** + - Guitar Hero III Mobile .bar [*GH3_BAR*] + - *bar*: `.bar` + - Codecs: IMA +- **ffw.c** + - Freedom Fighters BGM header [*FFW*] + - *ffw*: `.ffw` + - Codecs: PCM16BE +- **jstm.c** + - JSTM Header [*PS2_JSTM*] + - *jstm*: `.stm .jstm` - Codecs: PCM16LE -- **ps2_wmus.c** - - assumed The Warriors Sony ADPCM by .wmus extension [*PS2_WMUS*] - - *ps2_wmus*: `.wmus` - - Codecs: PSX -- **ps2_xa30.c** - - Reflections XA30 PS2 header [*PS2_XA30*] - - *ps2_xa30*: `.xa .xa30` - - Codecs: PSX +- **xvag.c** + - Sony XVAG header [*XVAG*] + - *xvag*: `.xvag .(extensionless)` + - Codecs: PSX MPEG ATRAC9 +- **cps.c** + - tri-Crescendo CPS Header [*CPS*] + - *cps*: `.cps` + - Codecs: PCM16BE PSX +- **sqex_scd.c** + - Square Enix SCD header [*SQEX_SCD*] + - *sqex_scd*: `.scd` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG PCM16LE PSX MPEG MSADPCM NGC_DSP XMA ATRAC3 ATRAC9 +- **ngc_nst_dsp.c** + - Animaniacs NST header [*NGC_NST_DSP*] + - *ngc_nst_dsp*: `.dsp` + - Codecs: NGC_DSP +- **baf.c** + - Bizarre Creations .baf header [*BAF*] + - *baf*: `.baf` + - Codecs: PCM16LE PSX_cfg XMA1 +- **msf.c** + - Sony MSF header [*MSF*] + - *msf*: `.msf .msa .at3 .mp3 .str` + - Codecs: PCM16BE PCM16LE PSX ATRAC3 FFmpeg(various) - **ps3_past.c** - SNDP header [*PS3_PAST*] - *ps3_past*: `.past` - Codecs: PCM16LE -- **psb.c** - - M2 PSB header [*PSB*] - - *psb*: `.psb` - - Subfiles: *riff vag* - - Codecs: PCM16LE PCM24LE MSADPCM XWMA XMA NGC_DSP Opus -- **psf.c** - - Pivotal PSF header [*PSF*] - - *psf_single*: `.psf .swd` - - *psf_segmented*: `.psf .swd` - - Subfiles: *psf_single* - - *psf_pfsm*: `.psf` - - *sch*: `.sch + .(external)` - - Subfiles: *psf_segmented psf_single* - - Codecs: PSX PSX_pivotal NGC_DSP PCM16BE -- **pwb.c** - - Double Fine WB header [*PWB*] - - *pwb*: `.pwb` - - Codecs: PSX -- **rad.c** - - Traveller's Tales .RAD header [*RAD*] - - *rad*: `.rad` - - Codecs: PCM16LE -- **raw_int.c** - - PS2 .int raw header [*RAW_INT*] - - *raw_int*: `.int .wp2` - - Codecs: PCM16LE -- **raw_pcm.c** - - PC .raw raw header [*RAW_PCM*] - - *raw_pcm*: `.raw` - - Codecs: PCM16LE -- **raw_rsf.c** - - Retro Studios .RSF raw header [*RSF*] - - *raw_rsf*: `.rsf` - - Codecs: G721 -- **raw_s14_sss.c** - - Namco .S14 raw header [*S14*] - - Namco .SSS raw header [*SSS*] - - *raw_s14_sss*: `.sss .s14` - - Codecs: G7221C -- **raw_snds.c** - - PC .snds raw header [*RAW_SNDS*] - - *raw_snds*: `.snds` - - Codecs: SNDS_IMA -- **raw_wavm.c** - - Xbox .wavm raw header [*RAW_WAVM*] - - *raw_wavm*: `.wavm` - - Codecs: XBOX_IMA -- **redspark.c** - - RedSpark Header [*REDSPARK*] - - Codecs: NGC_DSP -- **rfrm.c** - - Retro Studios RFRM header [*RFRM*] - - *rfrm_mpr*: `.csmp` - - *rfrm*: `.csmp` - - Codecs: NGC_DSP -- **riff.c** - - RIFF WAVE header [*RIFF_WAVE*] - - RIFF WAVE header with loop markers [*RIFF_WAVE_labl*] - - RIFF WAVE header with sample looping info [*RIFF_WAVE_smpl*] - - RIFF WAVE header with wsmp looping info [*RIFF_WAVE_wsmp*] - - RIFF WAVE header with .mwv flavoring [*RIFF_WAVE_MWV*] - - RIFX WAVE header [*RIFX_WAVE*] - - RIFX WAVE header with sample looping info [*RIFX_WAVE_smpl*] - - *riff*: `.wav .lwav .xwav .mwv .da .dax .cd .med .snd .adx .adp .xss .xsew .adpcm .adw .wd .(extensionless) .sbv .wvx .str .at3 .rws .aud .at9 .ckd .saf .ima .nsa .pcm .xvag .ogg .logg .p1d .xms .mus .dat .ldat` - - *rifx*: `.wav .lwav` - - Codecs: AICA_int PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int -- **rkv.c** - - Legacy of Kain - Blood Omen 2 RKV PS2 header [*PS2_RKV*] - - Legacy of Kain - Blood Omen 2 RKV GC header [*NGC_RKV*] - - *ps2_rkv*: `.rkv` - - *ngc_rkv*: `.(extensionless) .rkv .bo2` - - Codecs: PSX NGC_DSP -- **rs03.c** - - Retro Studios RS03 header [*DSP_RS03*] - - *rs03*: `.dsp` - - Codecs: NGC_DSP -- **rsd.c** - - Radical RSD header [*RSD*] - - *rsd*: `.rsd .rsp` - - Subfiles: *ogg_vorbis_config* - - Codecs: PCM16LE PCM16BE PSX XBOX_IMA_mch XBOX_IMA NGC_DSP NGC_DSP_subint RAD_IMA OGG FFmpeg(various) ATRAC3 XMA -- **rstm_rockstar.c** - - Rockstar Games RSTM Header [*RSTM_ROCKSTAR*] - - *rstm_rockstar*: `.rsm .rstm` - - Codecs: PSX -- **rwax.c** - - Konami RWAX header [*RWAX*] - - *rwax*: `.rwx` - - Codecs: PCM16LE -- **rws_809.c** - - RenderWare RWS header [*RWS*] - - *rws_809*: `.rws` - - Codecs: PSX NGC_DSP PCM16BE PCM16LE -- **rws_80d.c** - - RenderWare RWS header [*RWS*] - - *rws_80d*: `.rws` - - Codecs: PCM16_int PCM16BE PCM16LE PSX NGC_DSP XBOX_IMA -- **rwsd.c** - - Nintendo RWSD header (single stream) [*RWSD*] - - *rwsd*: `.brwsd .rwsd` - - Codecs: PCM8 PCM16BE NGC_DSP -- **rxws.c** - - Sony RXWS header [*RXWS*] - - *rxws*: `.xwb .xws + .xwh .xwb` - - Codecs: PSX PCM16LE ATRAC3 -- **s3v.c** - - Konami S3V header [*S3V*] - - *s3v*: `.s3v` - - Codecs: FFmpeg(various) -- **sab.c** - - Sensaura SAB header [*SAB*] - - *sab*: `.sab + .sob` - - Codecs: PCM16LE PSX XBOX_IMA -- **sadf.c** - - Procyon Studio SADF header [*SADF*] - - *sadf*: `.sad .nop .(extensionless)` - - Codecs: NGC_DSP -- **sadl.c** - - Procyon Studio SADL header [*SADL*] - - *sadl*: `.sad` - - Codecs: IMA_int NDS_PROCYON -- **sat_baka.c** - - Konami BAKA header [*SAT_BAKA*] - - *sat_baka*: `.(extensionless) .baka` - - Codecs: PCM16BE -- **sat_dvi.c** - - Konami KCEN DVI. header [*SAT_DVI*] - - *sat_dvi*: `.pcm .dvi` - - Codecs: DVI_IMA_int -- **sat_sap.c** - - VING .SAP header [*SAP*] - - *sat_sap*: `.sap` - - Codecs: PCM16BE -- **sbk.c** - - Team17 SBK header [*SBK*] - - *sbk*: `.sbk` - - Codecs: PCM8_U PCM16LE MS_IMA -- **scd_pcm.c** - - Lunar: Eternal Blue .PCM header [*SCD_PCM*] - - *scd_pcm*: `.pcm` - - Codecs: PCM8_SB -- **sd9.c** - - beatmania IIDX SD9 header [*SD9*] - - *sd9*: `.sd9` - - Codecs: MSADPCM -- **sdf.c** - - Beyond Reality SDF header [*SDF*] - - *sdf*: `.sdf` - - Codecs: PCM16LE PSX NGC_DSP -- **sdrh.c** - - feelplus SDRH header [*SDRH*] - - *sdrh_new*: `.xse` - - *sdrh_old*: `.xse` - - Codecs: PSX MPEG XMA2 ATRAC3 XMA1 -- **sdt.c** - - High Voltage .sdt header [*SDT*] - - *sdt*: `.sdt` - - Codecs: NGC_DSP -- **seb.c** - - Game Arts .SEB header [*SEB*] - - *seb*: `.seb .gms .(extensionless)` - - Codecs: PSX -- **seg.c** - - Stormfront SEG header [*SEG*] - - *seg*: `.seg` - - Codecs: PSX XBOX_IMA NGC_DSP IMA XMA2 -- **sfh.c** - - (container) - - *sfh*: `.at3 .sspr` - - Subfiles: *riff sspr* -- **sfl.c** - - Ogg Vorbis header (SFPL looping) [*OGG_SFL*] - - *sfl_ogg*: `.sfl .ogg + .(external) .ogg` - - Subfiles: *ogg_vorbis* - **sgxd.c** - Sony SGXD header [*SGXD*] - *sgxd*: `.sgb .sgx .sgd + .sgh .sgb` - Codecs: PCM16BE OGG_VORBIS PSX ATRAC3 PSX_cfg FFmpeg(various) -- **sk_aud.c** - - Silicon Knights AUD header [*SK_AUD*] - - *sk_aud*: `.aud` - - Codecs: VORBIS_custom -- **sli.c** - - (container) - - *sli_loops*: `.sli + .(external)` - - Subfiles: *ogg_opus ogg_vorbis riff* -- **smc_smh.c** - - Genki SMC+SMH header [*SMC_SMH*] - - *smc_smh*: `.smc + .smh` - - Codecs: PSX -- **smk.c** - - RAD Game Tools SMACKER header [*SMACKER*] - - *smk*: `.smk` - - Codecs: FFmpeg(various) -- **smp.c** - - Infernal Engine .smp header [*SMP*] - - *smp*: `.smp .snb` - - Codecs: ATRAC3 NGC_DSP MSADPCM PSX XMA2 -- **smpl.c** - - Skonec SMPL header [*SMPL*] - - *smpl*: `.v0 .v1` - - Codecs: PSX -- **smv.c** - - extreme .SMV header [*SMV*] - - *smv*: `.smv` - - Codecs: PSX -- **sndz.c** - - Sony SNDZ header [*SNDZ*] - - *sndz*: `.szd1 .szd .szd3 + .szd2` - - Codecs: PCM16LE PCM24LE PCMFLOAT HEVAG ATRAC9 +- **wii_ras.c** + - RAS header [*WII_RAS*] + - *wii_ras*: `.ras` + - Codecs: NGC_DSP - **spm.c** - Square SPM header [*SPM*] - *spm*: `.spm` - Codecs: PCM16LE -- **spsd.c** - - Sega Naomi SPSD header [*SPSD*] - - *spsd*: `.str .spsd` - - Codecs: PCM16LE PCM8 AICA_int -- **sps_n1.c** - - Nippon Ichi .SPS header [*SPS_N1*] - - *sps_n1*: `.sps` - - Subfiles: *vag riff* - - *sps_n1_segmented*: `.at9 .nlsd` - - Subfiles: *ogg_vorbis opus_std* -- **spt_spd.c** - - SPT+SPD DSP Header [*SPT_SPD*] - - *spt_spd*: `.spd + .spt` - - Codecs: NGC_DSP PCM16BE -- **sqex_scd.c** - - Square Enix SCD header [*SQEX_SCD*] - - *sqex_scd*: `.scd` - - Subfiles: *ogg_vorbis_config* - - Codecs: OGG PCM16LE PSX MPEG MSADPCM NGC_DSP XMA ATRAC3 ATRAC9 -- **sqex_sead.c** - - Square Enix SAB header [*SQEX_SAB*] - - Square Enix MAB header [*SQEX_MAB*] - - *sqex_sead*: `.sab .mab .sbin` - - Subfiles: *ogg_vorbis_config hca* - - Codecs: PCM16LE MSADPCM OGG ATRAC9 MPEG -- **sscf.c** - - Square Enix SSCF header [*SSCF*] - - *sscf*: `.scd` +- **ps2_iab.c** + - Runtime .IAB header [*PS2_IAB*] + - *ps2_iab*: `.iab` - Codecs: PSX -- **sscf_encrypted.c** - - (container) - - *sscf_encrypted*: `.scd` - - Subfiles: *xma* -- **sspf.c** - - Konami SSPF header [*SSPF*] - - *sspf*: `.ssp` - - Codecs: PCM16BE MTA2 -- **sspr.c** - - (container) - - *sspr*: `.sspr` - - Subfiles: *riff* -- **ster.c** - - ALCHEMY STER header [*STER*] - - *ster*: `.ster .sfs` +- **vs_str.c** + - Square .VS STRx header [*VS_STR*] + - *vs_str*: `.vs .str` - Codecs: PSX -- **sthd.c** - - Dream Factory STHD header [*STHD*] - - *sthd*: `.stx` - - Codecs: XBOX_IMA_int -- **stm.c** - - Angel Studios/Rockstar San Diego STMA header [*STM*] - - *stm*: `.stm .lstm` - - Codecs: NGC_DSP DVI_IMA_int PCM16BE PCM16LE -- **strm_abylight.c** - - Abylight STRM header [*STRM_ABYLIGHT*] - - *strm_abylight*: `.strm` - - Codecs: AAC -- **str_snds.c** - - 3DO SNDS header [*STR_SNDS*] - - *str_snds*: `.str .stream .3do` - - Codecs: SDX2_int SDX2 CBD2_int CBD2 -- **str_wav.c** - - Blitz Games .STR+WAV header [*STR_WAV*] - - *str_wav*: `.str .data .wav .wma .(extensionless) + .(external) .wav .sth` - - Codecs: PSX NGC_DSP XBOX_IMA BLITZ_IMA FFmpeg(various) XMA2 -- **sts.c** - - Alfa System .STS header [*STS*] - - *sts*: `.sts` - - Codecs: NGC_DSP -- **svag_kcet.c** - - Konami SVAG header [*SVAG_KCET*] - - *svag_kcet*: `.svag` - - Codecs: PSX -- **svag_snk.c** - - SNK SVAG header [*SVAG_SNK*] - - *svag_snk*: `.svag` +- **lsf.c** + - Gizmondo Studios Helsingborg LSF header [*LSF_N1NJ4N*] + - *lsf_n1nj4n*: `.lsf` + - Codecs: PSX_cfg LSF +- **xwav.c** + - feelplus XWAV header [*XWAV*] + - *xwav_new*: `.xwv .vawx` + - *xwav_old*: `.xwv` + - Codecs: PSX XMA2 ATRAC3 +- **mattel_hyperscan.c** + - Mattel Hyperscan KVAG [*HYPERSCAN_KVAG*] + - *hyperscan_kvag*: `.bvg` + - Codecs: DVI_IMA +- **ios_psnd.c** + - PSND Header [*IOS_PSND*] + - *ios_psnd*: `.psnd` + - Codecs: PCM16LE +- **adp_wildfire.c** + - Wildfire ADP! header [*ADP_WILDFIRE*] + - *adp_wildfire*: `.adp` + - Codecs: DVI_IMA_int +- **adp_qd.c** + - Quantic Dream .ADP header [*QD_ADP*] + - *adp_qd*: `.adp` + - Codecs: QD_IMA +- **excitebots.c** + - Excitebots .sfx header [*EB_SFX*] + - assumed Excitebots .sf0 by extension [*EB_SF0*] + - *eb_sfx*: `.sfx` + - *eb_sf0*: `.sf0` + - Codecs: PCM16BE NGC_DSP +- **mtaf.c** + - Konami MTAF header [*MTAF*] + - *mtaf*: `.mtaf` + - Codecs: MTAF +- **alp.c** + - High Voltage ALP header [*ALP*] + - *alp*: `.tun .pcm` + - Codecs: HV_IMA +- **wpd.c** + - WPD 'DPW' header [*WPD*] + - *wpd*: `.wpd` + - Codecs: PCM16LE +- **mn_str.c** + - Mini Ninjas 'STR' header [*MN_STR*] + - *mn_str*: `.mnstr` + - Codecs: PCM16LE +- **mss.c** + - Guerilla MCSS header [*MSS*] + - *mss*: `.mss` + - Codecs: XBOX_IMA PSX +- **ps2_hsf.c** + - Lowrider 'HSF' header [*PS2_HSF*] + - *ps2_hsf*: `.hsf` - Codecs: PSX -- **svg.c** - - High Voltage SVG header [*SVG*] - - *svg*: `.svg` +- **ivag.c** + - Namco IVAG header [*IVAG*] + - *ivag*: `.ivag` - Codecs: PSX -- **svs.c** - - Square SVS header [*SVS*] - - *svs*: `.svs` +- **ps2_2pfs.c** + - Konami 2PFS header [*PS2_2PFS*] + - *ps2_2pfs*: `.sap .2pfs` - Codecs: PSX -- **swav.c** - - Nintendo SWAV header [*SWAV*] - - *swav*: `.swav .adpcm` - - Codecs: PCM8 PCM16LE IMA_int -- **sxd.c** - - Sony SXD header [*SXD*] - - *sxd*: `.sxd .sxd2 .sxd3 + .sxd1` - - Codecs: PSX HEVAG ATRAC9 -- **tac.c** - - tri-Ace Codec header [*TAC*] - - *tac*: `.(extensionless) .aac .laac` - - Codecs: TAC -- **tgc.c** - - Tiger Game.com .4 header [*TGC*] - - *tgc*: `.4` - - Codecs: TGC -- **thp.c** - - Nintendo THP header [*THP*] - - *thp*: `.thp .dsp .mov .(extensionless)` - - Codecs: NGC_DSP -- **tt_ad.c** - - Traveller's Tales AUDIO_DATA header [*TT_AD*] - - *tt_ad*: `.audio_data` - - Codecs: OGG_VORBIS MS_IMA_mono -- **ubi_bao.c** - - Ubisoft BAO header [*UBI_BAO*] - - *ubi_bao_pk*: `.pk .lpk .cpk` - - *ubi_bao_atomic*: `.bao .(extensionless)` - - *ubi_bao_spk*: `.spk` - - *ubi_bao_header*: `(base) + .(external)` - - Codecs: UBI_IMA PCM16LE PSX NGC_DSP XMA ATRAC3 OGG_VORBIS +- **xnb.c** + - Microsoft XNA Game Studio 4.0 header [*XNB*] + - *xnb*: `.xnb + .(external)` + - Subfiles: *ogg_vorbis riff opus_std ffmpeg* + - Codecs: PCM8_U PCM16LE MSADPCM MS_IMA XMA2 NGC_DSP - **ubi_ckd.c** - Ubisoft CKD RIFF header [*UBI_CKD*] - *ubi_ckd*: `.ckd` - Codecs: NGC_DSP MSADPCM XMA -- **ubi_ckd_cwav.c** - - (container) - - *ubi_ckd_cwav*: `.wav .lwav` - - Subfiles: *bcwav* -- **ubi_hx.c** - - Ubisoft HXx header [*UBI_HX*] - - *ubi_hx*: `.hxd .hxc .hx2 .hxg .hxx .hx3 + .bnh .(external)` - - Codecs: PCM16BE PCM16LE UBI_ADPCM PSX NGC_DSP XBOX_IMA XMA2 ATRAC3 MPEG -- **ubi_jade.c** - - Ubisoft Jade RIFF header [*UBI_JADE*] - - *ubi_jade*: `.waa .wac .wad .wam .wav .lwav` - - Subfiles: *msf* - - *ubi_jade_container*: `.waa .wac .wad .wam .wav .lwav .xma` - - Subfiles: *xma ubi_jade* - - Codecs: XBOX_IMA PSX NGC_DSP MSADPCM -- **ubi_lyn.c** - - Ubisoft LyN RIFF header [*UBI_LYN*] - - *ubi_lyn*: `.sns .wav .lwav .son` - - Subfiles: *ogg_vorbis* - - *ubi_lyn_container*: `.sns .wav .lwav .son` - - Subfiles: *ubi_lyn* - - Codecs: PCM16LE NGC_DSP OGG_VORBIS MPEG MP4/AAC XMA -- **ubi_raki.c** - - Ubisoft RAKI header [*UBI_RAKI*] - - *ubi_raki*: `.rak .ckd` - - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 Opus -- **ubi_sb.c** - - Ubisoft SBx header [*UBI_SB*] - - *ubi_sb*: `.sb0 .sb1 .sb2 .sb3 .sb4 .sb5 .sb6 .sb7` - - *ubi_sm*: `.sm0 .sm1 .sm2 .sm3 .sm4 .sm5 .sm6 .sm7 .lm0 .lm1 .lm2 .lm3 .lm4 .lm5 .lm6 .lm7` - - *ubi_bnm*: `.bnm` - - *ubi_dat*: `.dat` - - *ubi_dat_main*: `(base) + .(external) .osb .kat` - - Subfiles: *kat riff* - - *ubi_bnm_ps2*: `.bnm` - - *ubi_blk*: `.blk + .(external)` - - *ubi_sb_audio*: `(base) + .(external)` - - *ubi_sb_layer*: `(base) + .(external)` - - *ubi_sb_sequence*: `(base) + .(external)` - - *ubi_sb_header*: `(base) + .(external) .kat` - - Codecs: PCM16LE AICA_int UBI_IMA UBI_SCE_IMA UBI_ADPCM PSX XBOX_IMA NGC_DSP ATRAC3 XMA OGG_VORBIS DVI_IMA_int -- **ue4opus.c** - - Epic Games UE4OPUS header [*UE4OPUS*] - - *ue4opus*: `.opus .lopus .ue4opus` - - Codecs: Opus -- **utk.c** - - Maxis UTK header [*UTK*] - - *utk*: `.utk` - - Codecs: EA_MT -- **vab.c** - - Sony VAB header [*VAB*] - - *vab*: `.vh .vab + .vb` - - Codecs: PSX -- **vag.c** - - Sony VAG header (custom) [*VAG_custom*] - - Sony VAG header [*VAG*] - - Acclaim Austin AAAp header [*AAAP*] - - *vag*: `.vag .swag .str .vig .l .r .vas .xa2 .snd` - - *vag_aaap*: `.vag` - - Codecs: PSX HEVAG -- **vai.c** - - Asobo Studio .VAI header [*VAI*] - - *vai*: `.vai` - - Codecs: NGC_DSP -- **vgs.c** - - Guitar Hero VGS Header [*VGS*] - - *vgs*: `.vgs` - - Codecs: PSX_badflags -- **vgs_ps.c** - - Princess Soft VGS header [*VGS_PS*] - - *vgs_ps*: `.vgs` - - Codecs: PSX -- **vid1.c** - - Factor 5 VID1 header [*VID1*] - - *vid1*: `.vid .ogg .logg` - - Codecs: PCM16_int XBOX_IMA NGC_DSP VORBIS_custom -- **vis.c** - - Konami VIS header [*VIS*] - - *vis*: `.vis` +- **ps2_vbk.c** + - PS2 VBK Header [*PS2_VBK*] + - *ps2_vbk*: `.vbk` - Codecs: PSX -- **voi.c** - - Irem .VOI header [*VOI*] - - *voi*: `.voi` +- **otm.c** + - Otomedius OTM Header [*OTM*] + - *otm*: `.otm` - Codecs: PCM16LE -- **vpk.c** - - SCE America VPK Header [*VPK*] - - *vpk*: `.vpk` - - Codecs: PSX -- **vs.c** - - Melbourne House .VS header [*VS*] - - *vs*: `.vs` - - Codecs: PSX -- **vsf.c** - - Square Enix VSF header [*VSF*] - - *vsf*: `.vsf` - - Codecs: PSX -- **vsf_tta.c** - - VSF with SMSS Header [*PS2_VSF_TTA*] - - *ps2_vsf_tta*: `.vsf` - - Codecs: PSX -- **vsv.c** - - Square Enix .vsv Header [*VSV*] - - *vsv*: `.vsv .psh` +- **bcstm.c** + - Nintendo CSTM Header [*CSTM*] + - *bcstm*: `.bcstm` + - Codecs: PCM8 PCM16LE NGC_DSP NW_IMA +- **g1l.c** + - Koei Tecmo WiiBGM Header [*KT_WIIBGM*] + - *kt_g1l*: `.g1l` + - *kt_wiibgm_offset*: `.g1l .dsp` + - Codecs: NGC_DSP_subint +- **bfstm.c** + - Nintendo FSTM Header [*FSTM*] + - *bfstm*: `.bfstm` + - Codecs: PCM8 PCM16BE PCM16LE NGC_DSP +- **mca.c** + - Capcom MCA header [*MCA*] + - *mca*: `.mca` + - Codecs: NGC_DSP +- **ktss.c** + - Koei Tecmo KTSS header [*KTSS*] + - *ktss*: `.kns .kno .ktss` + - Codecs: NGC_DSP Opus +- **hca.c** + - CRI HCA header [*HCA*] + - *hca* + - Subfiles: *hca_subkey* + - *hca_subkey*: `.hca` + - Codecs: CRI_HCA +- **svag_snk.c** + - SNK SVAG header [*SVAG_SNK*] + - *svag_snk*: `.svag` - Codecs: PSX -- **vs_square.c** - - Square VS header [*VS_SQUARE*] - - *vs_square*: `.vs` - - Codecs: PSX -- **vs_str.c** - - Square .VS STRx header [*VS_STR*] - - *vs_str*: `.vs .str` +- **ps2_vds_vdm.c** + - Procyon Studio VDS/VDM header [*PS2_VDS_VDM*] + - *ps2_vds_vdm*: `.vds .vdm` - Codecs: PSX +- **cxs.c** + - tri-Crescendo CXS header [*CXS*] + - *cxs*: `.cxs` + - Codecs: XMA2 +- **adx_monster.c** + - Monster Games .ADX header [*ADX_MONSTER*] + - *adx_monster*: `.adx` + - Codecs: NGC_DSP +- **akb.c** + - Square Enix AKB header [*AKB*] + - *akb*: `.akb` + - Subfiles: *ogg_vorbis_config* + - *akb2*: `.akb` + - Subfiles: *ogg_vorbis_config* + - Codecs: MSADPCM OGG FFmpeg(various) PCM16LE +- **mp4.c** + - MP4/AAC header [*MP4*] + - *mp4_aac_ffmpeg*: `.mp4 .m4a .m4v .lmp4 .bin .lbin .msd` + - Codecs: FFmpeg(various) +- **bik.c** + - RAD Game Tools Bink header [*BINK*] + - *bik*: `.bik .bik2 .bk2 .ps3 .xmv .xen .vid .bika` + - Codecs: FFmpeg(various) +- **astb.c** + - Capcom ASTB header [*ASTB*] + - *astb*: `.ast` + - Codecs: XMA +- **wwise.c** + - Audiokinetic Wwise RIFF header [*WWISE_RIFF*] + - *wwise* + - Subfiles: *wwise_bnk* + - *wwise_bnk*: `.wem .wav .lwav .ogg .logg .xma .bnk` + - Codecs: PCM16BE PCM16LE WWISE_IMA XBOX_IMA VORBIS_custom NGC_DSP XMA XWMA FFmpeg(various) Opus HEVAG ATRAC9 PTADPCM +- **ubi_raki.c** + - Ubisoft RAKI header [*UBI_RAKI*] + - *ubi_raki*: `.rak .ckd` + - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 Opus +- **pasx.c** + - Premium Agency PASX header [*PASX*] + - *pasx*: `.past .sgb` + - Codecs: XMA +- **xma.c** + - Microsoft XMA RIFF header [*XMA_RIFF*] + - *xma*: `.xma .xma2 .wav .lwav .nps .str .kmx` + - Codecs: XMA +- **sxd.c** + - Sony SXD header [*SXD*] + - *sxd*: `.sxd .sxd2 .sxd3 + .sxd1` + - Codecs: PSX HEVAG ATRAC9 +- **ogl.c** + - Shin'en OGL header [*OGL*] + - *ogl*: `.ogl` + - Codecs: VORBIS_custom +- **mc3.c** + - Paradigm MC3 header [*MC3*] + - *mc3*: `.mc3` + - Codecs: MC3 +- **ghs.c** + - Hexadrive GHS/S_P_STH header [*GHS*] + - *ghs*: `.gtd` + - *s_p_sth*: `.gtd` + - Subfiles: *msf* + - Codecs: XMA ATRAC9 +- **aac_triace.c** + - tri-Ace AAC header [*AAC_TRIACE*] + - *aac_triace*: `.aac .laac` + - Codecs: XMA2 ATRAC3 ATRAC9 MSADPCM ASKA OGG_VORBIS +- **ps2_va3.c** + - Konami VA3 header [*VA3*] + - *va3*: `.va3` + - Codecs: ATRAC3 +- **mta2.c** + - Konami MTA2 header [*MTA2*] + - *mta2*: `.mta2` + - *mta2_container*: `.dbm .bgm .mta2` + - Subfiles: *mta2* + - Codecs: MTA2 +- **xa_xa30.c** + - Reflections XA30 header [*XA_XA30*] + - *xa_xa30*: `.xa .xa30 .e4x` + - Codecs: PCM16LE REF_IMA +- **xa_04sw.c** + - Reflections 04SW header [*XA_04SW*] + - *xa_04sw*: `.xa` + - Codecs: NGC_DSP +- **ea_schl_fixed.c** + - Electronic Arts SCHl header (fixed) [*EA_SCHL_fixed*] + - *ea_schl_fixed*: `.asf .lasf .cnk` + - Codecs: PCM8 PCM16BE PCM16LE DVI_IMA PSX +- **sk_aud.c** + - Silicon Knights AUD header [*SK_AUD*] + - *sk_aud*: `.aud` + - Codecs: VORBIS_custom +- **stma.c** + - Angel Studios/Rockstar San Diego STMA header [*STMA*] + - *stma*: `.stm .lstm` + - Codecs: NGC_DSP DVI_IMA_int PCM16BE PCM16LE +- **ea_eaac.c** + - Electronic Arts SNR+SNS header [*EA_SNR_SNS*] + - Electronic Arts SPS header [*EA_SPS*] + - Electronic Arts SNU header [*EA_SNU*] + - *ea_snr_sns*: `.snr` + - *ea_sps*: `.sps` + - *ea_snu*: `.snu` + - *ea_abk_eaac*: `.abk + .ast` + - *ea_sbr*: `.sbr + .sbs` + - *ea_hdr_sth_dat*: `.hdr + .sth .dat .mus .(external)` + - *ea_mpf_mus_eaac*: `.mpf + .(external)` + - *ea_tmx*: `.tmx` + - Subfiles: *gin* + - *ea_sbr_harmony*: `.sbr + .sbs` + - *eaaudiocore_header*: `(base) + .sns` + - Codecs: PCM16_int EA_XAS_V1 MPEG NGC_DSP SPEEX ATRAC9 Opus XMA1 XMA2 +- **awc.c** + - Rockstar AWC header [*AWC*] + - *awc*: `.awc` + - Codecs: PCM16BE PCM16LE AWC_IMA XMA2 MPEG VORBIS_custom +- **opus.c** + - Nintendo Switch OPUS header [*OPUS*] + - *opus_std*: `.opus .lopus .bgm .opu + .psi` + - *opus_n1*: `.opus .lopus` + - *opus_capcom*: `.opus .lopus` + - *opus_nop*: `.nop` + - *opus_shinen*: `.opus .lopus` + - *opus_nus3*: `.opus .lopus` + - *opus_sps_n1*: `.sps .nlsd .at9 .opus .lopus` + - *opus_opusx*: `.opusx` + - *opus_prototype*: `.opus .lopus` + - *opus_opusnx*: `.opus .lopus` + - *opus_nsopus*: `.nsopus` + - *opus_sqex*: `.wav .lwav` + - *opus_rsnd*: `.rsnd` + - Codecs: Opus +- **nxa.c** + - Entergram NXA header [*NXA*] + - *opus_nxa*: `.nxa` + - Codecs: Opus +- **pc_ast.c** + - Capcom AST (PC) header [*PC_AST*] + - *pc_ast*: `.ast` + - Codecs: PCM16LE +- **naac.c** + - Namco NAAC header [*NAAC*] + - *naac*: `.naac` + - Codecs: AAC +- **ubi_sb.c** + - Ubisoft SBx header [*UBI_SB*] + - *ubi_sb*: `.sb0 .sb1 .sb2 .sb3 .sb4 .sb5 .sb6 .sb7` + - *ubi_sm*: `.sm0 .sm1 .sm2 .sm3 .sm4 .sm5 .sm6 .sm7 .lm0 .lm1 .lm2 .lm3 .lm4 .lm5 .lm6 .lm7` + - *ubi_bnm*: `.bnm` + - *ubi_dat*: `.dat` + - *ubi_dat_main*: `(base) + .(external) .osb .kat` + - Subfiles: *kat riff* + - *ubi_bnm_ps2*: `.bnm` + - *ubi_blk*: `.blk + .(external)` + - *ubi_sb_audio*: `(base) + .(external)` + - *ubi_sb_layer*: `(base) + .(external)` + - *ubi_sb_sequence*: `(base) + .(external)` + - *ubi_sb_header*: `(base) + .(external) .kat` + - Codecs: PCM16LE AICA_int UBI_IMA UBI_SCE_IMA UBI_ADPCM PSX XBOX_IMA NGC_DSP ATRAC3 XMA OGG_VORBIS DVI_IMA_int +- **ezw.c** + - EZ2DJ EZWAVE header [*EZW*] + - *ezw*: `.ezw` + - Codecs: PCM16LE - **vxn.c** - Gameloft VXN header [*VXN*] - *vxn*: `.vxn` - Codecs: PCM16LE MSADPCM MS_IMA FFmpeg(various) -- **wady.c** - - Marble WADY header [*WADY*] - - *wady*: `.way .(extensionless)` - - Codecs: WADY +- **vid1.c** + - Factor 5 VID1 header [*VID1*] + - *vid1*: `.vid .ogg .logg` + - Codecs: PCM16_int XBOX_IMA NGC_DSP VORBIS_custom +- **flx.c** + - Ultima IX .FLX header [*PC_FLX*] + - *flx*: `.flx` + - Codecs: PCM16LE EA_XA EA_XA_int EA_MT +- **mogg.c** + - Harmonix Music Systems MOGG Vorbis [*MOGG*] + - *mogg*: `.mogg` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **kma9.c** + - Koei Tecmo KMA9 header [*KMA9*] + - *kma9*: `.km9` + - Codecs: ATRAC9 +- **xwc.c** + - Starbreeze XWC header [*XWC*] + - *xwc*: `.xwc` + - Codecs: MPEG XMA2 OGG_VORBIS +- **atsl.c** + - (container) + - *atsl*: `.atsl .atsl3 .atsl4 .atslx` + - Subfiles: *ogg_vorbis riff xma ktac ktss* +- **sps_n1.c** + - Nippon Ichi .SPS header [*SPS_N1*] + - *sps_n1*: `.sps` + - Subfiles: *vag riff* + - *sps_n1_segmented*: `.at9 .nlsd` + - Subfiles: *ogg_vorbis opus_std* +- **atx.c** + - (container) + - *atx*: `.atx + .(external)` + - Subfiles: *riff* +- **sqex_sead.c** + - Square Enix SAB header [*SQEX_SAB*] + - Square Enix MAB header [*SQEX_MAB*] + - *sqex_sead*: `.sab .mab .sbin` + - Subfiles: *ogg_vorbis_config hca* + - Codecs: PCM16LE MSADPCM OGG ATRAC9 MPEG - **waf.c** - KID WAF header [*WAF*] - *waf*: `.waf` @@ -1703,232 +1220,715 @@ different internally (encrypted, different versions, etc) and not always can be - EngineBlack .WAVE header [*WAVE*] - *wave*: `.wave` - Codecs: IMA_int NGC_DSP -- **wavebatch.c** - - Firebrand Games WBAT header [*WAVEBATCH*] - - *wavebatch*: `.wavebatch` - - Codecs: PCM16BE PCM16LE PCM8 NGC_DSP - **wave_segmented.c** - EngineBlack .WAVE header [*WAVE*] - EngineBlack .WAVE header (segmented) [*WAVE_segmented*] - *wave_segmented*: `.wave` - Subfiles: *ogg_vorbis_config* - Codecs: IMA_int NGC_DSP OGG -- **wbk.c** - - Treyarch WBK header [*WBK*] - - Treyarch NSLB header [*WBK_NSLB*] - - *wbk*: `.wbk` - - *wbk_nslb*: `.wbk` - - Subfiles: *fsb* - - Codecs: NGC_DSP PSX XBOX_IMA IMA XMA -- **wii_bns.c** - - Nintendo BNS header [*WII_BNS*] - - *wii_bns*: `.bin .lbin .bns` - - Codecs: NGC_DSP -- **wii_mus.c** - - mus header [*DSP_WII_MUS*] - - *wii_mus*: `.mus` - - Codecs: NGC_DSP -- **wii_ras.c** - - RAS header [*WII_RAS*] - - *wii_ras*: `.ras` - - Codecs: NGC_DSP -- **wii_sng.c** - - SNG DSP Header [*WII_SNG*] - - *wii_sng*: `.sng` - - Codecs: NGC_DSP -- **wpd.c** - - WPD 'DPW' header [*WPD*] - - *wpd*: `.wpd` - - Codecs: PCM16LE -- **wsi.c** - - Alone in the Dark .WSI header [*DSP_WSI*] - - *wsi*: `.wsi` - - Codecs: NGC_DSP -- **ws_aud.c** - - Westwood Studios .AUD header [*WS_AUD*] - - *ws_aud*: `.aud` - - Codecs: WS IMA_int -- **wv2.c** - - Infogrames North America WAV2 header [*WV2*] - - *wv2*: `.wv2` - - Codecs: DVI_IMA_int -- **wv6.c** - - Gorilla Systems WV6 header [*WV6*] - - *wv6*: `.wv6` - - Codecs: WV6_IMA -- **wvs.c** - - Swingin' Ape .WVS header [*WVS*] - - *wvs_xbox*: `.wvs` - - *wvs_ngc*: `.wvs` - - Codecs: XBOX_IMA NGC_DSP -- **wwise.c** - - Audiokinetic Wwise RIFF header [*WWISE_RIFF*] - - *wwise* - - Subfiles: *wwise_bnk* - - *wwise_bnk*: `.wem .wav .lwav .ogg .logg .xma .bnk` - - Codecs: PCM16BE PCM16LE WWISE_IMA XBOX_IMA VORBIS_custom NGC_DSP XMA XWMA FFmpeg(various) Opus HEVAG ATRAC9 PTADPCM -- **wxd_wxh.c** - - Relic WXD+WXH header [*WXD_WXH*] - - *wxd_wxh*: `.wxd + .wxh` - - Codecs: RELIC -- **xa.c** - - Sony XA header [*XA*] - - *xa*: `.xa .str .pxa .grn .an2 .(extensionless)` - - Codecs: XA8 XA -- **xa2_acclaim.c** - - Acclaim .XA2 Header [*XA2_ACCLAIM*] - - *xa2_acclaim*: `.xa2` +- **smv.c** + - extreme .SMV header [*SMV*] + - *smv*: `.smv` - Codecs: PSX -- **xau.c** - - XPEC XAU header [*XAU*] - - *xau*: `.xau` - - Codecs: PSX XBOX_IMA -- **xau_konami.c** - - Konami XAU header [*XAU_KONAMI*] - - *xau_konami*: `.xau` - - Codecs: PCM16LE -- **xavs.c** - - Reflections XAVS header [*XAVS*] - - *xavs*: `.xav` - - Codecs: PCM16LE -- **xa_04sw.c** - - Reflections 04SW header [*XA_04SW*] - - *xa_04sw*: `.xa` +- **nxap.c** + - Nex NXAP header [*NXAP*] + - *nxap*: `.adp` + - Codecs: NXAP +- **ea_wve_au00.c** + - Electronic Arts WVE (au00) header [*EA_WVE_AU00*] + - *ea_wve_au00*: `.wve .fsv` + - Codecs: EA_XA_int PSX_cfg +- **ea_wve_ad10.c** + - Electronic Arts WVE (Ad10) header [*EA_WVE_AD10*] + - *ea_wve_ad10*: `.wve .mov` + - Codecs: PSX PCM8_U_int +- **sthd.c** + - Dream Factory STHD header [*STHD*] + - *sthd*: `.stx` + - Codecs: XBOX_IMA_int +- **pcm_sre.c** + - Capcom .PCM+SRE header [*PCM_SRE*] + - *pcm_sre*: `.pcm + .sre` + - Codecs: PSX +- **ubi_lyn.c** + - Ubisoft LyN RIFF header [*UBI_LYN*] + - *ubi_lyn*: `.sns .wav .lwav .son` + - Subfiles: *ogg_vorbis* + - *ubi_lyn_container*: `.sns .wav .lwav .son` + - Subfiles: *ubi_lyn* + - Codecs: PCM16LE NGC_DSP OGG_VORBIS MPEG MP4/AAC XMA +- **msb_msh.c** + - Sony MultiStream MSH+MSB header [*MSB_MSH*] + - *msb_msh*: `.msb + .msh` + - Codecs: PSX +- **smc_smh.c** + - Genki SMC+SMH header [*SMC_SMH*] + - *smc_smh*: `.smc + .smh` + - Codecs: PSX +- **ppst.c** + - Parappa PPST header [*PPST*] + - *ppst*: `.sng` + - Subfiles: *riff* +- **ubi_bao.c** + - Ubisoft BAO header [*UBI_BAO*] + - *ubi_bao_pk*: `.pk .lpk .cpk` + - *ubi_bao_atomic*: `.bao .(extensionless)` + - *ubi_bao_spk*: `.spk` + - *ubi_bao_header*: `(base) + .(external)` + - Codecs: UBI_IMA PCM16LE PSX NGC_DSP XMA ATRAC3 OGG_VORBIS +- **sadf.c** + - Procyon Studio SADF header [*SADF*] + - *sadf*: `.sad .nop .(extensionless)` - Codecs: NGC_DSP -- **xa_xa30.c** - - Reflections XA30 header [*XA_XA30*] - - *xa_xa30*: `.xa .xa30 .e4x` - - Codecs: PCM16LE REF_IMA -- **xbox_ims.c** - - assumed Matrix file by .matx extension [*XBOX_MATX*] - - *xbox_matx*: `.matx` - - Codecs: XBOX_IMA -- **xma.c** - - Microsoft XMA RIFF header [*XMA_RIFF*] - - *xma*: `.xma .xma2 .wav .lwav .nps .str .kmx` - - Codecs: XMA -- **xma_ue3.c** - - Unreal Engine XMA header [*XMA_UE3*] - - *xma_ue3*: `.xma .x360audio .(extensionless)` - - Codecs: XMA +- **h4m.c** + - Hudson HVQM4 header [*H4M*] + - *h4m*: `.h4m .hvqm` + - Codecs: H4M_IMA +- **asf.c** + - Argonaut ASF header [*ASF*] + - *asf*: `.asf .lasf` + - Codecs: ASF - **xmd.c** - Konami XMD header [*XMD*] - *xmd*: `.xmd` - Codecs: XMD -- **xmu.c** - - Outrage XMU header [*XMU*] - - *xmu*: `.xmu` +- **ck.c** + - Cricket Audio CKS header [*CKS*] + - Cricket Audio CKB header [*CKB*] + - *cks*: `.cks` + - *ckb*: `.ckb` + - Codecs: PCM16LE PCM8 MSADPCM_ck +- **wv6.c** + - Gorilla Systems WV6 header [*WV6*] + - *wv6*: `.wv6` + - Codecs: WV6_IMA +- **str_wav.c** + - Blitz Games .STR+WAV header [*STR_WAV*] + - *str_wav*: `.str .data .wav .wma .(extensionless) + .(external) .wav .sth` + - Codecs: PSX NGC_DSP XBOX_IMA BLITZ_IMA FFmpeg(various) XMA2 +- **wavebatch.c** + - Firebrand Games WBAT header [*WAVEBATCH*] + - *wavebatch*: `.wavebatch` + - Codecs: PCM16BE PCM16LE PCM8 NGC_DSP +- **hd3_bd3.c** + - Sony HD3+BD3 header [*HD3_BD3*] + - *hd3_bd3*: `.hd3 + .bd3` + - Codecs: PSX +- **bnk_sony.c** + - Sony BNK header [*BNK_SONY*] + - *bnk_sony*: `.bnk` + - Codecs: ATRAC9 PCM16BE PCM16LE PSX HEVAG +- **nus3bank.c** + - (container) + - *nus3bank*: `.nub2 .nus3bank` + - Subfiles: *idsp_namco opus_nus3 riff bnsf ivag xma nus3bank_encrypted* + - *nus3bank_encrypted*: `.nus3bank .xma` + - Subfiles: *xma* +- **sscf.c** + - Square Enix SSCF header [*SSCF*] + - *sscf*: `.scd` + - Codecs: PSX +- **a2m.c** + - Artificial Mind & Movement A2M header [*A2M*] + - *a2m*: `.int` + - Codecs: PSX +- **ahv.c** + - Amuze AHV header [*AHV*] + - *ahv*: `.ahv` + - Codecs: PSX +- **msv.c** + - Sony MultiStream MSV header [*MSV*] + - *msv*: `.msv .msvp` + - Codecs: PSX +- **sdf.c** + - Beyond Reality SDF header [*SDF*] + - *sdf*: `.sdf` + - Codecs: PCM16LE PSX NGC_DSP +- **svg.c** + - High Voltage SVG header [*SVG*] + - *svg*: `.svg` + - Codecs: PSX +- **vis.c** + - Konami VIS header [*VIS*] + - *vis*: `.vis` + - Codecs: PSX +- **vai.c** + - Asobo Studio .VAI header [*VAI*] + - *vai*: `.vai` + - Codecs: NGC_DSP +- **aif_asobo.c** + - Asobo Studio .AIF header [*AIF_ASOBO*] + - *aif_asobo*: `.aif .laif` - Codecs: XBOX_IMA -- **xnb.c** - - Microsoft XNA Game Studio 4.0 header [*XNB*] - - *xnb*: `.xnb + .(external)` - - Subfiles: *ogg_vorbis riff opus_std ffmpeg* - - Codecs: PCM8_U PCM16LE MSADPCM MS_IMA XMA2 NGC_DSP +- **ao.c** + - AlphaOgg .AO header [*AO*] + - *ao*: `.ao` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **apc.c** + - Cryo APC header [*APC*] + - *apc*: `.apc` + - Codecs: IMA +- **wv2.c** + - Infogrames North America WAV2 header [*WV2*] + - *wv2*: `.wv2` + - Codecs: DVI_IMA_int +- **xau_konami.c** + - Konami XAU header [*XAU_KONAMI*] + - *xau_konami*: `.xau` + - Codecs: PCM16LE +- **derf.c** + - Xilam DERF header [*DERF*] + - *derf*: `.adp` + - Codecs: DERF +- **utk.c** + - Maxis UTK header [*UTK*] + - *utk*: `.utk` + - Codecs: EA_MT +- **adpcm_capcom.c** + - Capcom .ADPCM header [*ADPCM_CAPCOM*] + - *adpcm_capcom*: `.adpcm .mca` + - Codecs: NGC_DSP +- **ue4opus.c** + - Epic Games UE4OPUS header [*UE4OPUS*] + - *ue4opus*: `.opus .lopus .ue4opus` + - Codecs: Opus +- **xwma.c** + - Microsoft XWMA RIFF header [*XWMA*] + - *xwma*: `.xwma .xwm .xma .wma .lwma` + - Codecs: XWMA - **xopus.c** - Exient XOPUS header [*XOPUS*] - *xopus*: `.xopus` - Codecs: Opus +- **vs_square.c** + - Square VS header [*VS_SQUARE*] + - *vs_square*: `.vs` + - Codecs: PSX +- **msf_banpresto.c** + - (container) + - *msf_banpresto_wmsf*: `.msf` + - Subfiles: *msf* + - *msf_banpresto_2msf*: `.at9` + - Subfiles: *riff* +- **nwav.c** + - Chunsoft NWAV header [*NWAV*] + - *nwav*: `.nwav .(extensionless)` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG - **xpcm.c** - Circus XPCM header [*XPCM*] - *xpcm*: `.pcm` - Codecs: PCM16LE CIRCUS_ADPCM CIRCUS_VQ +- **msf_tamasoft.c** + - Tama-Soft MSF header [*MSF_TAMASOFT*] + - *msf_tamasoft*: `.msf` + - Codecs: PCM16LE - **xps.c** - From Software .XPS+DAT header [*XPS_DAT*] - *xps_dat*: `.xps + .dat` - *xps*: `.xps + .dat` - Subfiles: *riff* - Codecs: PCM16LE XBOX_IMA -- **xsh_xsd_xss.c** - - Treyarch XSH+XSD/XSS header [*XSH_XSD_XSS*] - - *xsh_xsd_xss*: `.xsh + .(external) .xsd` - - Subfiles: *riff* - - Codecs: XBOX_IMA -- **xss.c** - - Dino Crisis 3 XSS File [*XSS*] - - *xss*: `.xss` - - Codecs: PCM16LE -- **xssb.c** - - Artoon XSSB header [*XSSB*] - - *xssb*: `.bin .lbin` - - Codecs: PCM16LE XBOX_IMA -- **xvag.c** - - Sony XVAG header [*XVAG*] - - *xvag*: `.xvag .(extensionless)` - - Codecs: PSX MPEG ATRAC9 -- **xvas.c** - - Konami .XVAS header [*XVAS*] - - *xvas*: `.xvas` - - Codecs: XBOX_IMA -- **xwav.c** - - feelplus XWAV header [*XWAV*] - - *xwav_new*: `.xwv .vawx` - - *xwav_old*: `.xwv` - - Codecs: PSX XMA2 ATRAC3 -- **xwb.c** - - Microsoft XWB header [*XWB*] - - *xwb*: `.xwb .xna .hwb .bd .(extensionless) + .wbh` - - Subfiles: *riff* - - Codecs: PCM8_U PCM16LE PCM16BE XBOX_IMA MSADPCM XMA1 XMA2 FFmpeg(various) XWMA ATRAC3 OGG_VORBIS NGC_DSP -- **xwc.c** - - Starbreeze XWC header [*XWC*] - - *xwc*: `.xwc` - - Codecs: MPEG XMA2 OGG_VORBIS -- **xwma.c** - - Microsoft XWMA RIFF header [*XWMA*] - - *xwma*: `.xwma .xwm .xma .wma .lwma` - - Codecs: XWMA -- **xwma_konami.c** - - Konami XWMA header [*XWMA_KONAMI*] - - *xwma_konami*: `.xwma` - - Codecs: XWMA -- **xwv_valve.c** - - Half-Life 2 .WAV header [*XBOX_HLWAV*] - - Valve XWV header [*XWV_VALVE*] - - *xbox_hlwav*: `.wav .lwav` - - *xwv_valve*: `.wav .lwav` - - Codecs: PCM16LE XBOX_IMA PCM16BE XMA2 -- **ydsp.c** - - Yuke's YDSP Header [*YDSP*] - - *ydsp*: `.ydsp` - - Codecs: NGC_DSP -- **ymf.c** - - Yuke's .YMF Header [*YMF*] - - *ymf*: `.ymf` - - Codecs: NGC_DSP -- **zsd.c** - - Konami ZSD header [*ZSD*] - - *zsd*: `.zsd` - - Codecs: PCM8 - **zsnd.c** - Z-Axis ZSND header [*ZSND*] - *zsnd*: `.zss .zsm .ens .enm .zsd` - Codecs: IMA XBOX_IMA PSX NGC_DSP +- **ogg_opus.c** + - Ogg Opus header [*OGG_OPUS*] + - *ogg_opus*: `.opus .lopus .ogg .logg .bgm` + - Codecs: FFmpeg(various) +- **nus3audio.c** + - (container) + - *nus3audio*: `.nus3audio` + - Subfiles: *idsp_namco opus_nus3 riff bnsf* +- **imc.c** + - iNiS .IMC header [*IMC*] + - *imc*: `.imc` + - *imc_container*: `.imc` + - Subfiles: *imc* + - Codecs: PSX +- **smp.c** + - Infernal Engine .smp header [*SMP*] + - *smp*: `.smp .snb` + - Codecs: ATRAC3 NGC_DSP MSADPCM PSX XMA2 +- **gin.c** + - Electronic Arts Gnsu header [*GIN*] + - *gin*: `.gin` + - Codecs: EA_XAS_V0 +- **dsf.c** + - Ocean DSF header [*DSF*] + - *dsf*: `.dsf` + - Codecs: DSA +- **208.c** + - Ocean .208 header [*208*] + - *208*: `.208` + - Codecs: PCM8_U +- **ffdl.c** + - (container) + - *ffdl*: `.ogg .logg .mp4 .lmp4 .bin .(extensionless)` + - Subfiles: *ogg_vorbis mp4_aac_ffmpeg* +- **mus_vc.c** + - Vicious Cycle .MUS header [*MUS_VC*] + - *mus_vc*: `.mus` + - Codecs: NGC_DSP XBOX_IMA +- **strm_abylight.c** + - Abylight STRM header [*STRM_ABYLIGHT*] + - *strm_abylight*: `.strm` + - Codecs: AAC +- **sfh.c** + - (container) + - *sfh*: `.at3 .sspr` + - Subfiles: *riff sspr* +- **msf_konami.c** + - Konami MSF header [*MSF_KONAMI*] + - *msf_konami*: `.msf` + - Codecs: PSX +- **xwma_konami.c** + - Konami XWMA header [*XWMA_KONAMI*] + - *xwma_konami*: `.xwma` + - Codecs: XWMA +- **9tav.c** + - Konami 9TAV header [*9TAV*] + - *9tav*: `.9tav` + - Codecs: ATRAC9 +- **fsb5_fev.c** + - (container) + - *fsb5_fev_bank*: `.bank` + - Subfiles: *fsb5 fsb_encrypted* +- **bwav.c** + - Nintendo BWAV header [*BWAV*] + - *bwav*: `.bwav` + - Subfiles: *opus_std* + - Codecs: PCM16LE NGC_DSP +- **awb.c** + - (container) + - *awb* + - Subfiles: *awb_memory* + - *awb_memory*: `.awb .afs2 + .acb .(external)` + - Subfiles: *adx_subkey hca_subkey vag riff bcwav ngc_dsp_std dsp_cwac mp4_aac_ffmpeg* +- **acb.c** + - (container) + - *acb*: `.acb` + - Subfiles: *cpk_memory awb_memory* +- **rad.c** + - Traveller's Tales .RAD header [*RAD*] + - *rad*: `.rad` + - Codecs: PCM16LE +- **smk.c** + - RAD Game Tools SMACKER header [*SMACKER*] + - *smk*: `.smk` + - Codecs: FFmpeg(various) +- **idtech.c** + - id Software MZRT header [*MZRT*] + - id Software BSNF header [*BSNF*] + - *mzrt_v0*: `.idwav .idmsf .idxma` + - *mzrt_v1*: `.idmsf` + - *bsnf*: `.bsnd + .(external)` + - Codecs: PCM16LE MSADPCM XMA MPEG XMA2 OGG_VORBIS ATRAC9 +- **xavs.c** + - Reflections XAVS header [*XAVS*] + - *xavs*: `.xav` + - Codecs: PCM16LE +- **psf.c** + - Pivotal PSF header [*PSF*] + - *psf_single*: `.psf .swd` + - *psf_segmented*: `.psf .swd` + - Subfiles: *psf_single* + - *psf_pfsm*: `.psf` + - *sch*: `.sch + .(external)` + - Subfiles: *psf_segmented psf_single* + - Codecs: PSX PSX_pivotal NGC_DSP PCM16BE +- **ima.c** + - Blitz Games .IMA header [*IMA*] + - *ima*: `.ima` + - Codecs: BLITZ_IMA +- **nub.c** + - Namco NUB header [*NUB*] + - *nub*: `.nub .nub2 + .(external)` + - Subfiles: *nub_xma nub_wav nub_vag nub_at3 nub_dsp nub_idsp nub_is14 function* + - *nub_wav*: `.wav .lwav` + - *nub_vag*: `.vag` + - *nub_at3*: `.at3` + - Subfiles: *riff* + - *nub_xma*: `.xma` + - *nub_dsp*: `.dsp` + - Subfiles: *ngc_dsp_std* + - *nub_idsp*: `.idsp` + - Subfiles: *idsp_namco* + - *nub_is14*: `.is14` + - Subfiles: *bnsf* + - Codecs: PCM16BE PSX XMA +- **ubi_hx.c** + - Ubisoft HXx header [*UBI_HX*] + - *ubi_hx*: `.hxd .hxc .hx2 .hxg .hxx .hx3 + .bnh .(external)` + - Codecs: PCM16BE PCM16LE UBI_ADPCM PSX NGC_DSP XBOX_IMA XMA2 ATRAC3 MPEG +- **bmp_konami.c** + - Konami BMP header [*BMP_KONAMI*] + - *bmp_konami*: `.bin .lbin` + - Codecs: OKI4S +- **isb.c** + - Creative ISACT header [*ISB*] + - *isb*: `.isb` + - Subfiles: *msf* + - Codecs: PCM8_U PCM16LE XBOX_IMA OGG_VORBIS XMA +- **xssb.c** + - Artoon XSSB header [*XSSB*] + - *xssb*: `.bin .lbin` + - Codecs: PCM16LE XBOX_IMA +- **xma_ue3.c** + - Unreal Engine XMA header [*XMA_UE3*] + - *xma_ue3*: `.xma .x360audio .(extensionless)` + - Codecs: XMA +- **fwse.c** + - MT Framework FWSE header [*FWSE*] + - *fwse*: `.fwse` + - Codecs: MTF_IMA +- **fda.c** + - Relic FDA header [*FDA*] + - *fda*: `.fda` + - Codecs: RELIC +- **kwb.c** + - Koei Tecmo WaveBank header [*KWB*] + - *kwb*: `.wbd .wb2 .sed + .wbh .whd .wh2` + - *xws*: `.xws` + - *koei_wavebank* + - Subfiles: *msf dsp_apex* + - Codecs: PCM16LE MSADPCM NGC_DSP XMA2 ATRAC9 +- **lrmd.c** + - Sony LRMD header [*LRMD*] + - *lrmd*: `.lrmh + .lrmb` + - Codecs: ATRAC3 +- **bkhd.c** + - Audiokinetic Wwise FX header [*WWISE_FX*] + - *bkhd*: `.bnk` + - Subfiles: *wwise_bnk bkhd_fx* + - *bkhd_fx*: `.wem .bnk` + - Codecs: PCMFLOAT +- **diva.c** + - Sega DIVA header [*DIVA*] + - *diva*: `.diva` + - Codecs: DVI_IMA +- **imuse.c** + - LucasArts iMUSE header [*IMUSE*] + - *imuse*: `.imx .imc .wav .lwav` + - Codecs: IMUSE +- **ktsr.c** + - Koei Tecmo KTSR header [*KTSR*] + - *ktsr*: `.ktsl2asbin .asbin` + - Subfiles: *riff ogg_vorbis ktss* + - Codecs: MSADPCM_int NGC_DSP ATRAC9 +- **mups.c** + - (container) + - *mups*: `.mups .(extensionless)` + - Subfiles: *ogg_vorbis* +- **kat.c** + - Sega KAT header [*KAT*] + - *kat*: `.kat` + - Codecs: AICA_int PCM8 PCM16LE +- **pcm_success.c** + - Success PCM header [*PCM_SUCCESS*] + - *pcm_success*: `.pcm` + - Codecs: PSX +- **ktsc.c** + - (container) + - *ktsc*: `.ktsl2asbin .asbin` + - Subfiles: *ktsr* +- **adp_konami.c** + - Konami ADP header [*ADP_KONAMI*] + - *adp_konami*: `.adp` + - Codecs: OKI4S - **zwv.c** - (container) - *zwv*: `.zwv` - Subfiles: *msf* +- **dsb.c** + - (container) + - *dsb*: `.dsb` + - Subfiles: *bnsf* +- **bsf.c** + - (container) + - *bsf*: `.bsf` + - Subfiles: *ngc_dsp_std vag riff* +- **sdrh.c** + - feelplus SDRH header [*SDRH*] + - *sdrh_new*: `.xse` + - *sdrh_old*: `.xse` + - Codecs: PSX MPEG XMA2 ATRAC3 XMA1 +- **wady.c** + - Marble WADY header [*WADY*] + - *wady*: `.way .(extensionless)` + - Codecs: WADY +- **cpk.c** + - (container) + - *cpk* + - Subfiles: *cpk_memory* + - *cpk_memory*: `.awb + .acb` + - Subfiles: *hca bcwav adx* +- **sbk.c** + - Team17 SBK header [*SBK*] + - *sbk*: `.sbk` + - Codecs: PCM8_U PCM16LE MS_IMA +- **ifs.c** + - (container) + - *ifs*: `.ifs` + - Subfiles: *bmp_konami* +- **acx.c** + - (container) + - *acx*: `.acx` + - Subfiles: *adx* +- **compresswave.c** + - CompressWave .cwav header [*COMPRESSWAVE*] + - *compresswave*: `.cwav` + - Codecs: COMPRESSWAVE +- **ktac.c** + - Koei Tecmo KTAC header [*KTAC*] + - *ktac*: `.ktac` + - Codecs: MP4/AAC +- **tac.c** + - tri-Ace Codec header [*TAC*] + - *tac*: `.(extensionless) .aac .laac` + - Codecs: TAC +- **ogv_3rdeye.c** + - 3rdEye .OGV header [*OGV_3RDEYE*] + - *ogv_3rdeye*: `.ogv` + - Subfiles: *ogg_vorbis_config* + - Codecs: OGG +- **sspr.c** + - (container) + - *sspr*: `.sspr` + - Subfiles: *riff* +- **piff_tpcm.c** + - Tantalus PIFF TPCM header [*PIFF_TPCM*] + - *piff_tpcm*: `.tad` + - Codecs: TANTALUS +- **wxd_wxh.c** + - Relic WXD+WXH header [*WXD_WXH*] + - *wxd_wxh*: `.wxd + .wxh` + - Codecs: RELIC +- **bnk_relic.c** + - Relic BNK header [*BNK_RELIC*] + - *bnk_relic*: `.bnk` + - Codecs: RELIC +- **xsh_xsd_xss.c** + - Treyarch XSH+XSD/XSS header [*XSH_XSD_XSS*] + - *xsh_xsd_xss*: `.xsh + .(external) .xsd` + - Subfiles: *riff* + - Codecs: XBOX_IMA +- **psb.c** + - M2 PSB header [*PSB*] + - *psb*: `.psb` + - Subfiles: *riff vag* + - Codecs: PCM16LE PCM24LE MSADPCM XWMA XMA NGC_DSP Opus +- **lopu_fb.c** + - French-Bread LOPU header [*LOPU_FB*] + - *lopu_fb*: `.lopus` + - Codecs: Opus +- **lpcm_fb.c** + - French-Bread LPCM header [*LPCM_FB*] + - *lpcm_fb*: `.ladpcm` + - Codecs: NGC_DSP +- **wbk.c** + - Treyarch WBK header [*WBK*] + - Treyarch NSLB header [*WBK_NSLB*] + - *wbk*: `.wbk` + - *wbk_nslb*: `.wbk` + - Subfiles: *fsb* + - Codecs: NGC_DSP PSX XBOX_IMA IMA XMA +- **ubi_ckd_cwav.c** + - (container) + - *ubi_ckd_cwav*: `.wav .lwav` + - Subfiles: *bcwav* +- **sspf.c** + - Konami SSPF header [*SSPF*] + - *sspf*: `.ssp` + - Codecs: PCM16BE MTA2 +- **s3v.c** + - Konami S3V header [*S3V*] + - *s3v*: `.s3v` + - Codecs: FFmpeg(various) +- **esf.c** + - Eurocom ESF header [*ESF*] + - *esf*: `.esf` + - Codecs: DVI_IMA PCM8_U PCM16LE +- **adm3.c** + - Crankcase ADM3 header [*ADM3*] + - *adm3*: `.wem` + - Codecs: APPLE_IMA4 +- **tt_ad.c** + - Traveller's Tales AUDIO_DATA header [*TT_AD*] + - *tt_ad*: `.audio_data` + - Codecs: OGG_VORBIS MS_IMA_mono +- **bw_mp3_riff.c** + - (container) + - *bw_mp3_riff* + - Subfiles: *riff* + - *bw_riff_mp3* + - Subfiles: *mpeg* +- **sndz.c** + - Sony SNDZ header [*SNDZ*] + - *sndz*: `.szd1 .szd .szd3 + .szd2` + - Codecs: PCM16LE PCM24LE PCMFLOAT HEVAG ATRAC9 +- **vab.c** + - Sony VAB header [*VAB*] + - *vab*: `.vh .vab + .vb` + - Codecs: PSX +- **bigrp.c** + - Inti Creates .BIGRP header [*BIGRP*] + - *bigrp*: `.bigrp` + - Codecs: ICE_RANGE ICE_DCT +- **sscf_encrypted.c** + - (container) + - *sscf_encrypted*: `.scd` + - Subfiles: *xma* +- **ego_dic.c** + - Codemasters DIC1 header [*DIC1*] + - *ego_dic*: `.dic + .(external)` + - Codecs: PCM16LE ULAW XBOX_IMA OGG_VORBIS +- **awd.c** + - RenderWare Audio Wave Dictionary header [*AWD*] + - *awd*: `.awd .hwd .lwd` + - Codecs: PSX PCM16LE NGC_DSP XBOX_IMA +- **rws_809.c** + - RenderWare RWS header [*RWS*] + - *rws_809*: `.rws` + - Codecs: PCM16BE PCM16LE PSX NGC_DSP +- **pwb.c** + - Double Fine WB header [*PWB*] + - *pwb*: `.pwb` + - Codecs: PSX +- **scd_pcm.c** + - Lunar: Eternal Blue .PCM header [*SCD_PCM*] + - *scd_pcm*: `.pcm` + - Codecs: PCM8_SB +- **agsc.c** + - Retro Studios AGSC header [*AGSC*] + - *agsc*: `.agsc` + - Codecs: NGC_DSP +- **ps2_wmus.c** + - assumed The Warriors Sony ADPCM by .wmus extension [*PS2_WMUS*] + - *ps2_wmus*: `.wmus` + - Codecs: PSX +- **mib_mih.c** + - Sony MultiStream MIH+MIB header [*MIB_MIH*] + - *mib_mih*: `.mib + .mih` + - Codecs: PSX +- **mjb_mjh.c** + - Sony MultiStream MJH+MJB header [*MJB_MJH*] + - *mjb_mjh*: `.mjb + .mjh .mjb` + - Codecs: PSX +- **ps2_mic.c** + - KOEI .MIC header [*PS2_MIC*] + - *mic_koei*: `.mic` + - Codecs: PSX +- **seb.c** + - Game Arts .SEB header [*SEB*] + - *seb*: `.seb .gms .(extensionless)` + - Codecs: PSX +- **tgc.c** + - Tiger Game.com .4 header [*TGC*] + - *tgc*: `.4` + - Codecs: TGC +- **pos.c** + - RIFF WAVE header and .pos for looping [*RIFF_WAVE_POS*] + - *pos*: `.pos + .wav` + - Subfiles: *riff* +- **sli.c** + - (container) + - *sli_loops*: `.sli + .(external)` + - Subfiles: *ogg_opus ogg_vorbis riff* +- **ngc_adpdtk.c** + - Nintendo DTK raw header [*DTK*] + - *dtk*: `.dtk .adp .trk .wav .lwav` + - Codecs: NGC_DTK +- **mpeg.c** + - MPEG header [*MPEG*] + - *mpeg*: `.mp3 .mp2 .lmp3 .lmp2 .mus .imf .aix .(extensionless)` + - Codecs: MPEG +- **btsnd.c** + - Nintendo Wii U Menu Boot Sound [*WIIU_BTSND*] + - *btsnd*: `.btsnd` + - Codecs: PCM16BE +- **fsb_encrypted.c** + - (container) + - *fsb_encrypted*: `.fsb .ps3 .xen` + - Subfiles: *fsb fsb5* +- **encrypted.c** + - (container) + - *encrypted_ogg_tpf*: `.ogg .logg` + - Subfiles: *ogg_vorbis* + - *encrypted_mp3_tpf*: `.mp3` + - Subfiles: *ffmpeg* + - *encrypted_riff*: `.bgm .mse .koe` + - Subfiles: *riff* + - *encrypted_rpgmvo_riff*: `.rpgmvo` + - Subfiles: *riff* + - *encrypted_mc161*: `.mus` + - Subfiles: *ogg_vorbis* +- **raw_rsf.c** + - Retro Studios .RSF raw header [*RSF*] + - *raw_rsf*: `.rsf` + - Codecs: G721 +- **raw_int.c** + - PS2 .int raw header [*RAW_INT*] + - *raw_int*: `.int .wp2` + - Codecs: PCM16LE +- **raw_snds.c** + - PC .snds raw header [*RAW_SNDS*] + - *raw_snds*: `.snds` + - Codecs: SNDS_IMA +- **raw_wavm.c** + - Xbox .wavm raw header [*RAW_WAVM*] + - *raw_wavm*: `.wavm` + - Codecs: XBOX_IMA +- **raw_pcm.c** + - PC .raw raw header [*RAW_PCM*] + - *raw_pcm*: `.raw` + - Codecs: PCM16LE +- **raw_s14_sss.c** + - Namco .S14 raw header [*S14*] + - Namco .SSS raw header [*SSS*] + - *raw_s14_sss*: `.sss .s14` + - Codecs: G7221C +- **exakt_sc.c** + - assumed Activision / EXAKT SC by extension [*EXAKT_SC*] + - *exakt_sc*: `.sc` + - Codecs: SASSC +- **ps2_adm.c** + - Dragon Quest V .ADM raw header [*PS2_ADM*] + - *ps2_adm*: `.adm + .(external)` + - Codecs: PSX +- **rwsd.c** + - Nintendo RWSD header (single stream) [*RWSD*] + - *rwsd*: `.brwsd .rwsd` + - Codecs: PCM8 PCM16BE NGC_DSP +- **ffmpeg.c** + - FFmpeg supported format (check log) [*FFMPEG_faulty*] + - FFmpeg supported format [*FFMPEG*] + - *ffmpeg*: `.(any) .at3` + - Codecs: FFmpeg(various) ## Supported extras Reminder of some extra formats and helper files vgmstream supports. They are described in detail in USAGE.md. - artificial headers: - - .txth (text header, adds support to lots of extra formats) - - .genh (generic header, deprecated) +- .txth (text header, adds support to lots of extra formats) +- .genh (generic header, deprecated) - loop assists: - - .txtm (text map config, for formats that open companion files manually) - - .txtp (text play config, per song segment/layer manipulation) +- .txtm (text map config, for formats that open companion files manually) +- .txtp (text play config, per song segment/layer manipulation) - loop assists: - - .mus (playlist for .acm) - - .pos (loop info for .wav) - - .sli (loop info for .ogg) - - .sfl (loop info for .ogg) +- .mus (playlist for .acm) +- .pos (loop info for .wav) +- .sli (loop info for .ogg) +- .sfl (loop info for .ogg) - other: - - .adxkey (decryption key for .adx) - - .ahxkey (decryption key for .ahx) - - .hcakey (decryption key for .hca) - - .fsbkey (decryption key for .fsb) - - .bnsfkey (decryption key for .bnsf) +- .adxkey (decryption key for .adx) +- .ahxkey (decryption key for .ahx) +- .hcakey (decryption key for .hca) +- .fsbkey (decryption key for .fsb) +- .bnsfkey (decryption key for .bnsf) ## Supported codecs @@ -1936,84 +1936,84 @@ Quick list of most codecs vgmstream supports, including many obscure ones that are used in few games. - PCM - - PCM 16-bit (little endian, big endian) - - PCM 8-bit (signed, unsigned, sign bit) - - PCM 4-bit (signed, unsigned) - - PCM 24-bit (little endian, big endian) - - PCM 32-bit float - - u-Law/a-LAW +- PCM 16-bit (little endian, big endian) +- PCM 8-bit (signed, unsigned, sign bit) +- PCM 4-bit (signed, unsigned) +- PCM 24-bit (little endian, big endian) +- PCM 32-bit float +- u-Law/a-LAW - ADPCM (BRR/XA-style) - - CD-ROM XA ADPCM - - Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended) - - CRI ADX (standard, fixed, exponential, encrypted) - - Silicon Graphics VADPCM - - Nintendo DSP ADPCM a.k.a GC ADPCM - - Nintendo DTK ADPCM - - Nintendo AFC ADPCM - - Microsoft MSADPCM (standard, mono, Cricket Audio) - - Electronic Arts EA-XA (stereo, mono, Maxis) - - Electronic Arts EA-XAS (v0, v1) - - Konami MTAF ADPCM - - Konami MTA2 ADPCM - - FMOD FADPCM ADPCM - - Procyon Studio ADPCM - - Level-5 0x555 ADPCM - - Konami XMD ADPCM - - Argonaut ASF ADPCM - - Tantalus ADPCM +- CD-ROM XA ADPCM +- Sony PSX ADPCM a.k.a VAG (standard, badflags, configurable, extended) +- CRI ADX (standard, fixed, exponential, encrypted) +- Silicon Graphics VADPCM +- Nintendo DSP ADPCM a.k.a GC ADPCM +- Nintendo DTK ADPCM +- Nintendo AFC ADPCM +- Microsoft MSADPCM (standard, mono, Cricket Audio) +- Electronic Arts EA-XA (stereo, mono, Maxis) +- Electronic Arts EA-XAS (v0, v1) +- Konami MTAF ADPCM +- Konami MTA2 ADPCM +- FMOD FADPCM ADPCM +- Procyon Studio ADPCM +- Level-5 0x555 ADPCM +- Konami XMD ADPCM +- Argonaut ASF ADPCM +- Tantalus ADPCM - ADPCM (IMA-style) - - DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc) - - Microsoft MS-IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc) - - Yamaha ADPCM (AICA, Aska) - - Westwood VBR ADPCM - - OKI ADPCM (16-bit output, 4-shift, PC-FX) - - LucasArts iMUSE VBR ADPCM - - Tiger Game.com ADPCM +- DVI/IMA ADPCM (stereo/mono + high/low nibble, 3DS, Quantic Dream, SNDS, etc) +- Microsoft MS-IMA ADPCM (standard, Xbox, NDS, Radical, Wwise, FSB, WV6, etc) +- Yamaha ADPCM (AICA, Aska) +- Westwood VBR ADPCM +- OKI ADPCM (16-bit output, 4-shift, PC-FX) +- LucasArts iMUSE VBR ADPCM +- Tiger Game.com ADPCM - ADPCM (others) - - Sony HEVAG - - Ubisoft 4/6-bit ADPCM - - Platinum ADPCM - - Paradigm MC3 ADPCM - - Ocean DSA ADPCM - - lsf ADPCM - - ITU-T G.721 - - CompressWave (CWav) Huffman ADPCM +- Sony HEVAG +- Ubisoft 4/6-bit ADPCM +- Platinum ADPCM +- Paradigm MC3 ADPCM +- Ocean DSA ADPCM +- lsf ADPCM +- ITU-T G.721 +- CompressWave (CWav) Huffman ADPCM - Perceptual/transform-based - - MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc) - - Xiph Vorbis (Ogg, FSB, Wwise, OGL, Silicon Knights) - - CRI HCA - - ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco) - - ITU-T G.719 annex B a.k.a. Polycom Siren 22 - - Xiph Opus (Ogg, Switch, EA, UE4, Exient, FSB) - - Xiph CELT (FSB) - - Microsoft XMA1/2 - - Microsoft WMA v1, WMA v2, WMAPro - - AAC - - Sony ATRAC3 - - Sony ATRAC3plus - - Sony ATRAC9 - - Relic Codec - - tri-Ace PS2 Codec - - Bink - - AC3/SPDIF - - Musepack - - Electronic Arts EASpeex - - Electronic Arts EALayer3 - - Electronic Arts EA-XMA - - Electronic Arts MicroTalk a.k.a. UTK or UMT - - Inti Creates DCT codec - - Circus XPCM VQ +- MPEG MP1/2/3 (standard, AHX, XVAG, FSB, AWC, P3D, EA, etc) +- Xiph Vorbis (Ogg, FSB, Wwise, OGL, Silicon Knights) +- CRI HCA +- ITU-T G.722.1 annex C a.k.a. Polycom Siren 14 (Namco) +- ITU-T G.719 annex B a.k.a. Polycom Siren 22 +- Xiph Opus (Ogg, Switch, EA, UE4, Exient, FSB) +- Xiph CELT (FSB) +- Microsoft XMA1/2 +- Microsoft WMA v1, WMA v2, WMAPro +- AAC +- Sony ATRAC3 +- Sony ATRAC3plus +- Sony ATRAC9 +- Relic Codec +- tri-Ace PS2 Codec +- Bink +- AC3/SPDIF +- Musepack +- Electronic Arts EASpeex +- Electronic Arts EALayer3 +- Electronic Arts EA-XMA +- Electronic Arts MicroTalk a.k.a. UTK or UMT +- Inti Creates DCT codec +- Circus XPCM VQ - Misc - - SDX2 2:1 Squareroot-Delta-Exact compression DPCM - - CBD2 2:1 Cuberoot-Delta-Exact compression DPCM - - Activision EXAKT SASSC DPCM - - Xilam DERF DPCM - - Circus XPCM DPCM - - VisualArt's NWA PCM/DPCM - - Marble WADY PCM/DPCM - - InterPlay ACM - - Inti Creates Range codec - - FLAC +- SDX2 2:1 Squareroot-Delta-Exact compression DPCM +- CBD2 2:1 Cuberoot-Delta-Exact compression DPCM +- Activision EXAKT SASSC DPCM +- Xilam DERF DPCM +- Circus XPCM DPCM +- VisualArt's NWA PCM/DPCM +- Marble WADY PCM/DPCM +- InterPlay ACM +- Inti Creates Range codec +- FLAC - Others Sometimes standard codecs come in non-standard layouts that aren't normally @@ -2026,4 +2026,4 @@ proper support of encoder delay, accurate sample counts and seeking that other plugins may lack. Note that vgmstream doesn't (can't) reproduce in-game music 1:1, as internal -resampling, filters, volume, etc, are not replicated. +resampling, filters, volume, etc, are not replicated. \ No newline at end of file diff --git a/doc/TXTH.md b/doc/TXTH.md index 1a7ecaf86..8ec905fe0 100644 --- a/doc/TXTH.md +++ b/doc/TXTH.md @@ -132,8 +132,8 @@ as explained below, but often will use default values. Accepted codec strings: # # - MSADPCM Microsoft ADPCM (mono/stereo) # * For some PC games -# * Interleave (frame size) varies, often multiple of 0x100 [required] -# +# * Interleave (frame size) varies, often 0x2c/0x8c/0x100/0x400 and max 0x800 [required] + # - AICA Yamaha AICA ADPCM (mono/stereo) # * For some Dreamcast games, and some arcade (Naomi) games # * Special interleave is multiple of 0x1 From f4a7363cdd7f038939781e6bbe15b2be5ede7c37 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Sun, 2 Jul 2023 19:33:57 +0300 Subject: [PATCH 085/141] BNK Sony (v3): Bank/Sound name support --- src/meta/bnk_sony.c | 75 +++++++++++++++++++++++++++++++++++++++------ src/meta/vag.c | 19 ++++++------ 2 files changed, 75 insertions(+), 19 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 56b66314d..e0c7c7555 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -8,7 +8,8 @@ typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec; /* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - uint32_t start_offset, stream_offset, name_offset = 0; + char bank_name[STREAM_NAME_SIZE] /*[8]*/, stream_name[STREAM_NAME_SIZE] /*[16]*/; + uint32_t start_offset, stream_offset, bank_name_offset = 0, stream_name_offset = 0; uint32_t stream_size, interleave = 0; int channels = 0, loop_flag, sample_rate, big_endian; int32_t loop_start = 0, loop_end = 0; @@ -96,7 +97,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { uint32_t table1_suboffset, table2_suboffset; uint32_t table2_entry_offset = 0, table3_entry_offset = 0; int table4_entry_id = -1; - uint32_t table4_entries_offset, table4_names_offset; + uint32_t table4_entry_idx, table4_entries_offset, table4_names_offset; + uint32_t entry_offset, entry_count; switch(sblk_version) { @@ -332,8 +334,56 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* parse names */ switch(sblk_version) { - //case 0x03: /* different format? */ + case 0x03: + for (i = 0; i < section_entries; i++) { + entry_offset = read_u32(table1_offset + (i * table1_entry_size) + table1_suboffset, sf); + entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); + + /* is table2_entry_offset in the range of the expected section */ + if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) + table4_entry_id = i; + } + + /* table4: + * 0x00: bank name (optional) + * 0x08: name section offset + * 0x0C-0x14: 3 null pointers (reserved?) + * 0x18: 32 name chunk offsets (shorts) + */ + + /* Name chunks are organised as + * (name[0] + name[4] + name[8] + name[12]) & 0x1F; + * and using that as the index for the chunk offsets + * name_sect_offset + (chunk_idx[result] * 0x14); + */ + if (read_u8(table4_offset, sf)) + bank_name_offset = table4_offset; + + table4_entries_offset = table4_offset + 0x18; + table4_names_offset = table4_offset + read_u32(table4_offset + 0x08, sf); + + for (i = 0; i < 32; i++) { + table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf); + stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14); + /* searches the chunk until it finds the target name/index, or breaks at empty name */ + while (read_u8(stream_name_offset, sf)) { + /* in case it goes somewhere out of bounds unexpectedly */ + //if ((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + + // read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F != i) + // goto fail; + if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id) + goto loop_break; /* to break out of the for+while loop simultaneously */ + //break; + stream_name_offset += 0x14; + } + } + //goto fail; /* didn't find any valid index? */ + loop_break: + break; + //case 0x04: /* different format? */ + //case 0x05: /* different format? */ + case 0x08: case 0x09: case 0x0d: @@ -342,7 +392,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x10: /* find if this sound has an assigned name in table1 */ for (i = 0; i < section_entries; i++) { - uint32_t entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf); + entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf); /* rarely (ex. Polara sfx) one name applies to multiple materials, * from current entry_offset to next entry_offset (section offsets should be in order) */ @@ -358,6 +408,9 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* 0x0c: table4 size */ /* variable: entries */ /* variable: names (null terminated) */ + if (read_u8(table4_offset, sf)) + bank_name_offset = table4_offset; + table4_entries_offset = table4_offset + read_u32(table4_offset+0x08, sf); table4_names_offset = table4_entries_offset + (0x10*section_entries); //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); @@ -366,7 +419,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { for (i = 0; i < section_entries; i++) { int entry_id = read_u32(table4_entries_offset+(i*0x10)+0x0c, sf); if (entry_id == table4_entry_id) { - name_offset = table4_names_offset + read_u32(table4_entries_offset+(i*0x10)+0x00, sf); + stream_name_offset = table4_names_offset + read_u32(table4_entries_offset+(i*0x10)+0x00, sf); break; } } @@ -376,7 +429,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { break; } - //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, name_offset=%lx\n", stream_offset, stream_size, name_offset); + //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", stream_offset, stream_size, stream_name_offset); } @@ -635,9 +688,13 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { goto fail; } - if (name_offset) - read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf); - + if (!bank_name_offset && stream_name_offset) + read_string(vgmstream->stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); + else if (bank_name_offset && stream_name_offset) { + read_string(bank_name, STREAM_NAME_SIZE, bank_name_offset, sf); + read_string(stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); + snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", bank_name, stream_name); + } if (!vgmstream_open_stream(vgmstream, sf, start_offset)) goto fail; diff --git a/src/meta/vag.c b/src/meta/vag.c index 94c60593a..c8979ea64 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -81,25 +81,24 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { loop_flag = 0; break; - case 0x70474156: /* pGAV (little endian / stereo) [Jak 3 (PS2), Jak X (PS2)] */ + case 0x70474156: /* pGAV (little endian / stereo) [Jak II, Jak 3, Jak X (PS2)] */ meta_type = meta_VAG_custom; start_offset = 0x30; - if (is_id32be(0x20,sf, "Ster")) { - channels = 2; + if (is_id32be(0x2000,sf, "pGAV")) + interleave = 0x2000; /* Jak II & Jak 3 interleave, includes header */ + else if (is_id32be(0x1000,sf, "pGAV")) + interleave = 0x1000; /* Jak X interleave, includes header */ + else + interleave = 0; - if (is_id32be(0x2000,sf, "pGAV")) - interleave = 0x2000; /* Jak 3 interleave, includes header */ - else if (is_id32be(0x1000,sf, "pGAV")) - interleave = 0x1000; /* Jak X interleave, includes header */ - else - goto fail; + if (interleave) { + channels = 2; interleave_first = interleave - start_offset; /* interleave includes header */ interleave_first_skip = start_offset; } else { channels = 1; - interleave = 0; } channel_size = read_u32le(0x0C,sf) / channels; From aa3a11d5864e38838eb93fd7d87db01b6792dba2 Mon Sep 17 00:00:00 2001 From: lico-n <85761230+lico-n@users.noreply.github.com> Date: Fri, 7 Jul 2023 14:45:49 +0200 Subject: [PATCH 086/141] Add HCA Key [Final Fantasy VII: Ever Crisis(Android)] --- src/meta/hca_keys.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 555f47a43..9de2a3a56 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -1187,6 +1187,9 @@ static const hcakey_info hcakey_list[] = { // Disney Star Smash (Android) {3941111674189632}, // 000E006B915C3740 + // Final Fantasy VII: Ever Crisis (Android) + {19629307353822}, // 000011DA4DE45ADE + }; #endif/*_HCA_KEYS_H_*/ From fc7848bfd350517f1830d8e88dbc093578b08260 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 10:52:28 +0200 Subject: [PATCH 087/141] cleanup: hgc1, filp, wii_mus, sl3, wb, xss - Remove fake extension .hgc1 (use .str) - Remove fake extension .filp (use .fil) - Remove fake extension .sl3 (use .ms) --- src/formats.c | 12 ++-- src/meta/meta.h | 4 +- src/meta/ps2_bg00.c | 81 ++++++++++---------------- src/meta/ps2_filp.c | 122 ++++++++++++++++++-------------------- src/meta/ps2_hgc1.c | 79 +++++++++---------------- src/meta/ps2_sl3.c | 34 +++++------ src/meta/ps2_wb.c | 109 ++++++++++++++-------------------- src/meta/wii_mus.c | 132 ++++++++++-------------------------------- src/meta/xss.c | 99 ++++++++++++++----------------- src/vgmstream.c | 4 +- src/vgmstream_types.h | 4 +- 11 files changed, 261 insertions(+), 419 deletions(-) diff --git a/src/formats.c b/src/formats.c index 8d17e398a..546505a42 100644 --- a/src/formats.c +++ b/src/formats.c @@ -217,7 +217,6 @@ static const char* extension_list[] = { "hd3", "hdr", "hdt", - "hgc1", "his", "hps", "hsf", @@ -501,7 +500,6 @@ static const char* extension_list[] = { "sgd", "sgt", "sgx", - "sl3", "slb", //txth/reserved [THE Nekomura no Hitobito (PS2)] "sli", "smc", @@ -1025,8 +1023,8 @@ static const meta_info meta_info_list[] = { {meta_SADL, "Procyon Studio SADL header"}, {meta_PS2_BMDX, "Beatmania .bmdx header"}, {meta_DSP_WSI, "Alone in the Dark .WSI header"}, - {meta_AIFC, "Apple AIFF-C (Audio Interchange File Format) header"}, - {meta_AIFF, "Apple AIFF (Audio Interchange File Format) header"}, + {meta_AIFC, "Apple AIFF-C header"}, + {meta_AIFF, "Apple AIFF header"}, {meta_STR_SNDS, "3DO SNDS header"}, {meta_WS_AUD, "Westwood Studios .AUD header"}, {meta_PS2_IVB, "IVB/BVII header"}, @@ -1037,7 +1035,7 @@ static const meta_info meta_info_list[] = { {meta_NWA_NWAINFOINI, "VisualArt's NWA header (NWAINFO.INI looping)"}, {meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"}, {meta_XSS, "Dino Crisis 3 XSS File"}, - {meta_HGC1, "Knights of the Temple 2 hgC1 Header"}, + {meta_HGC1, "Cauldron HGC1 header"}, {meta_AUS, "Capcom AUS Header"}, {meta_RWS, "RenderWare RWS header"}, {meta_EA_1SNH, "Electronic Arts 1SNh header"}, @@ -1093,7 +1091,7 @@ static const meta_info meta_info_list[] = { {meta_YMF, "Yuke's .YMF Header"}, {meta_FAG, "Radical .FAG Header"}, {meta_PS2_MIHB, "Sony MultiStream MIC header"}, - {meta_DSP_WII_MUS, "mus header"}, + {meta_MUS_KRONE, "Krone .MUS header"}, {meta_WII_SNG, "SNG DSP Header"}, {meta_RSD, "Radical RSD header"}, {meta_DC_ASD, "ASD Header"}, @@ -1168,7 +1166,7 @@ static const meta_info meta_info_list[] = { {meta_NGC_DSP_AAAP, "Acclaim Austin AAAp DSP header"}, {meta_NGC_DSP_KONAMI, "Konami DSP header"}, {meta_BNSF, "Namco Bandai BNSF header"}, - {meta_PS2_WB, "Shooting Love. ~TRIZEAL~ WB header"}, + {meta_WB, "Triangle Service .WB header"}, {meta_S14, "Namco .S14 raw header"}, {meta_SSS, "Namco .SSS raw header"}, {meta_PS2_GCM, "Namco GCM header"}, diff --git a/src/meta/meta.h b/src/meta/meta.h index 69b455cfa..6cf2e072c 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -300,7 +300,7 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf); VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile); @@ -433,7 +433,7 @@ VGMSTREAM * init_vgmstream_ngc_dsp_konami(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_bnsf(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_wb(STREAMFILE* sf); VGMSTREAM* init_vgmstream_raw_s14_sss(STREAMFILE* sf); diff --git a/src/meta/ps2_bg00.c b/src/meta/ps2_bg00.c index 4ae1362da..7941e114a 100644 --- a/src/meta/ps2_bg00.c +++ b/src/meta/ps2_bg00.c @@ -1,65 +1,46 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* BG0 (from Ibara, Mushihimesama) -Note: Seems the Loop Infos are stored external... */ -VGMSTREAM * init_vgmstream_bg00(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; +/* BG00 - from Cave games [Ibara (PS2), Mushihime-sama (PS2)] */ +VGMSTREAM* init_vgmstream_bg00(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag = 0; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("bg00",filename_extension(filename))) goto fail; - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x42473030) /* "BG00" */ - goto fail; + /* check */ + if (!is_id32be(0x00,sf, "BG00")) + return NULL; - loop_flag = (read_32bitLE(0x08,streamFile)!=0); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; + /* .bg00: header ID (no filenames or debug strings) */ + if (!check_extensions(sf,"bg00")) + return NULL; - /* fill in the vital statistics */ - start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitBE(0x80,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitBE(0x4C,streamFile)*2)*28/16/channel_count; - } + if (!is_id32be(0x40,sf, "VAGp")) + return NULL; + if (!is_id32be(0x70,sf, "VAGp")) + return NULL; - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x10,streamFile); - vgmstream->meta_type = meta_BG00; + loop_flag = 0; /* flag at 0x08? loop points seem external */ + channels = 2; /* mono files use regular VAG */ + start_offset = 0x800; - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; + vgmstream->meta_type = meta_BG00; + vgmstream->sample_rate = read_s32be(0x80,sf); + vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,sf), 1); - } - } + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = read_32bitLE(0x10,sf); + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/ps2_filp.c b/src/meta/ps2_filp.c index 967cf2cc7..1f4e9e028 100644 --- a/src/meta/ps2_filp.c +++ b/src/meta/ps2_filp.c @@ -1,67 +1,55 @@ -#include "meta.h" -#include "../layout/layout.h" -#include "../util.h" - -/* FILp (Resident Evil - Dead Aim) */ -VGMSTREAM * init_vgmstream_filp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("filp",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0x0,streamFile) != 0x46494C70) /* "FILp" */ - goto fail; - if (read_32bitBE(0x100,streamFile) != 0x56414770) /* "VAGp" */ - goto fail; - if (read_32bitBE(0x130,streamFile) != 0x56414770) /* "VAGp" */ - goto fail; - if (get_streamfile_size(streamFile) != read_32bitLE(0xC,streamFile)) - goto fail; - - loop_flag = (read_32bitLE(0x34,streamFile) == 0); - channel_count = read_32bitLE(0x4,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x0; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x110,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->layout_type = layout_blocked_filp; - vgmstream->meta_type = meta_FILP; - - /* open the file for reading */ - { - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - } - } - - block_update_filp(start_offset,vgmstream); - vgmstream->num_samples = read_32bitLE(0x10C,streamFile)/16*28; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = vgmstream->num_samples; - } - - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" + + +/* FILp - from Resident Evil: Dead Aim (PS2) */ +VGMSTREAM* init_vgmstream_filp(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag; + + + /* checks */ + if (!is_id32be(0x00,sf, "FILp")) + return NULL; + /* .fil: extension in bigfile */ + if (!check_extensions(sf,"fil")) + return NULL; + + channels = read_s32le(0x04,sf); /* stereo only though */ + if (read_32bitLE(0x0C,sf) != get_streamfile_size(sf)) + goto fail; + loop_flag = (read_u32le(0x34,sf) == 0x00); /* 00/01/02 */ + + if (!is_id32be(0x100,sf, "VAGp")) + return NULL; + if (!is_id32be(0x130,sf, "VAGp")) + return NULL; + + start_offset = 0x00; /* multiple FILp blocks pasted together (each including VAGps, but their sizes refer to the whole thing) */ + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_FILP; + vgmstream->sample_rate = read_s32le(0x110,sf); + + vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x10C,sf), 1); /* channel size for the whole stream */ + vgmstream->loop_start_sample = 0; + vgmstream->loop_end_sample = vgmstream->num_samples; + + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_blocked_filp; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + block_update(start_offset, vgmstream); + + return vgmstream; +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/ps2_hgc1.c b/src/meta/ps2_hgc1.c index 7588febe8..1b3d9acb9 100644 --- a/src/meta/ps2_hgc1.c +++ b/src/meta/ps2_hgc1.c @@ -1,64 +1,41 @@ #include "meta.h" -#include "../util.h" - -/* hgC1 (from Knights of the Temple 2) */ -VGMSTREAM * init_vgmstream_hgc1(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("hgc1",filename_extension(filename))) goto fail; +#include "../coding/coding.h" + +/* hgC1 - from Knights of the Temple 2 (PS2) */ +VGMSTREAM* init_vgmstream_hgc1(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag = 0; + + /* checks */ + if (!is_id32be(0x00,sf, "hgC1")) + return NULL; + if (!is_id32be(0x04,sf, "strm")) + return NULL; + if (!check_extensions(sf,"str")) + return NULL; + + start_offset = 0x20; + loop_flag = 0; + channels = read_s32le(0x08,sf); /* always stereo? */ - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x68674331) /* "hgC1" */ - goto fail; - loop_flag = 0; - channel_count = read_32bitLE(0x08,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x10,streamFile); - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = (read_32bitLE(0x0C,streamFile)*32)/channel_count/16*28; - } + vgmstream->meta_type = meta_HGC1; + vgmstream->sample_rate = read_s32le(0x10,sf); + vgmstream->num_samples = ps_bytes_to_samples(read_u32le(0x0C,sf) * 0x10, 1); /* mono frames*/ + vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x10; - vgmstream->meta_type = meta_HGC1; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/ps2_sl3.c b/src/meta/ps2_sl3.c index 69fc81d38..8dc820466 100644 --- a/src/meta/ps2_sl3.c +++ b/src/meta/ps2_sl3.c @@ -1,41 +1,37 @@ #include "meta.h" #include "../coding/coding.h" -/* SL3 - Atari Melbourne House games [ Test Drive Unlimited (PS2), Transformers (PS2)] */ -VGMSTREAM * init_vgmstream_sl3(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; +/* SL3 - Winky Soft / Atari Melbourne House games [Test Drive Unlimited (PS2), Transformers 2003/2004 (PS2)] */ +VGMSTREAM* init_vgmstream_sl3(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag = 0, channel_count; + int loop_flag = 0, channels; /* checks */ - /* .ms: actual extension, sl3: header id */ - if (!check_extensions(streamFile, "ms,sl3")) + if (!is_id32be(0x00,sf, "SL3\0")) goto fail; - if (read_32bitBE(0x00,streamFile) != 0x534C3300) /* "SL3\0" */ + /* .ms: actual extension */ + if (!check_extensions(sf, "ms")) goto fail; loop_flag = 0; - channel_count = read_32bitLE(0x14,streamFile); + channels = read_32bitLE(0x14,sf); start_offset = 0x8000; /* also at 0x24? */ - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = read_32bitLE(0x18,streamFile); - vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(streamFile)-start_offset,channel_count); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x1C,streamFile); - } + vgmstream->meta_type = meta_SL3; + vgmstream->sample_rate = read_32bitLE(0x18,sf); + vgmstream->num_samples = ps_bytes_to_samples(get_streamfile_size(sf)-start_offset,channels); vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x20,streamFile); - vgmstream->meta_type = meta_SL3; + vgmstream->interleave_block_size = read_32bitLE(0x20,sf); - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) goto fail; return vgmstream; diff --git a/src/meta/ps2_wb.c b/src/meta/ps2_wb.c index 49efbf6b7..55f1680a8 100644 --- a/src/meta/ps2_wb.c +++ b/src/meta/ps2_wb.c @@ -1,64 +1,45 @@ -#include "meta.h" -#include "../util.h" - -/* WB (from Shooting Love. ~TRIZEAL~) */ -VGMSTREAM * init_vgmstream_ps2_wb(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("wb",filename_extension(filename))) goto fail; - - /* check header */ - if (read_32bitBE(0,streamFile) != 0x00000000) - goto fail; - - loop_flag = read_32bitLE(0x4,streamFile); - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x10; - vgmstream->channels = channel_count; - vgmstream->sample_rate = 48000; - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = read_32bitLE(0xC,streamFile)/4; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x4,streamFile); - vgmstream->loop_end_sample = read_32bitLE(0x8,streamFile); - } - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 2; - vgmstream->meta_type = meta_PS2_WB; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - -fail: - /* clean up anything we may have opened */ - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" + + +/* .WB - from Shooting Love. ~TRIZEAL~ */ +VGMSTREAM* init_vgmstream_wb(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag; + + /* check header */ + if (read_u32le(0x00,sf) != 0x00000000) + return NULL; + if (read_u32le(0x0c,sf) + 0x10 != get_streamfile_size(sf)) + return NULL; + + /* .wb: actual extension */ + if (!check_extensions(sf,"wb")) + goto fail; + + channels = 2; + start_offset = 0x10; + loop_flag = read_32bitLE(0x04,sf) > 0; /* loop end may be defined */ + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_WB; + vgmstream->sample_rate = 48000; + vgmstream->num_samples = pcm16_bytes_to_samples(read_u32le(0x0C,sf), channels); + vgmstream->loop_start_sample = read_s32le(0x04,sf); + vgmstream->loop_end_sample = read_s32le(0x08,sf); + + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 2; + + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; + return vgmstream; +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/wii_mus.c b/src/meta/wii_mus.c index 488930be4..de14948e4 100644 --- a/src/meta/wii_mus.c +++ b/src/meta/wii_mus.c @@ -1,124 +1,56 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" -#include "../util.h" -/* .mus, as seen in Star Wars The Force Unleashed for Wii */ -/* Doesn't seem to be working quite right yet, coef table looks odd */ -VGMSTREAM * init_vgmstream_wii_mus(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - off_t interleave; +/* .mus - from Star Wars: The Force Unleashed (Wii) */ +VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset, data_size; + int channels, loop_flag, interleave; + int32_t num_samples; - int i; - struct { - uint16_t gain; - uint16_t initial_ps; - uint16_t initial_hist1; - uint16_t initial_hist2; - uint16_t loop_ps; - /* - uint16_t loop_hist1; - uint16_t loop_hist2; - */ - } channel[2]; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("mus",filename_extension(filename))) goto fail; + /* checks */ + num_samples = read_s32be(0x00,sf); + interleave = read_s32be(0x04,sf); + start_offset = read_u32be(0x08,sf); + data_size = read_u32be(0x0c,sf); - start_offset = read_32bitBE(0x08,streamFile); - interleave = read_32bitBE(0x04,streamFile); + if (interleave != 0x8000) + return NULL; + if (start_offset != 0x80) + return NULL; + if (data_size + start_offset != get_streamfile_size(sf)) + return NULL; + /* could test gain/initial ps at 0x10 + 0x20 too */ - for (i=0;i<2;i++) - { - channel[i].gain = read_16bitBE(0x30+i*0x2e,streamFile); - channel[i].initial_ps = read_16bitBE(0x32+i*0x2e,streamFile); - channel[i].initial_hist1 = read_16bitBE(0x34+i*0x2e,streamFile); - channel[i].initial_hist2 = read_16bitBE(0x36+i*0x2e,streamFile); - channel[i].loop_ps = read_16bitBE(0x38+i*0x2e,streamFile); - } + if (!check_extensions(sf,"mus")) + return NULL; - /* check initial predictor/scale */ - if (channel[0].initial_ps != (uint8_t)read_8bit(start_offset,streamFile)) - goto fail; - if (channel[1].initial_ps != (uint8_t)read_8bit(start_offset+interleave,streamFile)) - goto fail; - - /* check type==0 and gain==0 */ - if (channel[0].gain || - channel[1].gain) - goto fail; -#if 0 - if (ch0_header.loop_flag) { - off_t loop_off; - /* check loop predictor/scale */ - loop_off = ch0_header.loop_start_offset/16*8; - loop_off = (loop_off/interleave*interleave*2) + (loop_off%interleave); - if (ch0_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off,streamFile)) - goto fail; - if (ch1_header.loop_ps != (uint8_t)read_8bit(start_offset+loop_off+interleave,streamFile)) - goto fail; - } -#endif + channels = 2; + loop_flag = 0; /* build the VGMSTREAM */ - - vgmstream = allocate_vgmstream(2,0); + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - /* fill in the vital statistics */ - vgmstream->num_samples = read_32bitBE(0x0,streamFile); - vgmstream->sample_rate = (uint16_t)read_16bitBE(0x6c,streamFile); - - /* TODO: adjust for interleave? */ -#if 0 - vgmstream->loop_start_sample = dsp_nibbles_to_samples( - ch0_header.loop_start_offset); - vgmstream->loop_end_sample = dsp_nibbles_to_samples( - ch0_header.loop_end_offset)+1; -#endif + vgmstream->meta_type = meta_MUS_KRONE; + vgmstream->num_samples = num_samples; + vgmstream->sample_rate = read_u16be(0x6c,sf); vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; - vgmstream->meta_type = meta_DSP_WII_MUS; + vgmstream->interleave_block_size = interleave; /* no last block size unlike similar DSPs */ - /* coeffs */ - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10 + i*2,streamFile); - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3e + i*2,streamFile); - } - - /* initial history */ - /* always 0 that I've ever seen, but for completeness... */ - vgmstream->ch[0].adpcm_history1_16 = channel[0].initial_hist1; - vgmstream->ch[0].adpcm_history2_16 = channel[0].initial_hist2; - vgmstream->ch[1].adpcm_history1_16 = channel[1].initial_hist1; - vgmstream->ch[1].adpcm_history2_16 = channel[1].initial_hist2; - - vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[0].streamfile) goto fail; - vgmstream->ch[1].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[1].streamfile) goto fail; - - /* open the file for reading */ - for (i=0;i<2;i++) { - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+i*interleave; - } + dsp_read_coefs_be(vgmstream, sf, 0x10, 0x2e); + dsp_read_hist_be(vgmstream, sf, 0x10 + 0x24, 0x2e); + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - fail: - /* clean up anything we may have opened */ - if (vgmstream) { - if (vgmstream->ch[0].streamfile) close_streamfile(vgmstream->ch[0].streamfile); - close_vgmstream(vgmstream); - } + close_vgmstream(vgmstream); return NULL; } - diff --git a/src/meta/xss.c b/src/meta/xss.c index eecf7a197..588ce7487 100644 --- a/src/meta/xss.c +++ b/src/meta/xss.c @@ -1,72 +1,61 @@ #include "meta.h" -#include "../util.h" +#include "../coding/coding.h" -/* XSS (found in Dino Crisis 3) */ -VGMSTREAM * init_vgmstream_xss(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag = 0; - int channel_count; - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("xss",filename_extension(filename))) goto fail; +/* .XSS - found in Dino Crisis 3 (Xbox) */ +VGMSTREAM* init_vgmstream_xss(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t start_offset; + int channels, loop_flag, sample_rate; - /* check header */ - if ((uint16_t)read_16bitLE(0x15A,streamFile) != 0x10) - goto fail; - if (read_32bitLE(0x154,streamFile) / read_32bitLE(0x150,streamFile) != - (uint16_t)read_16bitLE(0x158,streamFile)) - goto fail; + /* checks */ + /* 00: name + garbage data up to ? + * (due to garbage it's hard which values are from this header, but these seem consistent) */ + if (read_u32le(0x0c,sf) != 0x3a) + return NULL; + if (read_u32le(0x10,sf) != 0x00) + return NULL; - loop_flag = (read_32bitLE(0x144,streamFile)!=0); - channel_count = (uint16_t)read_16bitLE(0x14E,streamFile); + if (!check_extensions(sf,"xss")) + return NULL; + + /* some floats and stuff up to 0x100, then some sizes, then RIFF fmt-like header */ - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; + uint32_t head_offset = 0x140; + if (read_u32le(head_offset+0x00, sf) != 0x40) + return NULL; + + loop_flag = (read_u32le(head_offset + 0x04,sf) != 0); + if (read_u16le(head_offset + 0x0c,sf) != 0x01) + return NULL; + channels = read_u16le(head_offset + 0x0E,sf); + sample_rate = read_u32le(head_offset + 0x10,sf); + /* 14: bitrate */ + /* 18: block size */ + if (read_u16le(head_offset + 0x1A,sf) != 0x10) + return NULL; - /* fill in the vital statistics */ start_offset = 0x800; - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_32bitLE(0x150,streamFile); - vgmstream->coding_type = coding_PCM16LE; - vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count; - if (loop_flag) { - vgmstream->loop_start_sample = read_32bitLE(0x144,streamFile)/2/channel_count; - vgmstream->loop_end_sample = read_32bitLE(0x148,streamFile)/2/channel_count; - } + - if (vgmstream->channels == 1) { - vgmstream->layout_type = layout_none; - } else if (vgmstream->channels > 1) { - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x2; - } + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels,loop_flag); + if (!vgmstream) goto fail; vgmstream->meta_type = meta_XSS; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = pcm16_bytes_to_samples(get_streamfile_size(sf) - start_offset, channels); + vgmstream->loop_start_sample = pcm16_bytes_to_samples(read_u32le(head_offset + 0x04,sf), channels); + vgmstream->loop_end_sample = pcm16_bytes_to_samples(read_u32le(head_offset + 0x08,sf), channels); - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } + vgmstream->coding_type = coding_PCM16LE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = 0x2; + if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + goto fail; return vgmstream; - - /* clean up anything we may have opened */ fail: - if (vgmstream) close_vgmstream(vgmstream); + close_vgmstream(vgmstream); return NULL; } diff --git a/src/vgmstream.c b/src/vgmstream.c index 866e40a71..aec48ee45 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -130,7 +130,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_mihb, init_vgmstream_ngc_pdt_split, init_vgmstream_ngc_pdt, - init_vgmstream_wii_mus, + init_vgmstream_mus_krone, init_vgmstream_dc_asd, init_vgmstream_spsd, init_vgmstream_rsd, @@ -201,7 +201,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_dmsg, init_vgmstream_ngc_dsp_aaap, init_vgmstream_ngc_dsp_konami, - init_vgmstream_ps2_wb, + init_vgmstream_wb, init_vgmstream_bnsf, init_vgmstream_ps2_gcm, init_vgmstream_smpl, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 028730216..926935915 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -258,7 +258,7 @@ typedef enum { meta_DSP_SADB, /* .sad */ meta_DSP_WSI, /* .wsi */ meta_IDSP_TT, /* Traveller's Tales games */ - meta_DSP_WII_MUS, /* .mus */ + meta_MUS_KRONE, meta_DSP_WII_WSD, /* Phantom Brave (WII) */ meta_WII_NDP, /* Vertigo (Wii) */ meta_DSP_YGO, /* Konami: Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ @@ -455,7 +455,7 @@ typedef enum { meta_AST_MMV, meta_DMSG, /* Nightcaster II - Equinox (XBOX) */ meta_NGC_DSP_AAAP, /* Turok: Evolution (NGC), Vexx (NGC) */ - meta_PS2_WB, /* Shooting Love. ~TRIZEAL~ */ + meta_WB, meta_S14, /* raw Siren 14, 24kbit mono */ meta_SSS, /* raw Siren 14, 48kbit stereo */ meta_PS2_GCM, /* NamCollection */ From 204d1f560fc3bd001f2c7ae91905d165b6d55f61 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 10:53:12 +0200 Subject: [PATCH 088/141] Fix TXTH dynamic chunks in some cases --- src/meta/txth.c | 9 ++++++++- src/meta/txth_streamfile.h | 8 +++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/meta/txth.c b/src/meta/txth.c index 73995bf8c..6cc2a04e2 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -142,6 +142,8 @@ typedef struct { int chunk_start_set; int chunk_size_set; int chunk_count_set; + int chunk_bsize_set; + int chunk_dsize_set; uint32_t base_offset; uint32_t is_offset_absolute; @@ -827,7 +829,8 @@ static void set_body_chunk(txth_header* txth) { //todo maybe should only be done once, or have some count to retrigger to simplify? if (!txth->chunk_start_set || !txth->chunk_size_set || !txth->chunk_count_set) return; - if (txth->chunk_size == 0 && !(txth->chunk_bsize_offset || txth->chunk_dsize_offset)) + + if (txth->chunk_size == 0 && !(txth->chunk_bsize_set || txth->chunk_dsize_set)) return; if (txth->chunk_start > txth->data_size || txth->chunk_count == 0) return; @@ -853,6 +856,8 @@ static void set_body_chunk(txth_header* txth) { cfg.chunk_bsize_offset = txth->chunk_bsize_offset; cfg.chunk_dsize_offset = txth->chunk_dsize_offset; cfg.chunk_be = txth->chunk_big_endian; + cfg.chunk_bsize_set = txth->chunk_bsize_set; + cfg.chunk_dsize_set = txth->chunk_dsize_set; cfg.chunk_start = txth->chunk_start; cfg.chunk_size = txth->chunk_size; @@ -1473,10 +1478,12 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha else if (is_string(key,"chunk_size_offset")) { if (!parse_num(txth->sf_head,txth,val, &txth->chunk_bsize_offset)) goto fail; txth->chunk_size_set = 1; + txth->chunk_bsize_set = 1; } else if (is_string(key,"chunk_data_size_offset")) { if (!parse_num(txth->sf_head,txth,val, &txth->chunk_dsize_offset)) goto fail; txth->chunk_size_set = 1; + txth->chunk_dsize_set = 1; } else if (is_string(key,"chunk_endianness")) { if (!parse_endianness(txth, val, &txth->chunk_big_endian, NULL)) goto fail; diff --git a/src/meta/txth_streamfile.h b/src/meta/txth_streamfile.h index 7816ea3bb..604550eb4 100644 --- a/src/meta/txth_streamfile.h +++ b/src/meta/txth_streamfile.h @@ -17,6 +17,8 @@ typedef struct { uint32_t chunk_bsize_offset; uint32_t chunk_dsize_offset; int chunk_be; + int chunk_bsize_set; + int chunk_dsize_set; } txth_io_config_data; typedef struct { @@ -72,15 +74,15 @@ static size_t txth_io_read(STREAMFILE* sf, uint8_t* dest, off_t offset, size_t l } /* chunk size reader (overwrites the above) */ - if (data->cfg.chunk_header_size && (data->cfg.chunk_bsize_offset || data->cfg.chunk_dsize_offset)) { + if (data->cfg.chunk_header_size && (data->cfg.chunk_bsize_set || data->cfg.chunk_dsize_set)) { read_u32_t read_u32 = data->cfg.chunk_be ? read_u32be : read_u32le; data->block_size = 0; data->data_size = 0; - if (data->cfg.chunk_bsize_offset) + if (data->cfg.chunk_bsize_set) data->block_size = read_u32(data->physical_offset + data->cfg.chunk_bsize_offset, sf); - if (data->cfg.chunk_dsize_offset) + if (data->cfg.chunk_dsize_set) data->data_size = read_u32(data->physical_offset + data->cfg.chunk_dsize_offset, sf); if (!data->block_size && !data->data_size) { /* bad read? */ From 61f6ba6cfd8c2d69c7235f61c85841f075a24e14 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 11:30:28 +0200 Subject: [PATCH 089/141] Remove .gsb extension (use .gsp) Uses .gsp as the base file for cleaner parsing --- src/formats.c | 4 +-- src/meta/gsp_gsb.c | 68 +++++++++++++++++++++---------------------- src/meta/meta.h | 2 +- src/vgmstream.c | 2 +- src/vgmstream_types.h | 6 ++-- 5 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/formats.c b/src/formats.c index 546505a42..76232fe62 100644 --- a/src/formats.c +++ b/src/formats.c @@ -206,8 +206,8 @@ static const char* extension_list[] = { "gin", "gms", "grn", - "gsb", "gsf", + "gsp", "gtd", "gwm", @@ -1110,7 +1110,7 @@ static const meta_info meta_info_list[] = { {meta_GCA, "GCA DSP Header"}, {meta_SPT_SPD, "SPT+SPD DSP Header"}, {meta_ISH_ISD, "ISH+ISD DSP Header"}, - {meta_GSP_GSB, "Tecmo GSP+GSB Header"}, + {meta_GSND, "Tecmo GSND Header"}, {meta_YDSP, "Yuke's YDSP Header"}, {meta_NGC_SSM, "SSM DSP Header"}, {meta_PS2_JOE, "Asobo Studio .JOE header"}, diff --git a/src/meta/gsp_gsb.c b/src/meta/gsp_gsb.c index 15ec2bcb2..9ea897f3f 100644 --- a/src/meta/gsp_gsb.c +++ b/src/meta/gsp_gsb.c @@ -4,55 +4,55 @@ #include "../util/chunks.h" /* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */ -VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_gsnd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - STREAMFILE* sf_head = NULL; + STREAMFILE* sb = NULL; int loop_flag, channel_count, sample_rate, num_samples, loop_start, loop_end; off_t start_offset, chunk_offset, first_offset; size_t data_size; int codec; - /* checks */ - if (!check_extensions(sf,"gsb")) + if (!is_id32be(0x00,sf, "GSND")) goto fail; - sf_head = open_streamfile_by_ext(sf, "gsp"); - if (!sf_head) goto fail; - - if (!is_id32be(0x00,sf_head, "GSND")) + if (!check_extensions(sf,"gsp")) goto fail; + + sb = open_streamfile_by_ext(sf, "gsb"); + if (!sb) goto fail; + /* 0x04: version? */ /* 0x08: 1? */ /* 0x0c: 0? */ - first_offset = read_32bitBE(0x10,sf_head); /* usually 0x14 */ + first_offset = read_32bitBE(0x10,sf); /* usually 0x14 */ - if (!find_chunk_be(sf_head, 0x48454144,first_offset,1, &chunk_offset,NULL)) /* "HEAD" */ + if (!find_chunk_be(sf, get_id32be("HEAD"),first_offset,1, &chunk_offset,NULL)) goto fail; /* 0x00: header size */ /* 0x04: num_chunks */ - if (!find_chunk_be(sf_head, 0x44415441,first_offset,1, &chunk_offset,NULL)) /* "DATA" */ + if (!find_chunk_be(sf, get_id32be("DATA"),first_offset,1, &chunk_offset,NULL)) goto fail; - data_size = read_32bitBE(chunk_offset + 0x00,sf_head); - codec = read_32bitBE(chunk_offset + 0x04,sf_head); - sample_rate = read_32bitBE(chunk_offset + 0x08,sf_head); + data_size = read_32bitBE(chunk_offset + 0x00,sf); + codec = read_32bitBE(chunk_offset + 0x04,sf); + sample_rate = read_32bitBE(chunk_offset + 0x08,sf); /* 0x0c: always 16? */ - channel_count = read_16bitBE(chunk_offset + 0x0e,sf_head); + channel_count = read_16bitBE(chunk_offset + 0x0e,sf); /* 0x10: always 0? */ - num_samples = read_32bitBE(chunk_offset + 0x14,sf_head); + num_samples = read_32bitBE(chunk_offset + 0x14,sf); /* 0x18: always 0? */ /* 0x1c: unk (varies with codec_id) */ - if (!find_chunk_be(sf_head, 0x42534943,first_offset,1, &chunk_offset,NULL)) /* "BSIC" */ + if (!find_chunk_be(sf, get_id32be("BSIC"),first_offset,1, &chunk_offset,NULL)) goto fail; /* 0x00/0x04: probably volume/pan/etc floats (1.0) */ /* 0x08: null? */ - loop_flag = read_8bit(chunk_offset+0x0c,sf_head); - loop_start = read_32bitBE(chunk_offset+0x10,sf_head); - loop_end = read_32bitBE(chunk_offset+0x14,sf_head); + loop_flag = read_8bit(chunk_offset+0x0c,sf); + loop_start = read_32bitBE(chunk_offset+0x10,sf); + loop_end = read_32bitBE(chunk_offset+0x14,sf); - //if (!find_chunk_be(streamHeader, 0x4E414D45,first_offset,1, &chunk_offset,NULL)) /* "NAME" */ + //if (!find_chunk_be(streamHeader, get_id32be("NAME"),first_offset,1, &chunk_offset,NULL)) // goto fail; /* 0x00: name_size */ /* 0x04+: name (same as filename) */ @@ -65,7 +65,7 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channel_count,loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_GSP_GSB; + vgmstream->meta_type = meta_GSND; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; @@ -80,16 +80,16 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_blocked_gsb; - if (!find_chunk_be(sf_head, 0x47434558,first_offset,1, &chunk_offset,NULL)) /* "GCEX" */ + if (!find_chunk_be(sf, get_id32be("GCEX"),first_offset,1, &chunk_offset,NULL)) goto fail; //vgmstream->current_block_size = read_32bitBE(chunk_offset+0x00,streamHeader); - block_header_size = read_32bitBE(chunk_offset+0x04,sf_head); - num_blocks = read_32bitBE(chunk_offset+0x08,sf_head); + block_header_size = read_32bitBE(chunk_offset+0x04,sf); + num_blocks = read_32bitBE(chunk_offset+0x08,sf); vgmstream->num_samples = (data_size - block_header_size * num_blocks) / 8 / vgmstream->channels * 14; /* 0x0c+: unk */ - dsp_read_coefs_be(vgmstream, sf_head, chunk_offset+0x18, 0x30); + dsp_read_coefs_be(vgmstream, sf, chunk_offset+0x18, 0x30); break; } #ifdef VGM_USE_FFMPEG @@ -101,7 +101,7 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay; /* fix num_samples as header samples seem to be modified to match altered (49999/48001) sample rates somehow */ - vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); + vgmstream->codec_data = init_ffmpeg_atrac3_raw(sb, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; @@ -112,18 +112,18 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { break; } - case 0x09: { /* XMA2 [Quantum Theory (PS3)] */ - if (!find_chunk_be(sf_head, 0x584D4558,first_offset,1, &chunk_offset,NULL)) /* "XMEX" */ + case 0x09: { /* XMA2 [Quantum Theory (X360)] */ + if (!find_chunk_be(sf, get_id32be("XMEX"),first_offset,1, &chunk_offset,NULL)) /* "XMEX" */ goto fail; /* 0x00: fmt0x166 header (BE) */ /* 0x34: seek table */ - vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf_head, sf, start_offset, data_size, chunk_offset, 0x34); + vgmstream->codec_data = init_ffmpeg_xma_chunk_split(sf, sb, start_offset, data_size, chunk_offset, 0x34); if (!vgmstream->codec_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_none; - xma_fix_raw_samples(vgmstream, sf, start_offset,data_size, 0, 0,0); /* samples are ok */ + xma_fix_raw_samples(vgmstream, sb, start_offset,data_size, 0, 0,0); /* samples are ok */ break; } #endif @@ -132,13 +132,13 @@ VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) { } - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + if (!vgmstream_open_stream(vgmstream, sb, start_offset)) goto fail; - close_streamfile(sf_head); + close_streamfile(sb); return vgmstream; fail: - close_streamfile(sf_head); + close_streamfile(sb); close_vgmstream(vgmstream); return NULL; } diff --git a/src/meta/meta.h b/src/meta/meta.h index 6cf2e072c..6d68c8dab 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -332,7 +332,7 @@ VGMSTREAM * init_vgmstream_ish_isd(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ydsp(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_gsp_gsb(STREAMFILE * streamFile); +VGMSTREAM* init_vgmstream_gsnd(STREAMFILE* sf); VGMSTREAM * init_vgmstream_ngc_ssm(STREAMFILE * streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index aec48ee45..fc92246b7 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -145,7 +145,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_gca, init_vgmstream_spt_spd, init_vgmstream_ish_isd, - init_vgmstream_gsp_gsb, + init_vgmstream_gsnd, init_vgmstream_ydsp, init_vgmstream_ngc_ssm, init_vgmstream_ps2_joe, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 926935915..56cb7e462 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -358,7 +358,7 @@ typedef enum { meta_IDSP_IE, /* Defencer (GC) */ meta_SPT_SPD, /* Various (SPT+SPT DSP) */ meta_ISH_ISD, /* Various (ISH+ISD DSP) */ - meta_GSP_GSB, /* Tecmo games (Super Swing Golf 1 & 2, Quamtum Theory) */ + meta_GSND, meta_YDSP, /* WWE Day of Reckoning */ meta_FFCC_STR, /* Final Fantasy: Crystal Chronicles */ meta_UBI_JADE, /* Beyond Good & Evil, Rayman Raving Rabbids */ @@ -581,11 +581,11 @@ typedef enum { meta_DSP_MCADPCM, /* Skyrim (Switch) */ meta_UBI_LYN, /* Ubisoft LyN engine [The Adventures of Tintin (multi)] */ meta_MSB_MSH, /* sfx companion of MIH+MIB */ - meta_TXTP, /* generic text playlist */ + meta_TXTP, meta_SMC_SMH, /* Wangan Midnight (System 246) */ meta_PPST, /* PPST [Parappa the Rapper (PSP)] */ meta_SPS_N1, - meta_UBI_BAO, /* Ubisoft BAO */ + meta_UBI_BAO, meta_DSP_SWITCH_AUDIO, /* Gal Gun 2 (Switch) */ meta_H4M, /* Hudson HVQM4 video [Resident Evil 0 (GC), Tales of Symphonia (GC)] */ meta_ASF, /* Argonaut ASF [Croc 2 (PC)] */ From 13bfa15e2f8e8d0f5e8a1d2d683816cfce02877c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 11:35:34 +0200 Subject: [PATCH 090/141] cleanup: wad matx - Remove fake extension .matx (use TXTH) - Remove fake format .wad (use TXTH) --- src/base/render.c | 1 - src/formats.c | 4 --- src/layout/blocked.c | 3 -- src/layout/blocked_matx.c | 18 ---------- src/layout/layout.h | 1 - src/meta/meta.h | 4 --- src/meta/ps2_wad.c | 71 --------------------------------------- src/meta/xbox_ims.c | 61 --------------------------------- src/vgmstream.c | 2 -- src/vgmstream_types.h | 3 -- 10 files changed, 168 deletions(-) delete mode 100644 src/layout/blocked_matx.c delete mode 100644 src/meta/ps2_wad.c delete mode 100644 src/meta/xbox_ims.c diff --git a/src/base/render.c b/src/base/render.c index a7cc29de7..d8a1b07fd 100644 --- a/src/base/render.c +++ b/src/base/render.c @@ -274,7 +274,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) { case layout_blocked_wsi: case layout_blocked_str_snds: case layout_blocked_ws_aud: - case layout_blocked_matx: case layout_blocked_dec: case layout_blocked_vs: case layout_blocked_mul: diff --git a/src/formats.c b/src/formats.c index 76232fe62..66594ba5b 100644 --- a/src/formats.c +++ b/src/formats.c @@ -325,7 +325,6 @@ static const char* extension_list[] = { "mab", "mad", "map", - "matx", "mc3", "mca", "mcadpcm", @@ -930,7 +929,6 @@ static const layout_info layout_info_list[] = { {layout_blocked_xvas, "blocked (.xvas)"}, {layout_blocked_str_snds, "blocked (.str SNDS)"}, {layout_blocked_ws_aud, "blocked (Westwood Studios .aud)"}, - {layout_blocked_matx, "blocked (Matrix .matx)"}, {layout_blocked_dec, "blocked (DEC)"}, {layout_blocked_vs, "blocked (Melbourne House VS)"}, {layout_blocked_mul, "blocked (MUL)"}, @@ -1077,7 +1075,6 @@ static const meta_info meta_info_list[] = { {meta_SDT, "High Voltage .sdt header"}, {meta_NGC_TYDSP, ".tydsp Header"}, {meta_WVS, "Swingin' Ape .WVS header"}, - {meta_XBOX_MATX, "assumed Matrix file by .matx extension"}, {meta_DEC, "Falcom DEC RIFF header"}, {meta_VS, "Melbourne House .VS header"}, {meta_DC_STR, "Sega Stream Asset Builder header"}, @@ -1181,7 +1178,6 @@ static const meta_info meta_info_list[] = { {meta_DSP_STR_IG, "Infogrames .DSP header"}, {meta_EA_SWVR, "Electronic Arts SWVR header"}, {meta_PS2_B1S, "B1S header"}, - {meta_PS2_WAD, "WAD header"}, {meta_DSP_XIII, "XIII dsp header"}, {meta_DSP_CABELAS, "Cabelas games .DSP header"}, {meta_PS2_ADM, "Dragon Quest V .ADM raw header"}, diff --git a/src/layout/blocked.c b/src/layout/blocked.c index bb7f65648..637502ee5 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -123,9 +123,6 @@ void block_update(off_t block_offset, VGMSTREAM* vgmstream) { case layout_blocked_ws_aud: block_update_ws_aud(block_offset,vgmstream); break; - case layout_blocked_matx: - block_update_matx(block_offset,vgmstream); - break; case layout_blocked_dec: block_update_dec(block_offset,vgmstream); break; diff --git a/src/layout/blocked_matx.c b/src/layout/blocked_matx.c deleted file mode 100644 index e69a05038..000000000 --- a/src/layout/blocked_matx.c +++ /dev/null @@ -1,18 +0,0 @@ -#include "layout.h" -#include "../vgmstream.h" - -/* set up for the block at the given offset */ -void block_update_matx(off_t block_offset, VGMSTREAM * vgmstream) { - int i; - - vgmstream->current_block_offset = block_offset; - vgmstream->current_block_size = read_32bitLE( - vgmstream->current_block_offset, - vgmstream->ch[0].streamfile); - vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 8; - vgmstream->current_block_size/=vgmstream->channels; - - for (i=0;ichannels;i++) { - vgmstream->ch[i].offset = vgmstream->current_block_offset + 8; - } -} diff --git a/src/layout/layout.h b/src/layout/layout.h index 4f3e64d6f..11a7d9aa5 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -20,7 +20,6 @@ void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream); void block_update_wsi(off_t block_offset, VGMSTREAM* vgmstream); void block_update_str_snds(off_t block_offset, VGMSTREAM* vgmstream); void block_update_ws_aud(off_t block_offset, VGMSTREAM* vgmstream); -void block_update_matx(off_t block_offset, VGMSTREAM* vgmstream); void block_update_dec(off_t block_offset, VGMSTREAM* vgmstream); void block_update_vs(off_t block_offset, VGMSTREAM* vgmstream); void block_update_mul(off_t block_offset, VGMSTREAM* vgmstream); diff --git a/src/meta/meta.h b/src/meta/meta.h index 6d68c8dab..5bf3da649 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -265,8 +265,6 @@ VGMSTREAM* init_vgmstream_wvs_ngc(STREAMFILE* sf); VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile); -VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile); - VGMSTREAM * init_vgmstream_dec(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_vs(STREAMFILE *streamFile); @@ -455,8 +453,6 @@ VGMSTREAM * init_vgmstream_ea_swvr(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps2_b1s(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE* streamFile); - VGMSTREAM * init_vgmstream_ps2_adm(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_lpcm_shade(STREAMFILE* sf); diff --git a/src/meta/ps2_wad.c b/src/meta/ps2_wad.c deleted file mode 100644 index 9242f4cb7..000000000 --- a/src/meta/ps2_wad.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* WAD (from The golden Compass) */ -VGMSTREAM * init_vgmstream_ps2_wad(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - int loop_flag = 0; - int channel_count; - off_t start_offset; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("wad",filename_extension(filename))) goto fail; - - /* check header */ - if ((read_32bitLE(0x00,streamFile)+0x40) != get_streamfile_size(streamFile)) - goto fail; - - loop_flag = 0; - channel_count = (uint16_t) read_16bitLE(0x4,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = 0x40; - vgmstream->channels = channel_count; - vgmstream->sample_rate = (uint16_t) read_16bitLE(0x6,streamFile);; - vgmstream->coding_type = coding_PSX; - vgmstream->num_samples = read_32bitLE(0x0,streamFile)/channel_count/16*28; - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/channel_count/16*28; - } - - if (channel_count == 1) - { - vgmstream->layout_type = layout_none; - } - else - { - goto fail; - } - - vgmstream->meta_type = meta_PS2_WAD; - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/meta/xbox_ims.c b/src/meta/xbox_ims.c deleted file mode 100644 index 1c6f60ad9..000000000 --- a/src/meta/xbox_ims.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "meta.h" -#include "../util.h" -#include "../layout/layout.h" - -/* matx - - MATX (found in Matrix) -*/ - -VGMSTREAM * init_vgmstream_xbox_matx(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - - int loop_flag=0; - int channel_count; - int i; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("matx",filename_extension(filename))) goto fail; - - loop_flag = 0; - channel_count=read_16bitLE(0x4,streamFile); - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - vgmstream->channels = channel_count; - vgmstream->sample_rate = read_16bitLE(0x06,streamFile) & 0xffff; - - vgmstream->coding_type = coding_XBOX_IMA; - vgmstream->layout_type = layout_blocked_matx; - vgmstream->meta_type = meta_XBOX_MATX; - - /* open the file for reading by each channel */ - { - for (i=0;ich[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!vgmstream->ch[i].streamfile) goto fail; - } - } - - /* Calc num_samples */ - block_update_matx(0,vgmstream); - vgmstream->num_samples=0; - - do { - vgmstream->num_samples += vgmstream->current_block_size/36*64; - block_update_matx(vgmstream->next_block_offset,vgmstream); - } while (vgmstream->next_block_offset Date: Sat, 8 Jul 2023 11:54:56 +0200 Subject: [PATCH 091/141] doc --- src/formats.c | 36 ++++++++++++++++++------------------ src/meta/ps2_sl3.c | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/formats.c b/src/formats.c index 66594ba5b..6d3bb9980 100644 --- a/src/formats.c +++ b/src/formats.c @@ -962,16 +962,16 @@ static const meta_info meta_info_list[] = { {meta_SILENCE, "Silence"}, {meta_RSTM, "Nintendo RSTM header"}, {meta_STRM, "Nintendo STRM header"}, - {meta_ADX_03, "CRI ADX header type 03"}, - {meta_ADX_04, "CRI ADX header type 04"}, - {meta_ADX_05, "CRI ADX header type 05"}, + {meta_ADX_03, "CRI ADX header (type 03)"}, + {meta_ADX_04, "CRI ADX header (type 04)"}, + {meta_ADX_05, "CRI ADX header (type 05)"}, {meta_AIX, "CRI AIX header"}, {meta_AAX, "CRI AAX header"}, {meta_UTF_DSP, "CRI ADPCM_WII header"}, {meta_AGSC, "Retro Studios AGSC header"}, {meta_CSMP, "Retro Studios CSMP header"}, {meta_RFRM, "Retro Studios RFRM header"}, - {meta_DTK, "Nintendo DTK raw header"}, + {meta_DTK, "Nintendo .DTK raw header"}, {meta_RSF, "Retro Studios .RSF raw header"}, {meta_AFC, "Nintendo .AFC header"}, {meta_AST, "Nintendo .AST header"}, @@ -1012,7 +1012,7 @@ static const meta_info meta_info_list[] = { {meta_PWB, "Double Fine WB header"}, {meta_RAW_WAVM, "Xbox .wavm raw header"}, {meta_DSP_STR, "Cauldron .STR header"}, - {meta_EA_SCHL, "Electronic Arts SCHl header (variable)"}, + {meta_EA_SCHL, "Electronic Arts SCHl header"}, {meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"}, {meta_CAF, "tri-Crescendo CAF Header"}, {meta_VPK, "SCE America VPK Header"}, @@ -1028,7 +1028,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_IVB, "IVB/BVII header"}, {meta_SVS, "Square SVS header"}, {meta_RIFF_WAVE, "RIFF WAVE header"}, - {meta_RIFF_WAVE_POS, "RIFF WAVE header and .pos for looping"}, + {meta_RIFF_WAVE_POS, "RIFF WAVE header (.pos looping)"}, {meta_NWA, "VisualArt's NWA header"}, {meta_NWA_NWAINFOINI, "VisualArt's NWA header (NWAINFO.INI looping)"}, {meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"}, @@ -1049,33 +1049,33 @@ static const meta_info meta_info_list[] = { {meta_PS2_XA30, "Reflections XA30 PS2 header"}, {meta_MUSC, "Krome MUSC header"}, {meta_MUSX, "Eurocom MUSX header"}, - {meta_FILP, "Bio Hazard - Gun Survivor FILp Header"}, + {meta_FILP, "cavia FILp Header"}, {meta_IKM, "MiCROViSiON IKM header"}, {meta_STER, "ALCHEMY STER header"}, - {meta_SAT_DVI, "Konami KCEN DVI. header"}, - {meta_DC_KCEY, "Konami KCEY KCEYCOMP header"}, - {meta_BG00, "Falcom BG00 Header"}, + {meta_SAT_DVI, "Konami DVI. header"}, + {meta_DC_KCEY, "Konami KCEY header"}, + {meta_BG00, "Cave BG00 header"}, {meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"}, {meta_ACM, "InterPlay ACM Header"}, {meta_MUS_ACM, "InterPlay MUS ACM header"}, {meta_PS2_KCES, "Konami KCES Header"}, {meta_HXD, "Tecmo HXD Header"}, {meta_VSV, "Square Enix .vsv Header"}, - {meta_RIFF_WAVE_labl, "RIFF WAVE header with loop markers"}, - {meta_RIFF_WAVE_smpl, "RIFF WAVE header with sample looping info"}, - {meta_RIFF_WAVE_wsmp, "RIFF WAVE header with wsmp looping info"}, + {meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"}, + {meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"}, + {meta_RIFF_WAVE_wsmp, "RIFF WAVE header (wsmp looping)"}, {meta_RIFX_WAVE, "RIFX WAVE header"}, - {meta_RIFX_WAVE_smpl, "RIFX WAVE header with sample looping info"}, - {meta_XNB, "Microsoft XNA Game Studio 4.0 header"}, + {meta_RIFX_WAVE_smpl, "RIFX WAVE header (smpl looping)"}, + {meta_XNB, "Microsoft XNA Game Studio header"}, {meta_SCD_PCM, "Lunar: Eternal Blue .PCM header"}, - {meta_PS2_PCM, "Konami KCEJ East .PCM header"}, + {meta_PS2_PCM, "Konami .PCM header"}, {meta_PS2_RKV, "Legacy of Kain - Blood Omen 2 RKV PS2 header"}, {meta_PS2_VAS, "Konami .VAS header"}, {meta_LP_AP_LEP, "Konami LP/AP/LEP header"}, {meta_SDT, "High Voltage .sdt header"}, {meta_NGC_TYDSP, ".tydsp Header"}, {meta_WVS, "Swingin' Ape .WVS header"}, - {meta_DEC, "Falcom DEC RIFF header"}, + {meta_DEC, "Falcom .DEC RIFF header"}, {meta_VS, "Melbourne House .VS header"}, {meta_DC_STR, "Sega Stream Asset Builder header"}, {meta_DC_STR_V2, "variant of Sega Stream Asset Builder header"}, @@ -1120,7 +1120,7 @@ static const meta_info meta_info_list[] = { {meta_PS2_P2BT, "Pop'n'Music 7 Header"}, {meta_PS2_GBTS, "Pop'n'Music 9 Header"}, {meta_NGC_DSP_IADP, "IADP Header"}, - {meta_RIFF_WAVE_MWV, "RIFF WAVE header with .mwv flavoring"}, + {meta_RIFF_WAVE_MWV, "RIFF WAVE header (ctrl looping)"}, {meta_FFCC_STR, "Final Fantasy: Crystal Chronicles STR header"}, {meta_SAT_BAKA, "Konami BAKA header"}, {meta_SWAV, "Nintendo SWAV header"}, diff --git a/src/meta/ps2_sl3.c b/src/meta/ps2_sl3.c index 8dc820466..a712c0dfd 100644 --- a/src/meta/ps2_sl3.c +++ b/src/meta/ps2_sl3.c @@ -1,7 +1,7 @@ #include "meta.h" #include "../coding/coding.h" -/* SL3 - Winky Soft / Atari Melbourne House games [Test Drive Unlimited (PS2), Transformers 2003/2004 (PS2)] */ +/* SL3 - Sirens Sound Library (Winky Soft / Atari Melbourne House) games [Test Drive Unlimited (PS2), Transformers 2003/2004 (PS2)] */ VGMSTREAM* init_vgmstream_sl3(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset; From a752297d77e2dc5efa0140557ec26909b96dd6bf Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 13:43:29 +0200 Subject: [PATCH 092/141] cleanup: renames --- doc/FORMATS.md | 88 +++++++++++++---------------- src/formats.c | 2 +- src/libvgmstream.vcxproj | 17 +++--- src/libvgmstream.vcxproj.filters | 49 +++++++--------- src/meta/{ps2_bg00.c => bg00.c} | 0 src/meta/{wii_bns.c => bns.c} | 10 ++-- src/meta/{ps2_filp.c => filp.c} | 0 src/meta/{ps2_hgc1.c => hgc1.c} | 0 src/meta/meta.h | 2 +- src/meta/{wii_mus.c => mus_krone.c} | 0 src/meta/{ps2_sl3.c => sl3.c} | 0 src/meta/{ps2_wb.c => wb.c} | 0 src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 14 files changed, 76 insertions(+), 96 deletions(-) rename src/meta/{ps2_bg00.c => bg00.c} (100%) rename src/meta/{wii_bns.c => bns.c} (97%) rename src/meta/{ps2_filp.c => filp.c} (100%) rename src/meta/{ps2_hgc1.c => hgc1.c} (100%) rename src/meta/{wii_mus.c => mus_krone.c} (100%) rename src/meta/{ps2_sl3.c => sl3.c} (100%) rename src/meta/{ps2_wb.c => wb.c} (100%) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 28cc1d8d3..6a95cf82a 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -25,9 +25,9 @@ different internally (encrypted, different versions, etc) and not always can be ### List - **adx.c** - - CRI ADX header type 03 [*ADX_03*] - - CRI ADX header type 04 [*ADX_04*] - - CRI ADX header type 05 [*ADX_05*] + - CRI ADX header (type 03) [*ADX_03*] + - CRI ADX header (type 04) [*ADX_04*] + - CRI ADX header (type 05) [*ADX_05*] - *adx* - Subfiles: *adx_subkey* - *adx_subkey*: `.adx .adp + .(external)` @@ -198,7 +198,7 @@ different internally (encrypted, different versions, etc) and not always can be - Codecs: NGC_DSP - **ea_schl.c** - Electronic Arts BNK header [*EA_BNK*] - - Electronic Arts SCHl header (variable) [*EA_SCHL*] + - Electronic Arts SCHl header [*EA_SCHL*] - *ea_schl*: `.asf .lasf .str .chk .eam .exa .sng .aud .sx .xa .strm .stm .hab .xsf .gsf .(extensionless)` - *ea_schl_video*: `.uv .dct .mad .wve .vp6` - *ea_bnk*: `.bnk .sdt .hdt .ldt .abk .ast` @@ -239,8 +239,8 @@ different internally (encrypted, different versions, etc) and not always can be - *wsi*: `.wsi` - Codecs: NGC_DSP - **aifc.c** - - Apple AIFF-C (Audio Interchange File Format) header [*AIFC*] - - Apple AIFF (Audio Interchange File Format) header [*AIFF*] + - Apple AIFF-C header [*AIFC*] + - Apple AIFF header [*AIFF*] - *aifc*: `.aif .laif .wav .lwav .(extensionless) .aifc .laifc .afc .cbd2 .bgm .fda .n64 .xa .aiff .laiff .acm .adp .ai .pcm` - Codecs: SDX2 CBD2 DVI_IMA_int APPLE_IMA4 RELIC VADPCM PCM8 PCM16BE XA - **str_snds.c** @@ -265,12 +265,12 @@ different internally (encrypted, different versions, etc) and not always can be - Codecs: PSX - **riff.c** - RIFF WAVE header [*RIFF_WAVE*] - - RIFF WAVE header with loop markers [*RIFF_WAVE_labl*] - - RIFF WAVE header with sample looping info [*RIFF_WAVE_smpl*] - - RIFF WAVE header with wsmp looping info [*RIFF_WAVE_wsmp*] - - RIFF WAVE header with .mwv flavoring [*RIFF_WAVE_MWV*] + - RIFF WAVE header (labl looping) [*RIFF_WAVE_labl*] + - RIFF WAVE header (smpl looping) [*RIFF_WAVE_smpl*] + - RIFF WAVE header (wsmp looping) [*RIFF_WAVE_wsmp*] + - RIFF WAVE header (ctrl looping) [*RIFF_WAVE_MWV*] - RIFX WAVE header [*RIFX_WAVE*] - - RIFX WAVE header with sample looping info [*RIFX_WAVE_smpl*] + - RIFX WAVE header (smpl looping) [*RIFX_WAVE_smpl*] - *riff*: `.wav .lwav .xwav .mwv .da .dax .cd .med .snd .adx .adp .xss .xsew .adpcm .adw .wd .(extensionless) .sbv .wvx .str .at3 .rws .aud .at9 .ckd .saf .ima .nsa .pcm .xvag .ogg .logg .p1d .xms .mus .dat .ldat` - *rifx*: `.wav .lwav` - Codecs: AICA_int PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int @@ -290,13 +290,13 @@ different internally (encrypted, different versions, etc) and not always can be - Dino Crisis 3 XSS File [*XSS*] - *xss*: `.xss` - Codecs: PCM16LE -- **ps2_sl3.c** +- **sl3.c** - Atari Melbourne House SL3 header [*SL3*] - - *sl3*: `.ms .sl3` + - *sl3*: `.ms` - Codecs: PSX -- **ps2_hgc1.c** - - Knights of the Temple 2 hgC1 Header [*HGC1*] - - *hgc1*: `.hgc1` +- **hgc1.c** + - Cauldron HGC1 header [*HGC1*] + - *hgc1*: `.str` - Codecs: PSX - **aus.c** - Capcom AUS Header [*AUS*] @@ -340,9 +340,9 @@ different internally (encrypted, different versions, etc) and not always can be - Eurocom MUSX header [*MUSX*] - *musx*: `.sfx .musx` - Codecs: PSX DAT4_IMA DVI_IMA_int XBOX_IMA NGC_DSP PCM16BE PCM16LE -- **ps2_filp.c** - - Bio Hazard - Gun Survivor FILp Header [*FILP*] - - *filp*: `.filp` +- **filp.c** + - cavia FILp Header [*FILP*] + - *filp*: `.fil` - Codecs: PSX - **ikm.c** - MiCROViSiON IKM header [*IKM*] @@ -356,16 +356,16 @@ different internally (encrypted, different versions, etc) and not always can be - ALCHEMY STER header [*STER*] - *ster*: `.ster .sfs` - Codecs: PSX -- **ps2_bg00.c** - - Falcom BG00 Header [*BG00*] +- **bg00.c** + - Cave BG00 header [*BG00*] - *bg00*: `.bg00` - Codecs: PSX - **sat_dvi.c** - - Konami KCEN DVI. header [*SAT_DVI*] + - Konami DVI. header [*SAT_DVI*] - *sat_dvi*: `.pcm .dvi` - Codecs: DVI_IMA_int - **dc_kcey.c** - - Konami KCEY KCEYCOMP header [*DC_KCEY*] + - Konami KCEY header [*DC_KCEY*] - *dc_kcey*: `.pcm .kcey` - Codecs: DVI_IMA - **rstm_rockstar.c** @@ -393,7 +393,7 @@ different internally (encrypted, different versions, etc) and not always can be - *vsv*: `.vsv .psh` - Codecs: PSX - **ps2_pcm.c** - - Konami KCEJ East .PCM header [*PS2_PCM*] + - Konami .PCM header [*PS2_PCM*] - *ps2_pcm*: `.pcm` - Codecs: PCM16LE - **rkv.c** @@ -429,12 +429,8 @@ different internally (encrypted, different versions, etc) and not always can be - *wvs_xbox*: `.wvs` - *wvs_ngc*: `.wvs` - Codecs: XBOX_IMA NGC_DSP -- **xbox_ims.c** - - assumed Matrix file by .matx extension [*XBOX_MATX*] - - *xbox_matx*: `.matx` - - Codecs: XBOX_IMA - **dec.c** - - Falcom DEC RIFF header [*DEC*] + - Falcom .DEC RIFF header [*DEC*] - *dec*: `.dec .de2 + .(external)` - Codecs: MSADPCM - **vs.c** @@ -464,7 +460,7 @@ different internally (encrypted, different versions, etc) and not always can be - *dc_idvi*: `.dvi .idvi` - Codecs: DVI_IMA_int - **ps2_rnd.c** - - Knights of the Temple 2 hgC1 Header [*HGC1*] + - Cauldron HGC1 header [*HGC1*] - *ps2_rnd*: `.rnd` - Codecs: PSX - **kraw.c** @@ -504,9 +500,9 @@ different internally (encrypted, different versions, etc) and not always can be - *ngc_pdt*: `.pdt` - *ngc_pdt_split*: `.pdt` - Codecs: NGC_DSP -- **wii_mus.c** - - mus header [*DSP_WII_MUS*] - - *wii_mus*: `.mus` +- **mus_krone.c** + - Krone .MUS header [*MUS_KRONE*] + - *mus_krone*: `.mus` - Codecs: NGC_DSP - **dc_asd.c** - ASD Header [*DC_ASD*] @@ -563,8 +559,8 @@ different internally (encrypted, different versions, etc) and not always can be - *ish_isd*: `.isd + .ish` - Codecs: NGC_DSP - **gsp_gsb.c** - - Tecmo GSP+GSB Header [*GSP_GSB*] - - *gsp_gsb*: `.gsb + .gsp` + - Tecmo GSND Header [*GSND*] + - *gsnd*: `.gsp + .gsb` - Codecs: NGC_DSP ATRAC3 XMA - **ydsp.c** - Yuke's YDSP Header [*YDSP*] @@ -730,9 +726,9 @@ different internally (encrypted, different versions, etc) and not always can be - Sensaura SAB header [*SAB*] - *sab*: `.sab + .sob` - Codecs: PCM16LE PSX XBOX_IMA -- **wii_bns.c** - - Nintendo BNS header [*WII_BNS*] - - *wii_bns*: `.bin .lbin .bns` +- **bns.c** + - Nintendo BNS header [*BNS*] + - *bns*: `.bin .lbin .bns` - Codecs: NGC_DSP - **pona.c** - Policenauts BGM header [*PONA_3DO*] @@ -771,9 +767,9 @@ different internally (encrypted, different versions, etc) and not always can be - Konami DSP header [*NGC_DSP_KONAMI*] - *ngc_dsp_konami*: `.dsp` - Codecs: NGC_DSP -- **ps2_wb.c** - - Shooting Love. ~TRIZEAL~ WB header [*PS2_WB*] - - *ps2_wb*: `.wb` +- **wb.c** + - Triangle Service .WB header [*WB*] + - *wb*: `.wb` - Codecs: PCM16LE - **bnsf.c** - Namco Bandai BNSF header [*BNSF*] @@ -811,10 +807,6 @@ different internally (encrypted, different versions, etc) and not always can be - B1S header [*PS2_B1S*] - *ps2_b1s*: `.b1s` - Codecs: PSX -- **ps2_wad.c** - - WAD header [*PS2_WAD*] - - *ps2_wad*: `.wad` - - Codecs: PSX - **lpcm_shade.c** - Shade LPCM header [*LPCM_SHADE*] - *lpcm_shade*: `.w .lpcm` @@ -952,7 +944,7 @@ different internally (encrypted, different versions, etc) and not always can be - *ps2_2pfs*: `.sap .2pfs` - Codecs: PSX - **xnb.c** - - Microsoft XNA Game Studio 4.0 header [*XNB*] + - Microsoft XNA Game Studio header [*XNB*] - *xnb*: `.xnb + .(external)` - Subfiles: *ogg_vorbis riff opus_std ffmpeg* - Codecs: PCM8_U PCM16LE MSADPCM MS_IMA XMA2 NGC_DSP @@ -1830,7 +1822,7 @@ different internally (encrypted, different versions, etc) and not always can be - *tgc*: `.4` - Codecs: TGC - **pos.c** - - RIFF WAVE header and .pos for looping [*RIFF_WAVE_POS*] + - RIFF WAVE header (.pos looping) [*RIFF_WAVE_POS*] - *pos*: `.pos + .wav` - Subfiles: *riff* - **sli.c** @@ -1838,7 +1830,7 @@ different internally (encrypted, different versions, etc) and not always can be - *sli_loops*: `.sli + .(external)` - Subfiles: *ogg_opus ogg_vorbis riff* - **ngc_adpdtk.c** - - Nintendo DTK raw header [*DTK*] + - Nintendo .DTK raw header [*DTK*] - *dtk*: `.dtk .adp .trk .wav .lwav` - Codecs: NGC_DTK - **mpeg.c** diff --git a/src/formats.c b/src/formats.c index 6d3bb9980..c4f0d24b0 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1150,7 +1150,7 @@ static const meta_info meta_info_list[] = { {meta_SAB, "Sensaura SAB header"}, {meta_MAXIS_XA, "Maxis XA Header"}, {meta_EXAKT_SC, "assumed Activision / EXAKT SC by extension"}, - {meta_WII_BNS, "Nintendo BNS header"}, + {meta_BNS, "Nintendo BNS header"}, {meta_WII_WAS, "Sumo Digital iSWS header"}, {meta_XBOX_HLWAV, "Half-Life 2 .WAV header"}, {meta_MYSPD, "Punchers Impact .MYSPD header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 35a59e1e1..331601904 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -298,7 +298,6 @@ - @@ -370,6 +369,7 @@ + @@ -377,6 +377,7 @@ + @@ -423,6 +424,7 @@ + @@ -441,6 +443,7 @@ + @@ -499,6 +502,7 @@ + @@ -549,12 +553,9 @@ - - - @@ -565,7 +566,6 @@ - @@ -574,8 +574,6 @@ - - @@ -622,6 +620,7 @@ + @@ -689,9 +688,8 @@ + - - @@ -709,7 +707,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 9cf33c329..da3dfccbb 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -715,9 +715,6 @@ layout\Source Files - - layout\Source Files - layout\Source Files @@ -931,6 +928,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -952,6 +952,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1090,6 +1093,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1144,6 +1150,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1318,6 +1327,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1468,24 +1480,15 @@ meta\Source Files - - meta\Source Files - meta\Source Files - - meta\Source Files - meta\Source Files meta\Source Files - - meta\Source Files - meta\Source Files @@ -1516,9 +1519,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1543,12 +1543,6 @@ meta\Source Files - - meta\Source Files - - - meta\Source Files - meta\Source Files @@ -1687,6 +1681,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1888,13 +1885,10 @@ meta\Source Files - - meta\Source Files - - + meta\Source Files - + meta\Source Files @@ -1948,9 +1942,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/ps2_bg00.c b/src/meta/bg00.c similarity index 100% rename from src/meta/ps2_bg00.c rename to src/meta/bg00.c diff --git a/src/meta/wii_bns.c b/src/meta/bns.c similarity index 97% rename from src/meta/wii_bns.c rename to src/meta/bns.c index 12fc35c3c..c184f59ee 100644 --- a/src/meta/wii_bns.c +++ b/src/meta/bns.c @@ -3,7 +3,7 @@ #include "../util.h" /* BNS - Wii "Banner Sound" disc jingle */ -VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) { +VGMSTREAM* init_vgmstream_bns(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t bns_offset; uint32_t info_offset = 0, data_offset = 0; @@ -15,7 +15,7 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) { /* .bin: actual extension * .bns: header id */ if (!check_extensions(sf, "bin,lbin,bns")) - goto fail; + return NULL; bns_offset = 0; if (is_id32be(bns_offset + 0x40, sf, "IMET")) { @@ -32,9 +32,9 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) { } if (!is_id32be(bns_offset + 0x00,sf, "BNS ")) - goto fail; + return NULL; if (read_u32be(bns_offset + 0x04,sf) != 0xFEFF0100u) - goto fail; + return NULL; /* find chunks */ { @@ -110,7 +110,7 @@ VGMSTREAM* init_vgmstream_wii_bns(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_WII_BNS; + vgmstream->meta_type = meta_BNS; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = sample_count; vgmstream->loop_start_sample = loop_start; diff --git a/src/meta/ps2_filp.c b/src/meta/filp.c similarity index 100% rename from src/meta/ps2_filp.c rename to src/meta/filp.c diff --git a/src/meta/ps2_hgc1.c b/src/meta/hgc1.c similarity index 100% rename from src/meta/ps2_hgc1.c rename to src/meta/hgc1.c diff --git a/src/meta/meta.h b/src/meta/meta.h index 5bf3da649..4f677693b 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -410,7 +410,7 @@ VGMSTREAM * init_vgmstream_sab(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_exakt_sc(STREAMFILE* streamFile); -VGMSTREAM * init_vgmstream_wii_bns(STREAMFILE* streamFile); +VGMSTREAM* init_vgmstream_bns(STREAMFILE* sf); VGMSTREAM * init_vgmstream_pona_3do(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_pona_psx(STREAMFILE* streamFile); diff --git a/src/meta/wii_mus.c b/src/meta/mus_krone.c similarity index 100% rename from src/meta/wii_mus.c rename to src/meta/mus_krone.c diff --git a/src/meta/ps2_sl3.c b/src/meta/sl3.c similarity index 100% rename from src/meta/ps2_sl3.c rename to src/meta/sl3.c diff --git a/src/meta/ps2_wb.c b/src/meta/wb.c similarity index 100% rename from src/meta/ps2_wb.c rename to src/meta/wb.c diff --git a/src/vgmstream.c b/src/vgmstream.c index eca7072b9..a8ccf2815 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -188,7 +188,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_apple_caff, init_vgmstream_pc_mxst, init_vgmstream_sab, - init_vgmstream_wii_bns, + init_vgmstream_bns, init_vgmstream_wii_was, init_vgmstream_pona_3do, init_vgmstream_pona_psx, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index af2f75f67..e9ed5609e 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -274,7 +274,7 @@ typedef enum { meta_THP, /* THP movie files */ meta_SWAV, meta_NDS_RRDS, /* Ridge Racer DS */ - meta_WII_BNS, /* Wii BNS Banner Sound (similar to RSTM) */ + meta_BNS, meta_WIIU_BTSND, /* Wii U Boot Sound */ meta_ADX_03, /* CRI ADX "type 03" */ From 73410943a11ea0091e0f00edbdbaf8c6a4863fb8 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 15:28:47 +0200 Subject: [PATCH 093/141] Fix some .bnk [Fat Princess (PS3)] --- src/meta/bnk_sony.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index e0c7c7555..1c31519ea 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -472,8 +472,9 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* hack for PS3 files that use dual subsongs as stereo */ if (total_subsongs == 2 && stream_size * 2 == data_size) { channels = 2; - stream_size = stream_size*channels; + stream_size = stream_size * channels; total_subsongs = 1; + start_offset -= stream_offset; /* also channels may be inverted [Fat Princess (PS3)] */ } interleave = stream_size / channels; From 896936488df605102cca0f44aa6437ed530f2c81 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 17:50:08 +0200 Subject: [PATCH 094/141] Add Torus Games SqueakStream format --- src/base/decode.c | 2 +- src/formats.c | 1 + src/meta/meta.h | 2 + src/meta/rawi.c | 178 ++++++++++++++++++++++++++++++++++++++++++ src/vgmstream.c | 1 + src/vgmstream_types.h | 1 + 6 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 src/meta/rawi.c diff --git a/src/base/decode.c b/src/base/decode.c index f55c3275c..3ac6d89b9 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -423,7 +423,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { return 64; case coding_MS_IMA: case coding_REF_IMA: - return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;/* +1 from header sample */ + return ((vgmstream->frame_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;/* +1 from header sample */ case coding_MS_IMA_mono: return ((vgmstream->frame_size - 0x04) * 2) + 1; /* +1 from header sample */ case coding_RAD_IMA: diff --git a/src/formats.c b/src/formats.c index c4f0d24b0..4da1547b3 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1410,6 +1410,7 @@ static const meta_info meta_info_list[] = { {meta_BIGRP, "Inti Creates .BIGRP header"}, {meta_DIC1, "Codemasters DIC1 header"}, {meta_AWD, "RenderWare Audio Wave Dictionary header"}, + {meta_RAWI, "Torus SqueakStream RAWI header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/meta/meta.h b/src/meta/meta.h index 4f677693b..290543588 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -978,4 +978,6 @@ VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf); VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_rawi(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/rawi.c b/src/meta/rawi.c new file mode 100644 index 000000000..909585b9c --- /dev/null +++ b/src/meta/rawi.c @@ -0,0 +1,178 @@ +#include "meta.h" +#include "../layout/layout.h" +#include "../coding/coding.h" +#include "../util/endianness.h" + + +/* RAWI - from Torus games "SqueakStream" samples */ +VGMSTREAM* init_vgmstream_rawi(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + STREAMFILE* sn = NULL; + uint32_t start_offset, name_offset, extn_offset, interleave; + int channels, loop_flag, codec, sample_rate; + int32_t num_samples, loop_start, loop_end; + + + /* checks */ + bool big_endian = false; + if (is_id32be(0x00,sf, "RAWI")) + big_endian = false; + else if (is_id32be(0x00,sf, "IWAR")) + big_endian = true; /* Wii/PS3 */ + else + return NULL; + //TODO: handle first version used in Scooby Doo! First Frights (similar but larger fields and no header ID) + + /* (extensionless): no known extension */ + if (!check_extensions(sf,"")) + return NULL; + + read_s32_t read_s32 = big_endian ? read_s32be : read_s32le; + read_u32_t read_u32 = big_endian ? read_u32be : read_u32le; + + /* mini header with a string to the external asset; on Wii this string is also in a separate file */ + + if (read_u8(0x04,sf) != 0x01) /* version? */ + return NULL; + codec = read_u8(0x05,sf); + channels = read_u8(0x06,sf); + /* 0x07: null */ + num_samples = read_s32(0x08, sf); + sample_rate = read_s32(0x0c, sf); + loop_start = read_s32(0x10, sf); + loop_end = read_s32(0x14, sf); + //etbl_offset = read_u32(0x18, sf); + name_offset = read_u32(0x1c, sf); + /* 0x20: null, unknown values (sometimes floats) */ + interleave = read_u32(0x38, sf); + /* extra values, then DSP coefs if needed, then asset name (header size is not exact) */ + + extn_offset = (name_offset >> 24) & 0xFF; /* if name is external, sub-offset inside that file */ + name_offset = (name_offset >> 0) & 0xFFFFFF; /* if name is external, default/unused (same with etbl_offset) */ + + /* simplify as Wii defines both and uses a separate file, PS3 only defines extn and doesn't use separate */ + if (extn_offset && !name_offset) { + name_offset = extn_offset; + extn_offset = 0; + } + + loop_flag = loop_end > 0; + + start_offset = 0x00; + + /* open external asset */ + { + char asset_name[0x20]; /* "(8-byte crc).raw", "MU(6-byte crc).raw" */ + + + if (extn_offset) { + sn = open_streamfile_by_ext(sf, "asset"); /* unknown real extension, based on debug strings */ + if (!sn) { + vgm_logi("RAWI: external name '.asset' not found (put together)\n"); + goto fail; + } + + read_string(asset_name, sizeof(asset_name), extn_offset, sn); + } + else { + read_string(asset_name, sizeof(asset_name), name_offset, sf); + } + + /* try to open external asset in various ways, since this format is a bit hard to use */ + + /* "(asset name)": plain as found */ + if (!sb){ + sb = open_streamfile_by_filename(sf, asset_name); + } + + /* "sound/(asset name)": most common way to store files */ + char path_name[256]; + snprintf(path_name, sizeof(path_name), "sound/%s", asset_name); + if (!sb){ + sb = open_streamfile_by_filename(sf, path_name); + } + + /* "(header name).raw": for renamed files */ + if (!sb){ + sb = open_streamfile_by_ext(sf, "raw"); + } + + if (!sb) { + vgm_logi("RAWI: external file '%s' not found (put together)\n", asset_name); + goto fail; + } + } + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_RAWI; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end + 1; + + switch(codec) { + case 0x00: /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ + vgmstream->coding_type = coding_NGC_DSP; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + //vgmstream->interleave_last_block_size = ...; /* apparently padded */ + + /* etbl_offset defines N coef offset per channel (with external name, etbl_offset is ignored and offsets start at 0x00 in .asset instead) + * but in practice this seem fixed */ + dsp_read_coefs(vgmstream, sf, 0x40, 0x30, big_endian); + dsp_read_hist(vgmstream, sf, 0x40 + 0x24, 0x30, big_endian); + break; + + case 0x01: /* Falling Skies The Game (PC) */ + vgmstream->coding_type = coding_PCM16BE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; /* not 0x02 */ + + case 0x02: /* Falling Skies The Game (X360) */ + vgmstream->coding_type = coding_PCM16BE; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; /* not 0x02 */ + + /* etbl_offset may set offsets to RIFF fmts per channel) */ + break; + + case 0x03: /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + vgmstream->coding_type = coding_PSX; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + break; + + case 0x05: /* Scooby Doo and the Spooky Swamp (DS) */ + vgmstream->coding_type = coding_PCM8; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = interleave; + break; + + case 0x09: /* Turbo Super Stunt Squad (DS) */ + vgmstream->coding_type = coding_MS_IMA; + vgmstream->layout_type = layout_none; + //vgmstream->interleave_block_size = interleave; /* unused? (mono) */ + vgmstream->frame_size = 0x20; + break; + + default: + vgm_logi("RAWI: unknown codec %x (report)\n", codec); + goto fail; + } + + if (!vgmstream_open_stream(vgmstream, sb, start_offset)) + goto fail; + close_streamfile(sb); + close_streamfile(sn); + return vgmstream; +fail: + close_streamfile(sb); + close_streamfile(sn); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index a8ccf2815..1e1093fd4 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -521,6 +521,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_awd, init_vgmstream_rws_809, init_vgmstream_pwb, + init_vgmstream_rawi, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index e9ed5609e..508ad8e2f 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -698,6 +698,7 @@ typedef enum { meta_BIGRP, meta_DIC1, meta_AWD, + meta_RAWI, } meta_t; From f77a2297858c8f4ead58956746d8b7a514769783 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 17:51:38 +0200 Subject: [PATCH 095/141] cleanup: rename + formats --- doc/FORMATS.md | 6 +++++- src/libvgmstream.vcxproj | 3 ++- src/libvgmstream.vcxproj.filters | 5 ++++- src/meta/{gsp_gsb.c => gsnd.c} | 0 4 files changed, 11 insertions(+), 3 deletions(-) rename src/meta/{gsp_gsb.c => gsnd.c} (100%) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 6a95cf82a..5fa67e83a 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -558,7 +558,7 @@ different internally (encrypted, different versions, etc) and not always can be - ISH+ISD DSP Header [*ISH_ISD*] - *ish_isd*: `.isd + .ish` - Codecs: NGC_DSP -- **gsp_gsb.c** +- **gsnd.c** - Tecmo GSND Header [*GSND*] - *gsnd*: `.gsp + .gsb` - Codecs: NGC_DSP ATRAC3 XMA @@ -1789,6 +1789,10 @@ different internally (encrypted, different versions, etc) and not always can be - Double Fine WB header [*PWB*] - *pwb*: `.pwb` - Codecs: PSX +- **rawi.c** + - Torus SqueakStream RAWI header [*RAWI*] + - *rawi*: `(base) + .asset .(external) .raw` + - Codecs: NGC_DSP PCM16BE PSX PCM8 MS_IMA - **scd_pcm.c** - Lunar: Eternal Blue .PCM header [*SCD_PCM*] - *scd_pcm*: `.pcm` diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 331601904..721d6557b 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -438,7 +438,7 @@ - + @@ -582,6 +582,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index da3dfccbb..9c205ecd4 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1135,7 +1135,7 @@ meta\Source Files - + meta\Source Files @@ -1567,6 +1567,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/gsp_gsb.c b/src/meta/gsnd.c similarity index 100% rename from src/meta/gsp_gsb.c rename to src/meta/gsnd.c From 888cd42ffa4a3abc822e4a2e59b60e14a508550c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 8 Jul 2023 18:06:41 +0200 Subject: [PATCH 096/141] Add HCA key --- src/meta/hca_keys.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 9de2a3a56..7946b7d3f 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -1187,9 +1187,12 @@ static const hcakey_info hcakey_list[] = { // Disney Star Smash (Android) {3941111674189632}, // 000E006B915C3740 - // Final Fantasy VII: Ever Crisis (Android) + // Final Fantasy VII: Ever Crisis (beta) (Android) {19629307353822}, // 000011DA4DE45ADE + // Tower of Sky (Android) + {5893902754391672}, // 0014F0792C042678 + }; #endif/*_HCA_KEYS_H_*/ From c5f3179714ff810ca3d458c0215f00d158c1dbf7 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Sun, 9 Jul 2023 01:45:33 +0300 Subject: [PATCH 097/141] Sony BNK: Attempt to closer calculate the guesstimated sample rate from pitch --- src/meta/bnk_sony.c | 197 +++++++++++++++++++++++++++++++------------- 1 file changed, 140 insertions(+), 57 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 1c31519ea..7e210f4b2 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -4,6 +4,7 @@ #include "../util/endianness.h" typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec; +uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t note, int16_t fine); /* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { @@ -13,7 +14,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { uint32_t stream_size, interleave = 0; int channels = 0, loop_flag, sample_rate, big_endian; int32_t loop_start = 0, loop_end = 0; - uint32_t center_note, center_fine, flags; + uint16_t center_note, center_fine, flags, pitch; uint32_t atrac9_info = 0; int total_subsongs, target_subsong = sf->stream_index; @@ -30,7 +31,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { read_f32 = read_f32be; big_endian = 1; } - else if (read_u32le(0x00,sf) == 0x03) { /* PS2/Vita/PS4 */ + else if (read_u32le(0x00,sf) == 0x03) { /* PS2/PSP/Vita/PS4 */ read_u32 = read_u32le; read_u16 = read_u16le; read_f32 = read_f32le; @@ -80,13 +81,13 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { * - 04: non-fixed bank? * - 100: has names * - 200: has user data */ - /* version < v0x1a: - * - 0x0c: block id - * - 0x10: block number + /* version < v0x1a: + * - 0x0c: block id + * - 0x10: block number * - 0x11: padding - * version >= v0x1a: + * version >= v0x1a: * - 0x0c: hash (0x10) - * - 0x1c: filename (0x100?) */ + * - 0x1c: filename (0x100?) */ //;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, sblk_version %x\n", sblk_offset, data_offset, sblk_version); { @@ -170,7 +171,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* table defs: * - table1: sections, point to some materials (may be less than streams/materials) - * (a "sound" that has N grains, and is triggered by games like a cue) + * (a "sound" that has N grains, and is triggered by games like a cue) * - table2: materials, point to all sounds or others subtypes (may be more than sounds) * (a "grain" that does actions like play or changes volume) * - table3: sounds, point to streams (multiple sounds can repeat stream) @@ -206,7 +207,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { if (total_subsongs == target_subsong) { table2_entry_offset = 0; table3_entry_offset = (i*0x28) + 0x08; - /* continue to count all subsongs*/ + /* continue to count all subsongs */ } } @@ -270,49 +271,40 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { stream_offset = read_u32(table3_offset+table3_entry_offset+0x10,sf); stream_size = read_u32(table3_offset+table3_entry_offset+0x14,sf); - /* "base" sample rates, allowed by the tool (for other rates must use base + semitones, but aren't exact) */ - if (center_note == 0xC4 && center_fine == 0x00) - sample_rate = 48000; - else if (center_note == 0xC2 && center_fine == 0x42) - sample_rate = 44100; - else if (center_note == 0xb6 && center_fine == 0x42) - sample_rate = 22050; - else if (center_note == 0xaa && center_fine == 0x42) - sample_rate = 11025; - else if (center_note == 0xa4 && center_fine == 0x7c) - sample_rate = 8000; - else { - /* rough ("center") sample rates using semitone-to-hz formula: (rate) * 2 ^ ((pitch - base) / 12) */ - double curr_rate = 48000 * pow(2.0, (double)((int)center_note - 0xc4) / 12.0); - double prev_rate = 48000 * pow(2.0, (double)(((int)center_note - 1) - 0xc4) / 12.0); - /* partial semitone, from 0x00 = 0.0 to 0x7f = 1.0 of a semitone for current rate */ - float fine_pct = center_fine / 127.0f; - - //TODO improve (fine seems approximate and not sure how to calc current semitone hz value, so needs prev_rate) - sample_rate = curr_rate + (curr_rate - prev_rate) * fine_pct; - - /* some odd "beep" sfx in Sly 2/3 seems to go slightly higher after applying fine_pct, probably should resample */ - if (sample_rate > VGMSTREAM_MAX_SAMPLE_RATE) - sample_rate = VGMSTREAM_MAX_SAMPLE_RATE; - - /* waves can set base sample rate (48/44/22/11/8khz) + pitch in semitones, then converted to center+fine - * 48000 + pitch 0.0 > center=0xc4, fine=0x00 - * 48000 + pitch 0.10 > center=0xc4, fine=0x0c - * 48000 + pitch 0.50 > center=0xc4, fine=0x3f - * 48000 + pitch 0.99 > center=0xc4, fine=0x7d - * 48000 + pitch 1.00 > center=0xc5, fine=0x00 - * 48000 + pitch 12.0 > center=0xd0, fine=0x00 - * 48000 + pitch 24.0 > center=0xdc, fine=0x00 - * 48000 + pitch 56.0 > center=0xfc, fine=0x00 - * 48000 + pitch 68.0 > center=0x08, fine=0x00 > ? - * 48000 + pitch -12.0 > center=0xb8, fine=0x00 - * 48000 + pitch -0.10 > center=0xc3, fine=0x72 - * 48000 + pitch -0.001 > not allowed - * 8000 + pitch 1.00 > center=0xa4, fine=0x7c - * 8000 + pitch -12.00 > center=0x98, fine=0x7c - * 8000 + pitch -48.00 > center=0x74, fine=0x7c - */ - } + /* if it isn't, then it's treated as 44100 base? (PS1?) */ + bool is_negative = center_note >> 7; /* center_note & 0x80; */ + + if (is_negative) + center_note = 0x100 - center_note; + + /* note/fine seems to always be set to 60, 0? */ + pitch = ps_note_to_pitch(center_note, center_fine, 0x3C, 0x00); + + if (pitch > 0x4000) + pitch = 0x4000; /* 192000 Hz max */ + + if (!is_negative) /* PS1 mode? */ + pitch = (pitch * 44100) / 48000; + + sample_rate = (pitch * 48000) / 0x1000; + + /* waves can set base sample rate (48/44/22/11/8khz) + pitch in semitones, then converted to center+fine + * 48000 + pitch 0.00 > center=0xc4, fine=0x00 + * 48000 + pitch 0.10 > center=0xc4, fine=0x0c + * 48000 + pitch 0.50 > center=0xc4, fine=0x3f + * 48000 + pitch 0.99 > center=0xc4, fine=0x7d + * 48000 + pitch 1.00 > center=0xc5, fine=0x00 + * 48000 + pitch 12.00 > center=0xd0, fine=0x00 + * 48000 + pitch 24.00 > center=0xdc, fine=0x00 + * 48000 + pitch 56.00 > center=0xfc, fine=0x00 + * 48000 + pitch 68.00 > center=0x08, fine=0x00 > ? + * 48000 + pitch -12.00 > center=0xb8, fine=0x00 + * 48000 + pitch -0.10 > center=0xc3, fine=0x72 + * 48000 + pitch -0.001 > not allowed + * 8000 + pitch 1.00 > center=0xa4, fine=0x7c + * 8000 + pitch -12.00 > center=0x98, fine=0x7c + * 8000 + pitch -48.00 > center=0x74, fine=0x7c + */ break; case 0x0d: @@ -336,19 +328,21 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { switch(sblk_version) { case 0x03: for (i = 0; i < section_entries; i++) { - entry_offset = read_u32(table1_offset + (i * table1_entry_size) + table1_suboffset, sf); + entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); /* is table2_entry_offset in the range of the expected section */ - if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) + if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { table4_entry_id = i; + break; + } } /* table4: * 0x00: bank name (optional) * 0x08: name section offset * 0x0C-0x14: 3 null pointers (reserved?) - * 0x18: 32 name chunk offsets (shorts) + * 0x18-0x58: 32 name chunk offset indices */ /* Name chunks are organised as @@ -378,6 +372,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { } } //goto fail; /* didn't find any valid index? */ + stream_name_offset = 0; loop_break: break; @@ -423,8 +418,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { break; } } - break; + default: break; } @@ -492,7 +487,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { * 200 = send LFE * 400 = send center */ - if ((flags & 0x80) && sblk_version <= 3) { + if ((flags & 0x80) && sblk_version <= 3) { codec = PCM16; /* rare [Wipeout HD (PS3)]-v3 */ } else { @@ -725,3 +720,91 @@ VGMSTREAM * init_vgmstream_bnk_sony_v2(STREAMFILE *sf) { return NULL; } #endif + +uint16_t note_pitch_table[12] = { + 0x8000, 0x879C, 0x8FAC, 0x9837, 0xA145, 0xAADC, + 0xB504, 0xBFC8, 0xCB2F, 0xD744, 0xE411, 0xF1A1 +}; + +uint16_t fine_pitch_table[128] = { + 0x8000, 0x800E, 0x801D, 0x802C, 0x803B, 0x804A, 0x8058, 0x8067, + 0x8076, 0x8085, 0x8094, 0x80A3, 0x80B1, 0x80C0, 0x80CF, 0x80DE, + 0x80ED, 0x80FC, 0x810B, 0x811A, 0x8129, 0x8138, 0x8146, 0x8155, + 0x8164, 0x8173, 0x8182, 0x8191, 0x81A0, 0x81AF, 0x81BE, 0x81CD, + 0x81DC, 0x81EB, 0x81FA, 0x8209, 0x8218, 0x8227, 0x8236, 0x8245, + 0x8254, 0x8263, 0x8272, 0x8282, 0x8291, 0x82A0, 0x82AF, 0x82BE, + 0x82CD, 0x82DC, 0x82EB, 0x82FA, 0x830A, 0x8319, 0x8328, 0x8337, + 0x8346, 0x8355, 0x8364, 0x8374, 0x8383, 0x8392, 0x83A1, 0x83B0, + 0x83C0, 0x83CF, 0x83DE, 0x83ED, 0x83FD, 0x840C, 0x841B, 0x842A, + 0x843A, 0x8449, 0x8458, 0x8468, 0x8477, 0x8486, 0x8495, 0x84A5, + 0x84B4, 0x84C3, 0x84D3, 0x84E2, 0x84F1, 0x8501, 0x8510, 0x8520, + 0x852F, 0x853E, 0x854E, 0x855D, 0x856D, 0x857C, 0x858B, 0x859B, + 0x85AA, 0x85BA, 0x85C9, 0x85D9, 0x85E8, 0x85F8, 0x8607, 0x8617, + 0x8626, 0x8636, 0x8645, 0x8655, 0x8664, 0x8674, 0x8683, 0x8693, + 0x86A2, 0x86B2, 0x86C1, 0x86D1, 0x86E0, 0x86F0, 0x8700, 0x870F, + 0x871F, 0x872E, 0x873E, 0x874E, 0x875D, 0x876D, 0x877D, 0x878C +}; + +uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t note, int16_t fine) { + /* Derived from OpenGOAL, Copyright (c) 2020-2022 OpenGOAL Team, ISC License + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + int32_t fine_adjust, fine_idx, note_adjust, note_idx; + int32_t unk1, unk2, unk3; /* TODO: better variable names */ + uint16_t pitch; + + fine_idx = fine + center_fine; + + fine_adjust = fine_idx; + if (fine_idx < 0) + fine_adjust = fine_idx + 0x7F; + + fine_adjust /= 128; + note_adjust = note + fine_adjust - center_note; + unk3 = note_adjust / 6; + + if (note_adjust < 0) + unk3--; + + fine_idx -= fine_adjust * 128; + + if (note_adjust < 0) + unk2 = -1; + else + unk2 = 0; + if (unk3 < 0) + unk3--; + + unk2 = (unk3 / 2) - unk2; + unk1 = unk2 - 2; + note_idx = note_adjust - (unk2 * 12); + + if ((note_idx < 0) || ((note_idx == 0) && (fine_idx < 0))) { + note_idx += 12; + unk1 = unk2 - 3; + } + + if (fine_idx < 0) { + note_idx = (note_idx - 1) + fine_adjust; + fine_idx += (fine_adjust + 1) * 128; + } + + pitch = (note_pitch_table[note_idx] * fine_pitch_table[fine_idx]) >> 16; + + if (unk1 < 0) + pitch = (pitch + (1 << (-unk1 - 1))) >> -unk1; + + return pitch; +} From 04f719b0809f626610f5ce62f5fd18f72e12714d Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 9 Jul 2023 23:22:36 +0200 Subject: [PATCH 098/141] Add Torus's SqueakSample and old SqueakStreams --- src/formats.c | 3 +- src/meta/meta.h | 4 +- src/meta/rawi.c | 392 ++++++++++++++++++++++++++++++++---------- src/vgmstream.c | 3 +- src/vgmstream_types.h | 3 +- 5 files changed, 309 insertions(+), 96 deletions(-) diff --git a/src/formats.c b/src/formats.c index 4da1547b3..72f942235 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1410,7 +1410,8 @@ static const meta_info meta_info_list[] = { {meta_BIGRP, "Inti Creates .BIGRP header"}, {meta_DIC1, "Codemasters DIC1 header"}, {meta_AWD, "RenderWare Audio Wave Dictionary header"}, - {meta_RAWI, "Torus SqueakStream RAWI header"}, + {meta_SQUEAKSTREAM, "Torus SqueakStream header"}, + {meta_SQUEAKSAMPLE, "Torus SqueakSample header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/meta/meta.h b/src/meta/meta.h index 290543588..e678c9717 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -978,6 +978,8 @@ VGMSTREAM* init_vgmstream_rws_809(STREAMFILE* sf); VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); -VGMSTREAM* init_vgmstream_rawi(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf); + #endif /*_META_H*/ diff --git a/src/meta/rawi.c b/src/meta/rawi.c index 909585b9c..5e283e0f8 100644 --- a/src/meta/rawi.c +++ b/src/meta/rawi.c @@ -3,176 +3,384 @@ #include "../coding/coding.h" #include "../util/endianness.h" +#define SQUEAK_MAX_CHANNELS 8 /* seen 3 in some voices */ +typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA } squeak_type_t; -/* RAWI - from Torus games "SqueakStream" samples */ -VGMSTREAM* init_vgmstream_rawi(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - STREAMFILE* sb = NULL; - STREAMFILE* sn = NULL; - uint32_t start_offset, name_offset, extn_offset, interleave; - int channels, loop_flag, codec, sample_rate; - int32_t num_samples, loop_start, loop_end; +typedef struct { + squeak_type_t type; + int version; + + int channels; + int codec; + int sample_rate; + uint32_t interleave; + + uint32_t extb_offset; + uint32_t name_offset; + + int32_t num_samples; + int32_t loop_start; + int32_t loop_end; + + uint32_t data_offset; + uint32_t coef_offset; + uint32_t coef_spacing; + + uint32_t data_size; + + bool big_endian; + bool external_info; + bool external_data; + bool stream; +} squeak_header_t; + +static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h); + + +/* SqueakStream - from Torus games (as identified in .hnk subdirs) */ +VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { + squeak_header_t h = {0}; + bool is_old = false; /* checks */ - bool big_endian = false; - if (is_id32be(0x00,sf, "RAWI")) - big_endian = false; - else if (is_id32be(0x00,sf, "IWAR")) - big_endian = true; /* Wii/PS3 */ - else + h.big_endian = false; + if (is_id32be(0x00,sf, "RAWI")) { + h.big_endian = false; + } + else if (is_id32be(0x00,sf, "IWAR")) { + h.big_endian = true; /* Wii/PS3/X360 */ + } + else { + /* no header id so test codec in dumb endian */ + if ((read_u32le(0x00,sf) & 0x00FFFFFF) > 9 || (read_u32be(0x00,sf) & 0x00FFFFFF) > 9) + return NULL; + is_old = true; + h.big_endian = guess_endian32(0x04, sf); + } + + if (get_streamfile_size(sf) > 0x1000) /* arbitrary max */ return NULL; - //TODO: handle first version used in Scooby Doo! First Frights (similar but larger fields and no header ID) /* (extensionless): no known extension */ if (!check_extensions(sf,"")) return NULL; - read_s32_t read_s32 = big_endian ? read_s32be : read_s32le; - read_u32_t read_u32 = big_endian ? read_u32be : read_u32le; + read_s32_t read_s32 = h.big_endian ? read_s32be : read_s32le; + read_u32_t read_u32 = h.big_endian ? read_u32be : read_u32le; + + /* base header (with extra checks for old version since format is a bit simple) */ + if (!is_old) { + h.version = read_u8(0x04,sf); + if (h.version != 0x01) return NULL; + h.codec = read_u8(0x05,sf); + h.channels = read_u8(0x06,sf); + /* 07: null */ + h.num_samples = read_s32(0x08, sf); + h.sample_rate = read_s32(0x0c, sf); + h.loop_start = read_s32(0x10, sf); + h.loop_end = read_s32(0x14, sf); + h.extb_offset = read_u32le(0x18, sf); /* LE! */ + h.name_offset = read_u32le(0x1c, sf); + /* 20: null, unknown values (sometimes floats) */ + h.interleave = read_u32(0x38, sf); + + h.data_offset = 0; /* implicit... */ - /* mini header with a string to the external asset; on Wii this string is also in a separate file */ + /* XX: extra values (may depend on codec/channels) */ + /* XX: DSP coefs / fmt headers (optional) */ + /* XX: extra table with offset to fmt headers / DSP coefs /etc (per channel) */ + /* XX: asset name */ + } + else { + h.codec = read_s32(0x00,sf); + if (h.codec > 0x09) return NULL; + h.channels = read_s32(0x04,sf); + if (h.channels > SQUEAK_MAX_CHANNELS) return NULL; + h.interleave = read_u32(0x08, sf); + if (h.interleave > 0xFFFFFF) return NULL; + h.loop_start = read_s32(0x0c, sf); + h.loop_end = read_s32(0x10, sf); + h.num_samples = read_s32(0x14, sf); + if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL; + /* 18: float/value */ + /* 1c: float/value */ + /* 20: cue table entries (optional) */ + /* 22: unknown */ + /* 24: cues offset */ + /* 26: cues flags */ + h.extb_offset = read_u32le(0x28, sf); /* LE! */ + h.name_offset = read_u32le(0x2c, sf); + h.data_offset = read_u32(0x30, sf); /* PS2 uses a few big .raw rather than separate per header */ + + /* XX: DSP coefs / fmt headers (optional) */ + /* XX: cue table (00=null + 04=sample start per entry) */ + /* XX: extra table (00=null + 00=sample rate, 04=samples, per channel) */ + /* XX: asset name */ + + //sample_rate = ...; // read later after opening external info + + /* not ideal but... */ + if (h.data_offset && h.codec == 0x03) { + h.data_size = (h.num_samples / 28) * 0x10 * h.channels; + } + } - if (read_u8(0x04,sf) != 0x01) /* version? */ + + /* Wii streams uses a separate info file, check external flags */ + /* (possibly every section may be separate or not but only seen all at once) */ + h.stream = true; + h.external_info = (h.name_offset & 0xF0000000); + h.external_data = true; + h.name_offset = h.name_offset & 0x0FFFFFFF; + h.extb_offset = h.extb_offset & 0x0FFFFFFF; + if (h.extb_offset > h.name_offset) return NULL; + + switch(h.codec) { + case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ + case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */ + case 0x02: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */ + case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */ + case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */ + default: + return NULL; + } + + return init_vgmstream_squeak_common(sf, &h); +} + + +/* SqueakSample - from Torus games (as identified in .hnk subdirs) */ +VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { + squeak_header_t h = {0}; + + + /* checks */ + if (read_u32le(0x00,sf) != 0x20 && read_u32le(0x00,sf) != 0x1c) /* even on BE */ return NULL; - codec = read_u8(0x05,sf); - channels = read_u8(0x06,sf); - /* 0x07: null */ - num_samples = read_s32(0x08, sf); - sample_rate = read_s32(0x0c, sf); - loop_start = read_s32(0x10, sf); - loop_end = read_s32(0x14, sf); - //etbl_offset = read_u32(0x18, sf); - name_offset = read_u32(0x1c, sf); - /* 0x20: null, unknown values (sometimes floats) */ - interleave = read_u32(0x38, sf); - /* extra values, then DSP coefs if needed, then asset name (header size is not exact) */ + //if (get_streamfile_size(sf) > 0x1000) /* not correct for non-external files */ + // return NULL; - extn_offset = (name_offset >> 24) & 0xFF; /* if name is external, sub-offset inside that file */ - name_offset = (name_offset >> 0) & 0xFFFFFF; /* if name is external, default/unused (same with etbl_offset) */ + /* (extensionless): no known extension */ + if (!check_extensions(sf,"")) + return NULL; - /* simplify as Wii defines both and uses a separate file, PS3 only defines extn and doesn't use separate */ - if (extn_offset && !name_offset) { - name_offset = extn_offset; - extn_offset = 0; + h.big_endian = guess_endian32(0x04, sf); + read_s32_t read_s32 = h.big_endian ? read_s32be : read_s32le; + + /* base header (with extra checks since format is a bit simple) */ + uint32_t offset = read_u32le(0x00, sf); /* old versions use 0x1c, new 0x20, but otherwise don't look different */ + + h.channels = read_s32(0x04,sf); + if (h.channels > SQUEAK_MAX_CHANNELS) return NULL; + /* 04: float/value */ + /* 0c: float/value */ + /* 14: value? */ + /* 18: value? (new) / 1 (old) */ + /* 1c: 1? (new) / none (old) */ + + /* sample header per channel (separate fields but assumes all are repeated except offsets) */ + h.num_samples = read_s32(offset + 0x00,sf); + h.data_offset = read_u32le(offset + 0x04,sf); + h.loop_start = read_s32(offset + 0x08,sf); + h.loop_end = read_s32(offset + 0x0c,sf); + if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL; + h.codec = read_s32(offset + 0x10,sf); + if (h.codec > 0x09) return NULL; + h.sample_rate = read_s32(offset + 0x14,sf); + if (h.sample_rate > 48000 || h.sample_rate < 0) return NULL; + + /* PCM has extended fields (0x68)*/ + if (h.codec != 0xFFFE0001) { + /* 18: loop start offset? (not always) */ + /* 1c: loop end offset? */ + /* 20: data size? */ + /* 24: data size? (new) / count? (old) */ + h.coef_offset = read_u32le(offset + 0x28,sf); } - loop_flag = loop_end > 0; + /* DSP and old versions use a external .raw file (assumed extension) */ + h.stream = false; + h.external_info = false; + h.external_data = (h.data_offset & 0xF0000000); + h.data_offset = h.data_offset & 0x0FFFFFFF; + + /* absolute offsets, should read for each channel but simplify + * (also channels may have padding, but files end with no padding) */ + if (h.channels > 1) { + int separation = h.codec == 0xFFFE0001 ? 0x68 : 0x2c; + uint32_t data_offset = read_u32le(offset + 0x04 + 1 * separation, sf) & 0x0FFFFFFF; + uint32_t coef_offset = read_u32le(offset + 0x28 + 1 * separation, sf); + h.interleave = data_offset - h.data_offset; /* distance */ + h.coef_spacing = coef_offset - h.coef_offset; + } - start_offset = 0x00; + switch(h.codec) { + case 0x00: h.type = DSP; break; /* (same as below for unlooped audio) */ + case 0x01: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS) */ + case 0x06: /* (same as below for unlooped audio) */ + case 0x07: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + case 0x08: /* (same as below for unlooped audio) */ + case 0x09: h.type = IMA; break; /* Scooby-Doo! First Frights (DS), Turbo Super Stunt Squad (DS) */ + case 0xFFFE0001: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360) */ + default: + return NULL; + } - /* open external asset */ - { - char asset_name[0x20]; /* "(8-byte crc).raw", "MU(6-byte crc).raw" */ + return init_vgmstream_squeak_common(sf, &h); +} - - if (extn_offset) { - sn = open_streamfile_by_ext(sf, "asset"); /* unknown real extension, based on debug strings */ - if (!sn) { - vgm_logi("RAWI: external name '.asset' not found (put together)\n"); - goto fail; - } - - read_string(asset_name, sizeof(asset_name), extn_offset, sn); + +static STREAMFILE* load_assets(STREAMFILE* sf, squeak_header_t* h) { + STREAMFILE* sb = NULL; + STREAMFILE* sn = NULL; + read_s32_t read_s32 = h->big_endian ? read_s32be : read_s32le; + + + char asset_name[0x20]; /* "(8-byte crc).raw", "xx(6-byte crc).raw", "(regular name).raw" */ + if (h->external_info) { + sn = open_streamfile_by_ext(sf, "asset"); /* unknown real extension if any, based on debug strings */ + if (!sn) { + vgm_logi("Squeak: external name '.asset' not found (put together)\n"); + goto fail; } - else { - read_string(asset_name, sizeof(asset_name), name_offset, sf); + } + + if (h->stream) { + if (h->version == 0) { + h->sample_rate = read_s32(h->extb_offset + 0x04, sn ? sn : sf); /* per channel, use first */ } - /* try to open external asset in various ways, since this format is a bit hard to use */ + read_string(asset_name, sizeof(asset_name), h->name_offset, sn ? sn : sf); + + /* extb_offset defines N coef offset per channel but in practice this seem fixed, simplify */ + h->coef_offset = 0x40; + h->coef_spacing = 0x30; + } + /* try to open external data .raw in various ways, since this format is a bit hard to use */ + if (h->stream) { /* "(asset name)": plain as found */ - if (!sb){ + if (!sb) { sb = open_streamfile_by_filename(sf, asset_name); } /* "sound/(asset name)": most common way to store files */ char path_name[256]; snprintf(path_name, sizeof(path_name), "sound/%s", asset_name); - if (!sb){ + if (!sb) { sb = open_streamfile_by_filename(sf, path_name); } + } - /* "(header name).raw": for renamed files */ - if (!sb){ - sb = open_streamfile_by_ext(sf, "raw"); - } + /* "(header name).raw": for squeakstreams and renamed files */ + if (!sb) { + sb = open_streamfile_by_ext(sf, "raw"); + } - if (!sb) { - vgm_logi("RAWI: external file '%s' not found (put together)\n", asset_name); - goto fail; - } + if (!sb) { + char* info = h->stream ? asset_name : "(filename).raw"; + vgm_logi("Squeak: external file '%s' not found (put together)\n", info); + goto fail; + } + + close_streamfile(sn); + return sb; +fail: + close_streamfile(sn); + return NULL; +} + +static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* sb = NULL; + + /* common */ + int loop_flag = h->loop_end > 0; + + + /* open external asset */ + if (h->external_data) { + sb = load_assets(sf, h); + if (!sb) goto fail; } /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels, loop_flag); + vgmstream = allocate_vgmstream(h->channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_RAWI; - vgmstream->sample_rate = sample_rate; - vgmstream->num_samples = num_samples; - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end + 1; + vgmstream->meta_type = h->stream ? meta_SQUEAKSTREAM : meta_SQUEAKSAMPLE; + vgmstream->sample_rate = h->sample_rate; + vgmstream->num_samples = h->num_samples; + vgmstream->loop_start_sample = h->loop_start; + vgmstream->loop_end_sample = h->loop_end + 1; + vgmstream->stream_size = h->data_size; - switch(codec) { - case 0x00: /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ + switch(h->type) { + case DSP: vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h->interleave; //vgmstream->interleave_last_block_size = ...; /* apparently padded */ - /* etbl_offset defines N coef offset per channel (with external name, etbl_offset is ignored and offsets start at 0x00 in .asset instead) - * but in practice this seem fixed */ - dsp_read_coefs(vgmstream, sf, 0x40, 0x30, big_endian); - dsp_read_hist(vgmstream, sf, 0x40 + 0x24, 0x30, big_endian); + dsp_read_coefs(vgmstream, sf, h->coef_offset + 0x00, h->coef_spacing, h->big_endian); + dsp_read_hist (vgmstream, sf, h->coef_offset + 0x24, h->coef_spacing, h->big_endian); break; - case 0x01: /* Falling Skies The Game (PC) */ - vgmstream->coding_type = coding_PCM16BE; + case PCM16LE: + vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; /* not 0x02 */ + vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ - case 0x02: /* Falling Skies The Game (X360) */ + case PCM16BE: vgmstream->coding_type = coding_PCM16BE; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; /* not 0x02 */ + vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ /* etbl_offset may set offsets to RIFF fmts per channel) */ break; - case 0x03: /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + case PSX: vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h->interleave; break; - case 0x05: /* Scooby Doo and the Spooky Swamp (DS) */ + case PCM8: vgmstream->coding_type = coding_PCM8; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h->interleave; break; - case 0x09: /* Turbo Super Stunt Squad (DS) */ + case MSIMA: vgmstream->coding_type = coding_MS_IMA; vgmstream->layout_type = layout_none; - //vgmstream->interleave_block_size = interleave; /* unused? (mono) */ + //vgmstream->interleave_block_size = h->interleave; /* unused? (mono) */ vgmstream->frame_size = 0x20; break; + case IMA: + vgmstream->coding_type = coding_IMA; + vgmstream->layout_type = layout_interleave; + vgmstream->interleave_block_size = h->interleave; + + /* possibly considered MS-IMA in a single block (not valid though), first 2 values maybe are adpcm hist */ + h->data_offset += 0x04; + break; + default: - vgm_logi("RAWI: unknown codec %x (report)\n", codec); + vgm_logi("RAWI: unknown codec %x (report)\n", h->codec); goto fail; } - if (!vgmstream_open_stream(vgmstream, sb, start_offset)) + if (!vgmstream_open_stream(vgmstream, sb ? sb : sf, h->data_offset)) goto fail; close_streamfile(sb); - close_streamfile(sn); return vgmstream; fail: close_streamfile(sb); - close_streamfile(sn); close_vgmstream(vgmstream); return NULL; } diff --git a/src/vgmstream.c b/src/vgmstream.c index 1e1093fd4..745f3b96f 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -521,7 +521,8 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_awd, init_vgmstream_rws_809, init_vgmstream_pwb, - init_vgmstream_rawi, + init_vgmstream_squeakstream, + init_vgmstream_squeaksample, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 508ad8e2f..fed129085 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -698,7 +698,8 @@ typedef enum { meta_BIGRP, meta_DIC1, meta_AWD, - meta_RAWI, + meta_SQUEAKSTREAM, + meta_SQUEAKSAMPLE, } meta_t; From 57a9611dad6c39c75be655350ddd934fcb61a47d Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 9 Jul 2023 23:23:49 +0200 Subject: [PATCH 099/141] cleanup: rename --- doc/FORMATS.md | 9 +++++---- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/{rawi.c => squeak.c} | 0 4 files changed, 9 insertions(+), 8 deletions(-) rename src/meta/{rawi.c => squeak.c} (100%) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 5fa67e83a..ed321080e 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -1789,10 +1789,11 @@ different internally (encrypted, different versions, etc) and not always can be - Double Fine WB header [*PWB*] - *pwb*: `.pwb` - Codecs: PSX -- **rawi.c** - - Torus SqueakStream RAWI header [*RAWI*] - - *rawi*: `(base) + .asset .(external) .raw` - - Codecs: NGC_DSP PCM16BE PSX PCM8 MS_IMA +- **squeak.c** + - Torus SqueakStream header [*SQUEAKSTREAM*] + - Torus SqueakSample header [*SQUEAKSAMPLE*] + - *squeaksample*: `(base) + .asset .(external) .raw` + - Codecs: NGC_DSP PCM16LE PCM16BE PSX PCM8 MS_IMA IMA - **scd_pcm.c** - Lunar: Eternal Blue .PCM header [*SCD_PCM*] - *scd_pcm*: `.pcm` diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 721d6557b..c3145a54d 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -582,7 +582,6 @@ - @@ -635,6 +634,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 9c205ecd4..d67ac7cdc 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1567,9 +1567,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files @@ -1726,6 +1723,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/rawi.c b/src/meta/squeak.c similarity index 100% rename from src/meta/rawi.c rename to src/meta/squeak.c From 31cfb1d9d88cc8fea1eddcae334ce02f9412c227 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 9 Jul 2023 23:24:05 +0200 Subject: [PATCH 100/141] bnk_sony: fix warning --- src/meta/bnk_sony.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 7e210f4b2..3cfa1a10d 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -254,7 +254,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x04: case 0x05: case 0x08: - case 0x09: + case 0x09: { /* "tone" */ /* 0x00: priority */ /* 0x01: volume */ @@ -306,7 +306,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { * 8000 + pitch -48.00 > center=0x74, fine=0x7c */ break; - + } case 0x0d: case 0x0e: case 0x0f: From 508d69a41bf8099707f2eb3cae88258b5446dc72 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Mon, 10 Jul 2023 00:26:05 +0300 Subject: [PATCH 101/141] Sony BNK: Verify the full beginning frame --- src/meta/bnk_sony.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 7e210f4b2..37d48dae5 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -133,7 +133,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* 0x30: next block offset */ table3_offset = sblk_offset + read_u32(sblk_offset+0x34,sf); /* grain data? */ table4_offset = sblk_offset + read_u32(sblk_offset+0x38,sf); /* block names */ - /*0x3c: SFXUD? */ + /* 0x3c: SFXUD? */ table1_entry_size = 0x0c; table1_suboffset = 0x08; @@ -449,8 +449,11 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { stream_size += 0x10; for (offset = data_offset + stream_offset + 0x10; offset < max_offset; offset += 0x10) { - /* beginning frame (if file loops won't have end frame) */ - if (read_u32be(offset + 0x00, sf) == 0x00000000 && read_u32be(offset + 0x04, sf) == 0x00000000) + /* beginning frame (if file loops won't have end frame) + * checking the entire 16 byte block, as it is possible + * for just the first 8 bytes to be empty [Bully (PS2)] */ + if (read_u32be(offset + 0x00, sf) == 0x00000000 && read_u32be(offset + 0x04, sf) == 0x00000000 && + read_u32be(offset + 0x08, sf) == 0x00000000 && read_u32be(offset + 0x0C, sf) == 0x00000000) break; stream_size += 0x10; From 0c228d0bac3fa3b8847cc831b8f97ce83ea92c86 Mon Sep 17 00:00:00 2001 From: Adam Gashlin Date: Sun, 9 Jul 2023 19:10:21 -0700 Subject: [PATCH 102/141] Allow a str+wav header to end at table1 Fixes Bad Boys: Miami Takedown (aka Bad Boys II) (PC) --- src/meta/str_wav.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/meta/str_wav.c b/src/meta/str_wav.c index 18fc59d9e..3fa77f3eb 100644 --- a/src/meta/str_wav.c +++ b/src/meta/str_wav.c @@ -583,11 +583,17 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa return 1; } + /* Bad Boys II (PC)[2004] */ /* Pac-Man World 3 (PC)[2005] */ if ((read_u32be(0x04,sf_h) == 0x00000800 || read_u32be(0x04,sf_h) == 0x01000800) && /* rare, mu_spectral1_explore_2 */ read_u32le(0x24,sf_h) == read_u32le(0x114,sf_h) && /* sample rate repeat */ - read_u32le(0x130,sf_h) + read_u32le(0x134,sf_h) * 0x40 == header_size /* ~0x140 + cues */ + ( + // check if the header ends at table1 (Bad Boys) + read_u32le(0x128,sf_h) * 0x4 + read_u32le(0x12c, sf_h) == header_size || + // otherwise it ends at table2 + read_u32le(0x130,sf_h) + read_u32le(0x134,sf_h) * 0x40 == header_size /* ~0x140 + cues */ + ) ) { /* 0x08: null */ /* 0x0c: hashname */ From f9a433980c867a1f242c0b4a3800e1ab85e17fb2 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Mon, 10 Jul 2023 17:44:40 +0300 Subject: [PATCH 103/141] Sony BNK: Check if name table exists --- src/meta/bnk_sony.c | 196 ++++++++++++++++++++++---------------------- 1 file changed, 100 insertions(+), 96 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 3a0aabcb3..f639fec9e 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -92,6 +92,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { { int i; + bool is_negative; uint32_t table1_offset, table2_offset, table3_offset, table4_offset; uint32_t section_entries, material_entries, stream_entries; uint32_t table1_entry_size; @@ -122,7 +123,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x05: /* Ratchet & Clank (PS3) */ case 0x08: /* Playstation Home Arcade (Vita) */ case 0x09: /* Puyo Puyo Tetris (PS4) */ - section_entries = read_u16(sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds)*/ + section_entries = read_u16(sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds) */ material_entries = read_u16(sblk_offset+0x18,sf); /* entry size: ~0x08 (NumGrains) */ stream_entries = read_u16(sblk_offset+0x1a,sf); /* entry size: ~0x18 + variable (NumWaveforms) */ table1_offset = sblk_offset + read_u32(sblk_offset+0x1c,sf); /* sound offset */ @@ -228,7 +229,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { if (total_subsongs == target_subsong) { table2_entry_offset = (i*0x08); table3_entry_offset = table2_subinfo; - /* continue to count all subsongs*/ + /* continue to count all subsongs */ } } @@ -254,7 +255,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { case 0x04: case 0x05: case 0x08: - case 0x09: { + case 0x09: /* "tone" */ /* 0x00: priority */ /* 0x01: volume */ @@ -272,12 +273,12 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { stream_size = read_u32(table3_offset+table3_entry_offset+0x14,sf); /* if it isn't, then it's treated as 44100 base? (PS1?) */ - bool is_negative = center_note >> 7; /* center_note & 0x80; */ + is_negative = center_note >> 7; /* center_note & 0x80; */ if (is_negative) center_note = 0x100 - center_note; - /* note/fine seems to always be set to 60, 0? */ + /* note/fine seems to always be set to 0x3C/0x00 */ pitch = ps_note_to_pitch(center_note, center_fine, 0x3C, 0x00); if (pitch > 0x4000) @@ -306,7 +307,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { * 8000 + pitch -48.00 > center=0x74, fine=0x7c */ break; - } + case 0x0d: case 0x0e: case 0x0f: @@ -325,106 +326,109 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { //;VGM_LOG("BNK: stream at %lx + %x\n", stream_offset, stream_size); /* parse names */ - switch(sblk_version) { - case 0x03: - for (i = 0; i < section_entries; i++) { - entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); - entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); - - /* is table2_entry_offset in the range of the expected section */ - if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { - table4_entry_id = i; - break; + /* table4 can be nonexistent */ + if (table4_offset > sblk_offset) { + switch (sblk_version) { + case 0x03: + for (i = 0; i < section_entries; i++) { + entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); + entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); + + /* is table2_entry_offset in the range of the expected section */ + if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { + table4_entry_id = i; + break; + } } - } - - /* table4: - * 0x00: bank name (optional) - * 0x08: name section offset - * 0x0C-0x14: 3 null pointers (reserved?) - * 0x18-0x58: 32 name chunk offset indices - */ - /* Name chunks are organised as - * (name[0] + name[4] + name[8] + name[12]) & 0x1F; - * and using that as the index for the chunk offsets - * name_sect_offset + (chunk_idx[result] * 0x14); - */ - if (read_u8(table4_offset, sf)) - bank_name_offset = table4_offset; - - table4_entries_offset = table4_offset + 0x18; - table4_names_offset = table4_offset + read_u32(table4_offset + 0x08, sf); - - for (i = 0; i < 32; i++) { - table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf); - stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14); - /* searches the chunk until it finds the target name/index, or breaks at empty name */ - while (read_u8(stream_name_offset, sf)) { - /* in case it goes somewhere out of bounds unexpectedly */ - //if ((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + - // read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F != i) - // goto fail; - if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id) - goto loop_break; /* to break out of the for+while loop simultaneously */ + /* table4: + * 0x00: bank name (optional) + * 0x08: name section offset + * 0x0C-0x14: 3 null pointers (reserved?) + * 0x18-0x58: 32 name chunk offset indices + */ + + /* Name chunks are organised as + * (name[0] + name[4] + name[8] + name[12]) & 0x1F; + * and using that as the index for the chunk offsets + * name_sect_offset + (chunk_idx[result] * 0x14); + */ + if (read_u8(table4_offset, sf)) + bank_name_offset = table4_offset; + + table4_entries_offset = table4_offset + 0x18; + table4_names_offset = table4_offset + read_u32(table4_offset + 0x08, sf); + + for (i = 0; i < 32; i++) { + table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf); + stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14); + /* searches the chunk until it finds the target name/index, or breaks at empty name */ + while (read_u8(stream_name_offset, sf)) { + /* in case it goes somewhere out of bounds unexpectedly */ + //if ((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + + // read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F != i) + // goto fail; + if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id) + goto loop_break; /* to break out of the for+while loop simultaneously */ //break; - stream_name_offset += 0x14; + stream_name_offset += 0x14; + } } - } - //goto fail; /* didn't find any valid index? */ - stream_name_offset = 0; + //goto fail; /* didn't find any valid index? */ + stream_name_offset = 0; loop_break: - break; - - //case 0x04: /* different format? */ - //case 0x05: /* different format? */ - - case 0x08: - case 0x09: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - /* find if this sound has an assigned name in table1 */ - for (i = 0; i < section_entries; i++) { - entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf); - - /* rarely (ex. Polara sfx) one name applies to multiple materials, - * from current entry_offset to next entry_offset (section offsets should be in order) */ - if (entry_offset <= table2_entry_offset ) { - table4_entry_id = i; - //break; + break; + + //case 0x04: /* different format? */ + //case 0x05: /* different format? */ + + case 0x08: + case 0x09: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + /* find if this sound has an assigned name in table1 */ + for (i = 0; i < section_entries; i++) { + entry_offset = read_u16(table1_offset + (i * table1_entry_size) + table1_suboffset + 0x00, sf); + + /* rarely (ex. Polara sfx) one name applies to multiple materials, + * from current entry_offset to next entry_offset (section offsets should be in order) */ + if (entry_offset <= table2_entry_offset) { + table4_entry_id = i; + //break; + } } - } - /* table4: */ - /* 0x00: bank name (optional) */ - /* 0x08: header size */ - /* 0x0c: table4 size */ - /* variable: entries */ - /* variable: names (null terminated) */ - if (read_u8(table4_offset, sf)) - bank_name_offset = table4_offset; - - table4_entries_offset = table4_offset + read_u32(table4_offset+0x08, sf); - table4_names_offset = table4_entries_offset + (0x10*section_entries); - //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); - - /* get assigned name from table4 names */ - for (i = 0; i < section_entries; i++) { - int entry_id = read_u32(table4_entries_offset+(i*0x10)+0x0c, sf); - if (entry_id == table4_entry_id) { - stream_name_offset = table4_names_offset + read_u32(table4_entries_offset+(i*0x10)+0x00, sf); - break; + /* table4: */ + /* 0x00: bank name (optional) */ + /* 0x08: header size */ + /* 0x0c: table4 size */ + /* variable: entries */ + /* variable: names (null terminated) */ + if (read_u8(table4_offset, sf)) + bank_name_offset = table4_offset; + + table4_entries_offset = table4_offset + read_u32(table4_offset + 0x08, sf); + table4_names_offset = table4_entries_offset + (0x10 * section_entries); + //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); + + /* get assigned name from table4 names */ + for (i = 0; i < section_entries; i++) { + int entry_id = read_u32(table4_entries_offset + (i * 0x10) + 0x0c, sf); + if (entry_id == table4_entry_id) { + stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10) + 0x00, sf); + break; + } } - } - break; + break; - default: - break; - } + default: + break; + } - //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", stream_offset, stream_size, stream_name_offset); + //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", stream_offset, stream_size, stream_name_offset); + } } From 526345b84eef584912bf65a8c563fcbf384a05f9 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Wed, 12 Jul 2023 18:04:10 +0300 Subject: [PATCH 104/141] Sony BNK: v4 and v5 name support --- src/meta/bnk_sony.c | 63 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 14 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index f639fec9e..3016b985f 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -348,11 +348,11 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { * 0x18-0x58: 32 name chunk offset indices */ - /* Name chunks are organised as - * (name[0] + name[4] + name[8] + name[12]) & 0x1F; - * and using that as the index for the chunk offsets - * name_sect_offset + (chunk_idx[result] * 0x14); - */ + /* Name chunks are organised as + * (name[0] + name[4] + name[8] + name[12]) & 0x1F; + * and using that as the index for the chunk offsets + * name_sect_offset + (chunk_idx[result] * 0x14); + */ if (read_u8(table4_offset, sf)) bank_name_offset = table4_offset; @@ -365,22 +365,57 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { /* searches the chunk until it finds the target name/index, or breaks at empty name */ while (read_u8(stream_name_offset, sf)) { /* in case it goes somewhere out of bounds unexpectedly */ - //if ((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + - // read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F != i) - // goto fail; + if (((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + + read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F) != i) + goto fail; if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id) goto loop_break; /* to break out of the for+while loop simultaneously */ - //break; + //break; stream_name_offset += 0x14; } } //goto fail; /* didn't find any valid index? */ stream_name_offset = 0; - loop_break: + loop_break: break; - //case 0x04: /* different format? */ - //case 0x05: /* different format? */ + case 0x04: + case 0x05: + /* a mix of v3 table1 parsing + v8-v16 table4 parsing */ + for (i = 0; i < section_entries; i++) { + entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); + entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); + + if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { + table4_entry_id = i; + break; + } + } + + /* table4: + * 0x00: bank name (optional) + * 0x08: name entries offset + * 0x0C: name section offset + * + * name entries offset: + * 0x00: name offset in name section + * 0x04: name hash(?) + * 0x08: ? (2x int16) + * 0x0C: section index (int16) + */ + if (read_u8(table4_offset, sf)) + bank_name_offset = table4_offset; + + table4_entries_offset = table4_offset + read_u32(table4_offset + 0x08, sf); + table4_names_offset = table4_offset + read_u32(table4_offset + 0x0C, sf); + + for (i = 0; i < section_entries; i++) { + if (read_u16(table4_entries_offset + (i * 0x10) + 0x0C, sf) == table4_entry_id) { + stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10), sf); + break; + } + } + break; case 0x08: case 0x09: @@ -768,8 +803,8 @@ uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t n * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ - int32_t fine_adjust, fine_idx, note_adjust, note_idx; - int32_t unk1, unk2, unk3; /* TODO: better variable names */ + int fine_adjust, fine_idx, note_adjust, note_idx; + int unk1, unk2, unk3; /* TODO: better variable names */ uint16_t pitch; fine_idx = fine + center_fine; From d2d809eb8e45ec78aa704d5daf1911e46779c5e2 Mon Sep 17 00:00:00 2001 From: kjhmagic <68441599+kjhmagic@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:37:59 +0900 Subject: [PATCH 105/141] Update hca_keys.h subkeys added for D4DJ Groovy Mix (Android) --- src/meta/hca_keys.h | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 7946b7d3f..95fee4ebe 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -424,6 +424,9 @@ static const hcakey_info hcakey_list[] = { {0xc4276ffaee4aadec}, //music_0000005 {0x683d739be9679e61}, //music_0000006 {0xa3adc531c32bb128}, //music_0000007 + {0xbb8f42a806d1fa6}, //music_0000008 + {0xfd6e5a721921d936}, //music_0000009 + {0x7749847207a5f0da}, //music_0000010 {0x52d065d9ccdb8696}, //music_0110001 {0xba26e58923a5da5d}, //music_0110002 {0x5b877af6e52af19b}, //music_0110003 @@ -454,6 +457,7 @@ static const hcakey_info hcakey_list[] = { {0x22c6b455883b1c28}, //music_0110030 {0xff2ae68fa067f80a}, //music_0110031 {0x422ca19b0fa5c7c0}, //music_0110032 + {0x3b11592a696da747}, //music_0110033 {0xfb647d074e53fab6}, //music_0120001 {0xc24049b9f7ed3105}, //music_0120002 {0xdc128f2fd48bf4b}, //music_0120003 @@ -495,6 +499,7 @@ static const hcakey_info hcakey_list[] = { {0xe38b758bcadfc621}, //music_0210018 {0x3399e970670db2ba}, //music_0210019 {0x1cb76530af356c05}, //music_0210020 + {0x2ae40b627c7125d7}, //music_0210021 {0x15bb78c31db0a0b6}, //music_0220001 {0x59b1257242c40109}, //music_0220002 {0xdb402bd08d522f34}, //music_0220003 @@ -576,6 +581,7 @@ static const hcakey_info hcakey_list[] = { {0x685b5601a43b6c60}, //music_0410018 {0x75927596a180f3e3}, //music_0410019 {0xc3d36676d54255c5}, //music_0410020 + {0x41283c6f06db3cdd}, //music_0410021 {0x5d1f3fdbbb036f8d}, //music_0420001 {0xc04264e8f34ad5c0}, //music_0420002 {0x8f0e96b4f71f724f}, //music_0420003 @@ -615,6 +621,8 @@ static const hcakey_info hcakey_list[] = { {0xb069a5c5e2d93edf}, //music_0510019 {0x30f9dcefa450733a}, //music_0510020 {0xf85695960e2dcb7f}, //music_0510021 + {0x212604f36a4ddb0c}, //music_0510022 + {0xef7ee9169b194770}, //music_0510023 {0x15f82c1617013c36}, //music_0520001 {0xc7da8e6f0e2fe399}, //music_0520002 {0xe350bffcdc9cb686}, //music_0520003 @@ -655,6 +663,8 @@ static const hcakey_info hcakey_list[] = { {0x7aece54359beac21}, //music_0610021 {0x7c9332be25e5c95a}, //music_0610022 {0x415eef25f84e8c2e}, //music_0610023 + {0xfd2237157af70152}, //music_0610024 + {0xf6c91cba66c3fe68}, //music_0610025 {0x8258ddd6a1d0849b}, //music_0620001 {0x1dd21a1244ca12f1}, //music_0620002 {0xfdec74b23d8b494b}, //music_0620003 @@ -674,15 +684,23 @@ static const hcakey_info hcakey_list[] = { {0x5c1195d8afcb1901}, //music_0620017 {0x1ad8db767d9ba4a7}, //music_0620018 {0x9bc820aa161b0f08}, //music_0620019 + {0x85f26fa7befc2b5a}, //music_0810000 {0xd1df27a57399613e}, //music_0810001 {0xd37ec4cb304e16ae}, //music_0810002 + {0x4582fedda6a62aa8}, //music_0810003 + {0xb31ea911ea8aba81}, //music_0810004 {0x1e99d14d97ab82c5}, //music_0820001 {0x5bf7cefecda8bcb2}, //music_0820002 {0x9cf7ab0ccafa374e}, //music_0820003 + {0x7a9e4b710716a8e2}, //music_0910000 {0x972b52f3dfaa387a}, //music_0910001 {0x407a4b6c3dcf2509}, //music_0910002 + {0x838be1aa4dc372bb}, //music_0910003 + {0xc03bac003c24471d}, //music_0910004 + {0xf864df0abe22ec49}, //music_0910005 {0x4683c57919dbdeee}, //music_0920001 {0x126d0d20ad7f0401}, //music_0920002 + {0x1652eb8bf3cea8f5}, //music_0920003 {0x2a47feac8dc3ca9c}, //music_3010001 {0x9ebbaf63ffe9d9ef}, //music_3010002 {0xe553dba6592293d8}, //music_3010003 @@ -700,10 +718,16 @@ static const hcakey_info hcakey_list[] = { {0x5e23d8a2488bc715}, //music_3010016 {0x198cc607e20dd264}, //music_3010017 {0x31a9ab25b5dff424}, //music_3010018 + {0x86e823895bb0bec6}, //music_3010019 {0x17f53cfa841f41b5}, //music_3010020 {0x4992a33be3ba81dd}, //music_3010021 {0x86d0ab836f09a599}, //music_3010022 + {0x2a5eefc1987bf7fb}, //music_3010023 {0x157f20b466d75228}, //music_3010024 + {0x13cada13f45f432b}, //music_3010025 + {0xe0f08378be17633b}, //music_3010026 + {0xaf81e107cd20ba90}, //music_3010027 + {0x4efe51d362dcb6b1}, //music_3010028 {0xfd3ea450350d666f}, //music_3020001 {0x5e91a3790c32e2b3}, //music_3020002 {0x358adfd1bbd3a95e}, //music_3020003 @@ -719,11 +743,18 @@ static const hcakey_info hcakey_list[] = { {0x3d01826fe053ddda}, //music_3020014 {0xa6a6426caed68f7c}, //music_3020015 {0x34cc16f635101f02}, //music_3020016 + {0xc92c94fdc988b8fa}, //music_3020017 {0x4429ed54ca45a36d}, //music_3020018 {0xcc935f3ebbb7bb94}, //music_3020019 {0x4a1d57f0db140c12}, //music_3020020 {0x8ddea25a12f93099}, //music_3020022 {0xf754248dcd46287e}, //music_3020023 + {0xa3c06ffa7775a274}, //music_3020024 + {0x427be43aa233382c}, //music_3020025 + {0x4ec96dd7db2adfd7}, //music_3020026 + {0x9f12a5003f112aaa}, //music_3020028 + {0x38edf73f19401e1c}, //music_3020030 + {0xfa2c72797fa3e388}, //music_3020031 {0xdfad847a86a126bb}, //music_5030001 {0x711ef85045b8c26e}, //music_5030002 {0xff7640b46d72b337}, //music_5030003 @@ -989,6 +1020,7 @@ static const hcakey_info hcakey_list[] = { {0x1be3e8255dde31e3}, //music_5050147 {0x58b735f1a68c9a81}, //music_5050148 {0x5b3cb281d89019db}, //music_5050149 + {0x74f39448d2b75d4d}, //music_5050150 {0x2b1a0269a3d890d4}, //music_5050151 {0x74e058fd628364c9}, //music_5050152 {0x3ade68d4857395c0}, //music_5050153 @@ -1042,6 +1074,29 @@ static const hcakey_info hcakey_list[] = { {0x929ca6a5e8e0445}, //music_5050206 {0xf0de6097ea78513c}, //music_5050207 {0xcde0de0e1216bdea}, //music_5050208 + {0xb496e9301bfc57c4}, //music_5050209 + {0xff4db63086831e8f}, //music_5050210 + {0x21cd7a36d33daae9}, //music_5050211 + {0x88fe1d5592979a66}, //music_5050212 + {0x1782668d98097f3b}, //music_5050213 + {0xb174215f3ed746e3}, //music_5050214 + {0x445aa44e5029d76b}, //music_5050215 + {0x39b3d29fc04211ed}, //music_5050216 + {0x6856a8773f3e7712}, //music_5050217 + {0x7f08330d7d971292}, //music_5050218 + {0x6ac19245cd7e8de0}, //music_5050219 + {0x7a0ed12fd8b5a9e8}, //music_5050220 + {0xc13b8037e2be01bf}, //music_5050221 + {0x5856576aa5c0a59f}, //music_5050222 + {0xe8286a95b8f38dd1}, //music_5050223 + {0x48015b291de44ff3}, //music_5050224 + {0x4521644fd1682bc0}, //music_5050226 + {0x808e307ec28b9ef0}, //music_5050227 + {0x6a4493f6e7dcce6c}, //music_5050228 + {0xd6bc23de632b00e0}, //music_5050229 + {0x7268ea33e33cbcfa}, //music_5050230 + {0x2de61d98bc2cea48}, //music_5050231 + {0xd8bdb31ab72c355b}, //music_5050242 {0x52c250eade92393b}, //music_9010001 {0xf66e6bb5b0599b07}, //music_9010002 {0x8582b5a60dbbf948}, //music_9010003 From 7cb570b2adde6dbf46328e90d0616fa2d0894d60 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 11:01:50 +0200 Subject: [PATCH 106/141] Add more SqueakStream/SqueakSample codecs --- src/coding/coding.h | 1 + src/coding/speex_decoder.c | 34 +++++++-- src/libvgmstream.vcxproj | 2 + src/libvgmstream.vcxproj.filters | 6 ++ src/meta/squeak.c | 114 +++++++++++++++++++++++-------- src/util/endianness.h | 6 +- src/util/layout_utils.c | 71 +++++++++++++++++++ src/util/layout_utils.h | 12 ++++ src/vgmstream.h | 1 + 9 files changed, 213 insertions(+), 34 deletions(-) create mode 100644 src/util/layout_utils.c create mode 100644 src/util/layout_utils.h diff --git a/src/coding/coding.h b/src/coding/coding.h index aa52ce7da..c41f7f5b7 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -588,6 +588,7 @@ void free_celt_fsb(celt_codec_data* data); typedef struct speex_codec_data speex_codec_data; speex_codec_data* init_speex_ea(int channels); +speex_codec_data* init_speex_torus(int channels); void decode_speex(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t samples_to_do); void reset_speex(speex_codec_data* data); void seek_speex(VGMSTREAM* vgmstream, int32_t num_sample); diff --git a/src/coding/speex_decoder.c b/src/coding/speex_decoder.c index 5bac10387..85186f0f0 100644 --- a/src/coding/speex_decoder.c +++ b/src/coding/speex_decoder.c @@ -10,15 +10,19 @@ #define SPEEX_DECODE_OK 0 /* -1 for end of stream, -2 corrupt stream */ +typedef enum { EA, TORUS } type_t; + /* opaque struct */ struct speex_codec_data { + type_t type; + /* config */ int channels; int samples_discard; int encoder_delay; uint8_t buf[SPEEX_MAX_FRAME_SIZE]; - uint8_t frame_size; + int frame_size; int16_t* samples; int frame_samples; @@ -32,7 +36,7 @@ struct speex_codec_data { /* raw SPEEX */ -speex_codec_data* init_speex_ea(int channels) { +static speex_codec_data* init_speex(type_t type, int channels) { int res, sample_rate; speex_codec_data* data = NULL; @@ -40,7 +44,9 @@ speex_codec_data* init_speex_ea(int channels) { data = calloc(1, sizeof(speex_codec_data)); if (!data) goto fail; - //TODO: EA uses N decoders, unknown layout (known samples are mono) + data->type = type; + + //TODO: unknown layout (known samples are mono, EA: N decoders, Torus: N too?) data->channels = channels; if (channels != 1) goto fail; @@ -78,6 +84,14 @@ speex_codec_data* init_speex_ea(int channels) { return NULL; } +speex_codec_data* init_speex_ea(int channels) { + return init_speex(EA, channels); +} + +speex_codec_data* init_speex_torus(int channels) { + return init_speex(TORUS, channels); +} + static int decode_frame(speex_codec_data* data) { int res; @@ -102,8 +116,18 @@ static int decode_frame(speex_codec_data* data) { static int read_frame(speex_codec_data* data, VGMSTREAMCHANNEL* stream) { size_t bytes; - data->frame_size = read_u8(stream->offset, stream->streamfile); - stream->offset += 0x01; + switch(data->type) { + case EA: + data->frame_size = read_u8(stream->offset, stream->streamfile); + stream->offset += 0x01; + break; + case TORUS: + data->frame_size = read_u16le(stream->offset, stream->streamfile); + stream->offset += 0x02; + break; + default: + break; + } if (data->frame_size == 0) goto fail; bytes = read_streamfile(data->buf, stream->offset, data->frame_size, stream->streamfile); diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index c3145a54d..80c2dc9ea 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -175,6 +175,7 @@ + @@ -737,6 +738,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index d67ac7cdc..dd7c7f133 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -350,6 +350,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2032,6 +2035,9 @@ util\Source Files + + util\Source Files + util\Source Files diff --git a/src/meta/squeak.c b/src/meta/squeak.c index 5e283e0f8..710d416aa 100644 --- a/src/meta/squeak.c +++ b/src/meta/squeak.c @@ -2,9 +2,10 @@ #include "../layout/layout.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/layout_utils.h" -#define SQUEAK_MAX_CHANNELS 8 /* seen 3 in some voices */ -typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA } squeak_type_t; +#define SQUEAK_MAX_CHANNELS 6 /* seen 3 in some voices */ +typedef enum { PCM16LE, PCM16BE, PCM8, DSP, PSX, MSIMA, IMA, XMA2, VORBIS, SPEEX } squeak_type_t; typedef struct { squeak_type_t type; @@ -26,6 +27,8 @@ typedef struct { uint32_t coef_offset; uint32_t coef_spacing; + uint32_t data_offsets[SQUEAK_MAX_CHANNELS]; + uint32_t coef_offsets[SQUEAK_MAX_CHANNELS]; uint32_t data_size; bool big_endian; @@ -37,22 +40,21 @@ typedef struct { static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h); -/* SqueakStream - from Torus games (as identified in .hnk subdirs) */ +/* SqueakStream - from Torus games (name/engine as identified in .hnk subdirs) */ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { squeak_header_t h = {0}; bool is_old = false; /* checks */ - h.big_endian = false; - if (is_id32be(0x00,sf, "RAWI")) { - h.big_endian = false; + if (is_id32be(0x00,sf, "RAWI") || is_id32be(0x00,sf, "VORB") || is_id32be(0x00,sf, "SPEX")) { + h.big_endian = false; /* VORB/SPEX only use vorbis/speex but no apparent diffs */ } else if (is_id32be(0x00,sf, "IWAR")) { h.big_endian = true; /* Wii/PS3/X360 */ } else { - /* no header id so test codec in dumb endian */ + /* no header id in early version so test codec in dumb endian */ if ((read_u32le(0x00,sf) & 0x00FFFFFF) > 9 || (read_u32be(0x00,sf) & 0x00FFFFFF) > 9) return NULL; is_old = true; @@ -137,13 +139,17 @@ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { if (h.extb_offset > h.name_offset) return NULL; switch(h.codec) { - case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ - case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */ - case 0x02: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */ - case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ - case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */ - case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */ + case 0x00: h.type = DSP; break; /* Turbo Super Stunt Squad (Wii/3DS), Penguins of Madagascar (Wii/U/3DS) */ + case 0x01: h.type = PCM16LE; break; /* Falling Skies The Game (PC) */ + case 0x02: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360)-be, Scooby Doo and the Spooky Swamp (PC)-le */ + case 0x03: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ + case 0x04: h.type = MSIMA; break; /* Barbie Dreamhouse Party (DS) */ + case 0x05: h.type = PCM8; break; /* Scooby Doo and the Spooky Swamp (DS), Scooby Doo! First Frights (DS) */ + case 0x07: h.type = SPEEX; break; /* Scooby Doo and the Spooky Swamp (PC) */ + case 0x08: h.type = VORBIS; break; /* Scooby Doo and the Spooky Swamp (PC) */ + case 0x09: h.type = MSIMA; break; /* Turbo Super Stunt Squad (DS) */ default: + VGM_LOG("SqueakStream: unknown codec %x\n", h.codec); return NULL; } @@ -151,7 +157,7 @@ VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf) { } -/* SqueakSample - from Torus games (as identified in .hnk subdirs) */ +/* SqueakSample - from Torus games (name/engine as identified in .hnk subdirs) */ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { squeak_header_t h = {0}; @@ -187,7 +193,6 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { h.loop_end = read_s32(offset + 0x0c,sf); if (h.loop_start > h.loop_end || h.loop_end > h.num_samples) return NULL; h.codec = read_s32(offset + 0x10,sf); - if (h.codec > 0x09) return NULL; h.sample_rate = read_s32(offset + 0x14,sf); if (h.sample_rate > 48000 || h.sample_rate < 0) return NULL; @@ -206,14 +211,25 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { h.external_data = (h.data_offset & 0xF0000000); h.data_offset = h.data_offset & 0x0FFFFFFF; - /* absolute offsets, should read for each channel but simplify - * (also channels may have padding, but files end with no padding) */ - if (h.channels > 1) { - int separation = h.codec == 0xFFFE0001 ? 0x68 : 0x2c; - uint32_t data_offset = read_u32le(offset + 0x04 + 1 * separation, sf) & 0x0FFFFFFF; - uint32_t coef_offset = read_u32le(offset + 0x28 + 1 * separation, sf); - h.interleave = data_offset - h.data_offset; /* distance */ - h.coef_spacing = coef_offset - h.coef_offset; + /* each channel has its own info but mostly repeats (data may have padding, but files end with no padding) */ + { + int separation = 0; + switch(h.codec) { + case 0xFFFE0001: + case 0x0001FFFE: + case 0x01660001: separation = 0x68; break; + default: separation = 0x2c; break; + } + + for (int i = 0; i < h.channels; i++) { + h.data_offsets[i] = read_u32le(offset + 0x04 + i * separation, sf) & 0x0FFFFFFF; + h.coef_offsets[i] = read_u32le(offset + 0x28 + i * separation, sf); + } + + if (h.channels > 1) { + h.interleave = h.data_offsets[1] - h.data_offsets[0]; + h.coef_spacing = h.coef_offsets[1] - h.coef_offsets[0]; + } } switch(h.codec) { @@ -223,8 +239,11 @@ VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf) { case 0x07: h.type = PSX; break; /* How to Train Your Dragon 2 (PS3), Falling Skies The Game (PS3) */ case 0x08: /* (same as below for unlooped audio) */ case 0x09: h.type = IMA; break; /* Scooby-Doo! First Frights (DS), Turbo Super Stunt Squad (DS) */ - case 0xFFFE0001: h.type = h.big_endian ? PCM16BE : PCM16LE; break; /* Falling Skies The Game (X360) */ + case 0xFFFE0001: h.type = PCM16BE; break; /* Falling Skies The Game (X360) */ + case 0x0001FFFE: h.type = PCM16LE; break; /* Scooby Doo and the Spooky Swamp (PC), Monster High: New Ghoul in School (PC) */ + case 0x01660001: h.type = XMA2; break; /* Rise of the Guardians (X360) */ default: + VGM_LOG("SqueakSample: unknown codec %x\n", h.codec); return NULL; } @@ -295,6 +314,7 @@ static STREAMFILE* load_assets(STREAMFILE* sf, squeak_header_t* h) { static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sb = NULL; + STREAMFILE* sf_body = NULL; /* common */ int loop_flag = h->loop_end > 0; @@ -306,6 +326,7 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* if (!sb) goto fail; } + sf_body = sb ? sb : sf; /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(h->channels, loop_flag); @@ -334,12 +355,13 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ + break; + case PCM16BE: vgmstream->coding_type = coding_PCM16BE; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = h->interleave; /* not 0x02 */ - /* etbl_offset may set offsets to RIFF fmts per channel) */ break; case PSX: @@ -358,7 +380,7 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* vgmstream->coding_type = coding_MS_IMA; vgmstream->layout_type = layout_none; //vgmstream->interleave_block_size = h->interleave; /* unused? (mono) */ - vgmstream->frame_size = 0x20; + vgmstream->frame_size = h->codec == 0x04 ? 0x400 : 0x20; break; case IMA: @@ -370,8 +392,46 @@ static VGMSTREAM* init_vgmstream_squeak_common(STREAMFILE* sf, squeak_header_t* h->data_offset += 0x04; break; +#ifdef VGM_USE_FFMPEG + case XMA2: { + /* uses separate mono streams */ + vgmstream->coding_type = coding_FFmpeg; + for (int i = 0; i < h->channels; i++) { + uint32_t offset = h->data_offsets[i]; + uint32_t next_offset = (i + 1 == h->channels) ? get_streamfile_size(sf_body) : h->data_offsets[i+1]; + uint32_t data_size = next_offset - offset; + int layer_channels = 1; + + vgmstream->codec_data = init_ffmpeg_xma2_raw(sf_body, offset, data_size, h->num_samples, layer_channels, h->sample_rate, 0, 0); + if (!layered_add_codec(vgmstream, 0, layer_channels)) + goto fail; + } + if (!layered_add_done(vgmstream)) + goto fail; + + break; + } +#endif +#ifdef VGM_USE_VORBIS + case VORBIS: + vgmstream->codec_data = init_ogg_vorbis(sf_body, h->data_offset, 0, NULL); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_OGG_VORBIS; + vgmstream->layout_type = layout_none; + + break; +#endif +#ifdef VGM_USE_SPEEX + case SPEEX: { + vgmstream->codec_data = init_speex_torus(h->channels); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_SPEEX; + vgmstream->layout_type = layout_none; + + break; + } +#endif default: - vgm_logi("RAWI: unknown codec %x (report)\n", h->codec); goto fail; } diff --git a/src/util/endianness.h b/src/util/endianness.h index ef67ef055..ab95f352e 100644 --- a/src/util/endianness.h +++ b/src/util/endianness.h @@ -1,10 +1,12 @@ -#ifndef _UTIL_ENDIAN_H -#define _UTIL_ENDIAN_H +#ifndef _ENDIANNESS_H +#define _ENDIANNESS_H #include "../streamfile.h" #include "reader_get.h" #include "reader_sf.h" +typedef uint64_t (*read_u64_t)(off_t, STREAMFILE*); +typedef int64_t (*read_s64_t)(off_t, STREAMFILE*); typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*); typedef int32_t (*read_s32_t)(off_t, STREAMFILE*); typedef uint16_t (*read_u16_t)(off_t, STREAMFILE*); diff --git a/src/util/layout_utils.c b/src/util/layout_utils.c new file mode 100644 index 000000000..70d39358a --- /dev/null +++ b/src/util/layout_utils.c @@ -0,0 +1,71 @@ +#include "layout_utils.h" + +#include "../vgmstream.h" +#include "../layout/layout.h" + +bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels) { + if (!vs || !vs->codec_data) { + goto fail; + } + + if (!layer_channels) + layer_channels = 1; + if (!layers) + layers = vs->channels / layer_channels; + + int i; + layered_layout_data* data; + + switch(vs->layout_type) { + case layout_segmented: //to be improved + goto fail; + + case layout_layered: + data = vs->layout_data; + + i = data->curr_layer; + break; + + default: + data = init_layout_layered(layers); + if (!data) goto fail; + vs->layout_data = data; + vs->layout_type = layout_layered; + + i = 0; + break; + } + + data->layers[i] = allocate_vgmstream(layer_channels, vs->loop_flag); + if (!data->layers[i]) goto fail; + + data->layers[i]->meta_type = vs->meta_type; + data->layers[i]->sample_rate = vs->sample_rate; + data->layers[i]->num_samples = vs->num_samples; + data->layers[i]->loop_start_sample = vs->loop_start_sample; + data->layers[i]->loop_end_sample = vs->loop_end_sample; + + data->layers[i]->codec_data = vs->codec_data; + if (!data->layers[i]->codec_data) goto fail; + data->layers[i]->coding_type = vs->coding_type; + data->layers[i]->layout_type = layout_none; + + vs->codec_data = NULL; /* moved to layer, don't hold it */ + + data->curr_layer++; + + return true; +fail: + return false; +} + +bool layered_add_done(VGMSTREAM* vs) { + //TODO: some extra checks/setup? + + if (!setup_layout_layered(vs->layout_data)) + goto fail; + + return true; +fail: + return false; +} diff --git a/src/util/layout_utils.h b/src/util/layout_utils.h new file mode 100644 index 000000000..d52472195 --- /dev/null +++ b/src/util/layout_utils.h @@ -0,0 +1,12 @@ +#ifndef _LAYOUTS_UTIL_H +#define _LAYOUTS_UTIL_H + +#include "../vgmstream.h" + +/* add a new layer from codec data (setups layout if needed) + * codec is passed in the vs for easier free/etc control */ +bool layered_add_codec(VGMSTREAM* vs, int layers, int layer_channels); + +/* call when done adding layers */ +bool layered_add_done(VGMSTREAM* vs); +#endif diff --git a/src/vgmstream.h b/src/vgmstream.h index 9038f4045..65854119a 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -273,6 +273,7 @@ typedef struct { int input_channels; /* internal buffer channels */ int output_channels; /* resulting channels (after mixing, if applied) */ int external_looping; /* don't loop using per-layer loops, but layout's own looping */ + int curr_layer; /* helper */ } layered_layout_data; From 738c9a419975b3549d8213edc0e2775196fbfa5a Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 11:02:03 +0200 Subject: [PATCH 107/141] changelog: tweaks --- .github/changelog.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/changelog.py b/.github/changelog.py index 18616c0c4..49d5c9ebb 100644 --- a/.github/changelog.py +++ b/.github/changelog.py @@ -46,15 +46,16 @@ def convert_git(stdout): def load_git(): if not USE_GIT: raise ValueError("git disabled") - + args = ['git', 'describe', '--tags', '--abbrev=0'] proc = subprocess.run(args, capture_output=True) if proc.returncode != 0: raise ValueError("git exception") latest_tag = proc.stdout.decode('utf-8').strip() - + + # no apparent portable way to get a utc timezone in date=format #args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S"', '--max-count', str(GIT_MAX_MERGES) ] - args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S"', '%s..HEAD' % (latest_tag)] + args = ['git','--no-pager','log', '--merges', '--date=format:"%Y-%m-%d %H:%M:%S %z"', '%s..HEAD' % (latest_tag)] proc = subprocess.run(args, capture_output=True) if proc.returncode != 0: raise ValueError("git exception") @@ -160,7 +161,7 @@ def get_lines(short_log=False): if short_log: lines = [] else: - curr_date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + curr_date = datetime.datetime.now(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S %z") lines = [ '### CHANGELOG', '(latest changes from previous release, generated on %s)' % (curr_date), From dbeb538d1a7611e7d595cf2d9a67f4c7ced9dfe7 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 11:03:29 +0200 Subject: [PATCH 108/141] ivaud: improve detection --- src/meta/ivaud.c | 21 +++++++++++++-------- src/vgmstream.c | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/meta/ivaud.c b/src/meta/ivaud.c index 43113eac3..13ed4888d 100644 --- a/src/meta/ivaud.c +++ b/src/meta/ivaud.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" typedef struct { int is_music; @@ -31,13 +32,13 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) { int loop_flag; /* checks */ - /* (hashed filenames are likely extensionless and .ivaud is added by tools) */ + /* (hashed filenames are likely extensionless, .ivaud is added by tools) */ if (!check_extensions(sf, "ivaud,")) - goto fail; + return NULL; /* check header */ if (!parse_ivaud_header(sf, &ivaud)) - goto fail; + return NULL; loop_flag = 0; @@ -121,9 +122,9 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) { /* Parse Rockstar's .ivaud header (much info from SparkIV). */ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { int target_subsong = sf->stream_index; - uint64_t (*read_u64)(off_t,STREAMFILE*); - uint32_t (*read_u32)(off_t,STREAMFILE*); - uint16_t (*read_u16)(off_t,STREAMFILE*); + read_u64_t read_u64; + read_u32_t read_u32; + read_u16_t read_u16; ivaud->big_endian = read_u32be(0x00, sf) == 0; /* table offset at 0x04 > BE (64b) */ @@ -131,6 +132,10 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { read_u32 = ivaud->big_endian ? read_u32be : read_u32le; read_u16 = ivaud->big_endian ? read_u16be : read_u16le; + uint64_t table_offset = read_u64(0x00,sf); + if (table_offset > 0x10000) /* arbitrary max, typically 0x1c~0x1000 */ + return 0; + /* use bank's stream count to detect */ ivaud->is_music = (read_u32(0x10,sf) == 0); @@ -138,7 +143,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { off_t block_table_offset, channel_table_offset, channel_info_offset; /* music header */ - block_table_offset = read_u64(0x00,sf); + block_table_offset = table_offset; ivaud->block_count = read_u32(0x08,sf); ivaud->block_size = read_u32(0x0c,sf); /* uses padded blocks */ /* 0x10(4): stream count */ @@ -185,7 +190,7 @@ static int parse_ivaud_header(STREAMFILE* sf, ivaud_header* ivaud) { off_t stream_table_offset, stream_info_offset, stream_entry_offset, offset; /* bank header */ - stream_table_offset = read_u64(0x00,sf); + stream_table_offset = table_offset; /* 0x08(8): header size? start offset? */ ivaud->total_subsongs = read_u32(0x10,sf); /* 0x14(4): unknown */ diff --git a/src/vgmstream.c b/src/vgmstream.c index 745f3b96f..85729a9d7 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -170,7 +170,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_zsd, init_vgmstream_vgs_ps, init_vgmstream_redspark, - init_vgmstream_ivaud, init_vgmstream_wii_wsd, init_vgmstream_dsp_ndp, init_vgmstream_ps2_sps, @@ -533,6 +532,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_mic_koei, init_vgmstream_seb, init_vgmstream_tgc, + init_vgmstream_ivaud, /* need companion files */ init_vgmstream_pos, init_vgmstream_sli_loops, From bf9cc7f63588b17c8a497b434d5063200361993b Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 11:06:14 +0200 Subject: [PATCH 109/141] cleanup: rename sxd to sndx --- src/formats.c | 2 +- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +++--- src/meta/meta.h | 2 +- src/meta/{sxd.c => sndx.c} | 6 +++--- src/vgmstream.c | 2 +- src/vgmstream_types.h | 4 ++-- 7 files changed, 12 insertions(+), 12 deletions(-) rename src/meta/{sxd.c => sndx.c} (97%) diff --git a/src/formats.c b/src/formats.c index 72f942235..023b542e9 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1242,7 +1242,7 @@ static const meta_info meta_info_list[] = { {meta_ASTB, "Capcom ASTB header"}, {meta_WWISE_RIFF, "Audiokinetic Wwise RIFF header"}, {meta_UBI_RAKI, "Ubisoft RAKI header"}, - {meta_SXD, "Sony SXD header"}, + {meta_SNDX, "Sony SNDX header"}, {meta_OGL, "Shin'en OGL header"}, {meta_MC3, "Paradigm MC3 header"}, {meta_GHS, "Hexadrive GHS/S_P_STH header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 80c2dc9ea..adcd81b02 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -628,6 +628,7 @@ + @@ -652,7 +653,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index dd7c7f133..e136f555c 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1705,6 +1705,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files @@ -1777,9 +1780,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index e678c9717..93d52d6ef 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -574,7 +574,7 @@ VGMSTREAM * init_vgmstream_ubi_raki(STREAMFILE* streamFile); VGMSTREAM* init_vgmstream_pasx(STREAMFILE* sf); -VGMSTREAM * init_vgmstream_sxd(STREAMFILE *streamFile); +VGMSTREAM * init_vgmstream_sndx(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_ogl(STREAMFILE *streamFile); diff --git a/src/meta/sxd.c b/src/meta/sndx.c similarity index 97% rename from src/meta/sxd.c rename to src/meta/sndx.c index 4cbd97fc9..798990cd6 100644 --- a/src/meta/sxd.c +++ b/src/meta/sndx.c @@ -3,8 +3,8 @@ #include "../util/chunks.h" -/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ -VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) { +/* SXDF/SXDS - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ +VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sf_sxd1 = NULL, *sf_sxd2 = NULL, *sf_data = NULL, *sf_h = NULL, *sf_b = NULL; off_t start_offset, chunk_offset, first_offset = 0x60, name_offset = 0; @@ -180,7 +180,7 @@ VGMSTREAM* init_vgmstream_sxd(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_SXD; + vgmstream->meta_type = meta_SNDX; vgmstream->sample_rate = sample_rate; vgmstream->num_samples = num_samples; diff --git a/src/vgmstream.c b/src/vgmstream.c index 85729a9d7..6f7444b47 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -283,7 +283,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ubi_raki, init_vgmstream_pasx, init_vgmstream_xma, - init_vgmstream_sxd, + init_vgmstream_sndx, init_vgmstream_ogl, init_vgmstream_mc3, init_vgmstream_ghs, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index fed129085..e25e0ad62 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -529,7 +529,7 @@ typedef enum { meta_ASTB, meta_WWISE_RIFF, /* Audiokinetic Wwise RIFF/RIFX */ meta_UBI_RAKI, /* Ubisoft RAKI header (Rayman Legends, Just Dance 2017) */ - meta_SXD, /* Sony SXD (Gravity Rush, Freedom Wars PSV) */ + meta_SNDX, meta_OGL, /* Shin'en Wii/WiiU (Jett Rocket (Wii), FAST Racing NEO (WiiU)) */ meta_MC3, /* Paradigm games (T3 PS2, MX Rider PS2, MI: Operation Surma PS2) */ meta_GHS, @@ -537,7 +537,7 @@ typedef enum { meta_MTA2, meta_XA_XA30, meta_XA_04SW, - meta_TXTH, /* generic text header */ + meta_TXTH, meta_SK_AUD, /* Silicon Knights .AUD (Eternal Darkness GC) */ meta_AHX, meta_STMA, From b67406a683b1e2fe85bd8eafc010ee32657d9d0c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 13:43:10 +0200 Subject: [PATCH 110/141] Add SNDS format --- src/formats.c | 1 + src/libvgmstream.vcxproj | 1 + src/libvgmstream.vcxproj.filters | 3 + src/meta/meta.h | 1 + src/meta/snds.c | 112 +++++++++++++++++++++++++++++++ src/vgmstream.c | 1 + src/vgmstream_types.h | 1 + 7 files changed, 120 insertions(+) create mode 100644 src/meta/snds.c diff --git a/src/formats.c b/src/formats.c index 023b542e9..cd1d88e54 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1412,6 +1412,7 @@ static const meta_info meta_info_list[] = { {meta_AWD, "RenderWare Audio Wave Dictionary header"}, {meta_SQUEAKSTREAM, "Torus SqueakStream header"}, {meta_SQUEAKSAMPLE, "Torus SqueakSample header"}, + {meta_SNDS, "Sony SNDS header"}, }; void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) { diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index adcd81b02..1171523c3 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -628,6 +628,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index e136f555c..af34e7846 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1705,6 +1705,9 @@ meta\Source Files + + meta\Source Files + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 93d52d6ef..1bbc59e65 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -981,5 +981,6 @@ VGMSTREAM* init_vgmstream_pwb(STREAMFILE* sf); VGMSTREAM* init_vgmstream_squeakstream(STREAMFILE* sf); VGMSTREAM* init_vgmstream_squeaksample(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf); #endif /*_META_H*/ diff --git a/src/meta/snds.c b/src/meta/snds.c new file mode 100644 index 000000000..bb5ec7c22 --- /dev/null +++ b/src/meta/snds.c @@ -0,0 +1,112 @@ +#include "meta.h" +#include "../coding/coding.h" +#include "../util/chunks.h" + + +/* SSDD - Sony/SCE's SNDS lib format (cousin of SGXD/SNDX) */ +VGMSTREAM* init_vgmstream_snds(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + uint32_t stream_offset, stream_size; + int loop_flag, channels, codec, sample_rate; + int32_t num_samples, loop_start, loop_end, encoder_delay; + uint32_t at9_config = 0; + int total_subsongs, target_subsong = sf->stream_index; + + + /* checks */ + if (!is_id32be(0x00, sf, "SSDD")) + return NULL; + + if (read_u32le(0x04, sf) != get_streamfile_size(sf)) + return NULL; + /* 0x10: file name */ + + /* (extensionless): no apparent extension in debug strings, though comparing other SCE libs possibly ".ssd" */ + if (!check_extensions(sf,"")) + return NULL; + + /* from debug info seems to have free chunks but known files always use the same and 1 subsong */ + off_t base_offset = 0x60, wavs_offset = 0; + if (!find_chunk_le(sf, get_id32be("WAVS"),base_offset,0, &wavs_offset,NULL)) + return NULL; + + if (read_u16le(wavs_offset + 0x00, sf) != 0x2c) /* entry size? */ + return NULL; + + total_subsongs = read_s16le(wavs_offset + 0x02, sf); + if (target_subsong == 0) target_subsong = 1; + if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) return NULL; + if (total_subsongs != 1) return NULL; /* not seen */ + + /* read stream header */ + { + uint32_t head_offset = wavs_offset + 0x04 + 0x2c * (target_subsong - 1); + /* 0x00: null/flags? */ + /* 0x04: null/offset? */ + /* 0x0c: null/offset? */ + codec = read_u8(head_offset + 0x0c, sf); + channels = read_u16le(head_offset + 0x0d, sf); + /* 0x0e: null? */ + sample_rate = read_u32le(head_offset + 0x10, sf); + at9_config = read_u32le(head_offset + 0x14, sf); /* !!! (only known use of this lib is Android/iOS) */ + num_samples = read_s32le(head_offset + 0x18, sf); + loop_start = read_s32le(head_offset + 0x1c, sf); + loop_end = read_s32le(head_offset + 0x20, sf); + encoder_delay = read_s32le(head_offset + 0x24, sf); + stream_size = read_u32le(head_offset + 0x28, sf); + + loop_flag = loop_end > 0; + } + + /* CUES chunk: cues (various fields, also names) */ + /* CUNS chunk: cue names (flags + hash + offset, then names) */ + + off_t wavd_offset = 0; + if (!find_chunk_le(sf, get_id32be("WAVD"),wavs_offset - 0x08,0, &wavd_offset,NULL)) + return NULL; + stream_offset = wavd_offset + 0x08; + + + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); + if (!vgmstream) goto fail; + + vgmstream->meta_type = meta_SNDS; + vgmstream->sample_rate = sample_rate; + vgmstream->num_samples = num_samples; + vgmstream->loop_start_sample = loop_start; + vgmstream->loop_end_sample = loop_end; + + vgmstream->num_streams = total_subsongs; + vgmstream->stream_size = stream_size; + + switch (codec) { +#ifdef VGM_USE_ATRAC9 + case 0x41: { + atrac9_config cfg = {0}; + + cfg.channels = channels; + cfg.config_data = at9_config; + cfg.encoder_delay = encoder_delay; + + vgmstream->codec_data = init_atrac9(&cfg); + if (!vgmstream->codec_data) goto fail; + vgmstream->coding_type = coding_ATRAC9; + vgmstream->layout_type = layout_none; + break; + } +#endif + default: + VGM_LOG("SNDS: unknown codec 0x%x\n", codec); + goto fail; + } + + /* open the file for reading */ + if (!vgmstream_open_stream(vgmstream, sf, stream_offset)) + goto fail; + return vgmstream; + +fail: + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/vgmstream.c b/src/vgmstream.c index 6f7444b47..63d2e822e 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -522,6 +522,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_pwb, init_vgmstream_squeakstream, init_vgmstream_squeaksample, + init_vgmstream_snds, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index e25e0ad62..ca0f70f81 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -700,6 +700,7 @@ typedef enum { meta_AWD, meta_SQUEAKSTREAM, meta_SQUEAKSAMPLE, + meta_SNDS, } meta_t; From 5d7883fed1a4e3cde1ce796e2292bb39c4e5e215 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 13:56:50 +0200 Subject: [PATCH 111/141] Remove fake extension .sgx (use .sgh+sgd) --- src/formats.c | 1 - src/meta/sgxd.c | 62 ++++++++++++++++++------------------------------- 2 files changed, 22 insertions(+), 41 deletions(-) diff --git a/src/formats.c b/src/formats.c index cd1d88e54..478bacf44 100644 --- a/src/formats.c +++ b/src/formats.c @@ -498,7 +498,6 @@ static const char* extension_list[] = { "sgb", "sgd", "sgt", - "sgx", "slb", //txth/reserved [THE Nekomura no Hitobito (PS2)] "sli", "smc", diff --git a/src/meta/sgxd.c b/src/meta/sgxd.c index c16c53a2f..a0ff71358 100644 --- a/src/meta/sgxd.c +++ b/src/meta/sgxd.c @@ -3,16 +3,15 @@ #include "../util/chunks.h" -/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */ +/* SGXD - Sony/SCEI's SGX lib (cousin of RXWS) */ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* sf_head = NULL; STREAMFILE* sf_body = NULL; off_t start_offset, data_offset, chunk_offset, name_offset = 0; size_t stream_size; - uint32_t base1_offset, base2_offset, base3_offset; - - int is_sgx, is_sgd = 0; + uint32_t /*base1_offset,*/ base2_offset, base3_offset; + int is_sgd = 0; int loop_flag, channels, codec, sample_rate; int32_t num_samples, loop_start_sample, loop_end_sample; int total_subsongs, target_subsong = sf->stream_index; @@ -28,35 +27,31 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { } if (!is_id32be(0x00,sf_head, "SGXD")) - goto fail; + return NULL; /* checks */ - /* .sgx: header+data (Genji) - * .sgd: header+data (common) + /* .sgd: header+data (common) * .sgh+sgd: header+data (streams) */ - if (!check_extensions(sf,"sgx,sgd,sgb")) - goto fail; + if (!check_extensions(sf,"sgd,sgb")) + return NULL; /* SGXD base (size 0x10), always LE even on PS3 */ - /* 0x04: SGX = full header size - SGD/SGH = bank name offset (part of NAME table, usually same as filename) */ - /* 0x08: SGX = first chunk offset? (0x10) - SGD/SGH = full header size */ - /* 0x0c: SGX/SGH = full data size with padding / - SGD = full data size ^ (1<<31) with padding */ - base1_offset = read_u32le(0x04, sf_head); + /* 0x04: SGD/SGH = bank name offset (part of NAME table, usually same as filename) */ + /* 0x08: SGD/SGH = full header size */ + /* 0x0c: SGH = full data size with padding + * SGD = full data size ^ (1<<31) with padding */ + //base1_offset = read_u32le(0x04, sf_head); base2_offset = read_u32le(0x08, sf_head); base3_offset = read_u32le(0x0c, sf_head); - is_sgx = base2_offset == 0x10; /* fixed size */ is_sgd = base3_offset & (1 << 31); /* flag */ /* Ogg SGXD don't have flag (probably due to codec hijack, or should be split), allow since it's not so obvious */ - if (!(is_sgx || is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */ + if (!(is_sgd) && get_streamfile_size(sf_head) != base2_offset) /* sgh but wrong header size must be sgd */ is_sgd = 1; /* for plugins that start with .sgh (and don't check extensions) */ - if (!(is_sgx || is_sgd) && sf == sf_head) { + if (!(is_sgd) && sf == sf_head) { sf_body = open_streamfile_by_ext(sf, "sgb"); if (!sf_body) goto fail; } @@ -65,9 +60,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { } - if (is_sgx) { - data_offset = base1_offset; - } else if (is_sgd) { + if (is_sgd) { data_offset = base2_offset; } else { data_offset = 0x00; @@ -76,7 +69,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { /* Format per chunk: * - 0x00: id - * - 0x04: SGX: unknown; SGD/SGH: chunk length + * - 0x04: chunk length * - 0x08: null * - 0x0c: entries */ @@ -103,14 +96,8 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { * - BUSS: bus config? */ /* WAVE chunk (size 0x10 + files * 0x38 + optional padding) */ - if (is_sgx) { /* position after chunk+size */ - if (!is_id32be(0x10,sf_head, "WAVE")) - goto fail; - chunk_offset = 0x18; - } else { - if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL)) - goto fail; - } + if (!find_chunk_le(sf_head, get_id32be("WAVE"),0x10,0, &chunk_offset, NULL)) + goto fail; /* check multi-streams (usually only SE containers; Puppeteer) */ total_subsongs = read_s32le(chunk_offset+0x04,sf_head); @@ -123,8 +110,7 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { chunk_offset += 0x08 + 0x38 * (target_subsong-1); /* position in target header*/ /* 0x00: ? (00/01/02) */ - if (!is_sgx) /* meaning unknown in .sgx; offset 0 = not a stream (a RGND sample) */ - name_offset = read_u32le(chunk_offset+0x04,sf_head); + name_offset = read_u32le(chunk_offset+0x04,sf_head); codec = read_u8(chunk_offset+0x08,sf_head); channels = read_u8(chunk_offset+0x09,sf_head); /* 0x0a: null */ @@ -141,13 +127,9 @@ VGMSTREAM* init_vgmstream_sgxd(STREAMFILE* sf) { loop_end_sample = read_s32le(chunk_offset+0x28,sf_head); stream_size = read_u32le(chunk_offset+0x2c,sf_head); /* stream size (without padding) / interleave (for type3) */ - if (is_sgx) { - stream_offset = 0x0; - } else{ - stream_offset = read_u32le(chunk_offset+0x30,sf_head); - } - /* 0x34: SGX = unknown - * SGD/SGH = stream size (with padding) / interleave */ + stream_offset = read_u32le(chunk_offset+0x30,sf_head); + + /* 0x34: SGD/SGH = stream size (with padding) / interleave */ loop_flag = loop_start_sample != -1 && loop_end_sample != -1; start_offset = data_offset + stream_offset; From f4e20be97dc5deb33d52c9e36d6928189c72e11e Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 15:08:45 +0200 Subject: [PATCH 112/141] Add .trs extension [Kamiwaza (PS2)] --- src/formats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/formats.c b/src/formats.c index 478bacf44..93c31e104 100644 --- a/src/formats.c +++ b/src/formats.c @@ -558,6 +558,7 @@ static const char* extension_list[] = { "tmx", "tra", "trk", + "trs", //txth/semi [Kamiwaza (PS2), Shinobido (PS2)] "tun", "txth", "txtp", From 3ad17813a48638d1eb87bcdf438add88228a09ae Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 15:09:33 +0200 Subject: [PATCH 113/141] doc --- doc/FORMATS.md | 21 ++++++++++++--------- src/meta/sdrh.c | 1 + 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index ed321080e..516c5648f 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -662,10 +662,6 @@ different internally (encrypted, different versions, etc) and not always can be - **redspark.c** - RedSpark Header [*REDSPARK*] - Codecs: NGC_DSP -- **ivaud.c** - - Rockstar .ivaud header [*IVAUD*] - - *ivaud*: `.ivaud .(extensionless)` - - Codecs: PCM16LE XMA1 MPEG IMA_int - **ps2_sps.c** - Ape Escape 2 SPS Header [*PS2_SPS*] - *ps2_sps*: `.sps` @@ -862,7 +858,7 @@ different internally (encrypted, different versions, etc) and not always can be - Codecs: PCM16LE - **sgxd.c** - Sony SGXD header [*SGXD*] - - *sgxd*: `.sgb .sgx .sgd + .sgh .sgb` + - *sgxd*: `.sgb .sgd + .sgh .sgb` - Codecs: PCM16BE OGG_VORBIS PSX ATRAC3 PSX_cfg FFmpeg(various) - **wii_ras.c** - RAS header [*WII_RAS*] @@ -1040,9 +1036,9 @@ different internally (encrypted, different versions, etc) and not always can be - Microsoft XMA RIFF header [*XMA_RIFF*] - *xma*: `.xma .xma2 .wav .lwav .nps .str .kmx` - Codecs: XMA -- **sxd.c** - - Sony SXD header [*SXD*] - - *sxd*: `.sxd .sxd2 .sxd3 + .sxd1` +- **sndx.c** + - Sony SNDX header [*SNDX*] + - *sndx*: `.sxd .sxd2 .sxd3 + .sxd1` - Codecs: PSX HEVAG ATRAC9 - **ogl.c** - Shin'en OGL header [*OGL*] @@ -1793,7 +1789,10 @@ different internally (encrypted, different versions, etc) and not always can be - Torus SqueakStream header [*SQUEAKSTREAM*] - Torus SqueakSample header [*SQUEAKSAMPLE*] - *squeaksample*: `(base) + .asset .(external) .raw` - - Codecs: NGC_DSP PCM16LE PCM16BE PSX PCM8 MS_IMA IMA + - Codecs: NGC_DSP PCM16LE PCM16BE PSX PCM8 MS_IMA IMA XMA2 OGG_VORBIS SPEEX +- **snds.c** + - Sony SNDS header [*SNDS*] + - Codecs: ATRAC9 - **scd_pcm.c** - Lunar: Eternal Blue .PCM header [*SCD_PCM*] - *scd_pcm*: `.pcm` @@ -1826,6 +1825,10 @@ different internally (encrypted, different versions, etc) and not always can be - Tiger Game.com .4 header [*TGC*] - *tgc*: `.4` - Codecs: TGC +- **ivaud.c** + - Rockstar .ivaud header [*IVAUD*] + - *ivaud*: `.ivaud .(extensionless)` + - Codecs: PCM16LE XMA1 MPEG IMA_int - **pos.c** - RIFF WAVE header (.pos looping) [*RIFF_WAVE_POS*] - *pos*: `.pos + .wav` diff --git a/src/meta/sdrh.c b/src/meta/sdrh.c index 88d43035a..72b04a6a9 100644 --- a/src/meta/sdrh.c +++ b/src/meta/sdrh.c @@ -216,6 +216,7 @@ VGMSTREAM* init_vgmstream_sdrh_old(STREAMFILE* sf) { * 0x30: file name in a custom 40-char (RADIX style) encoding * others: ? (change in old/new) */ + /* there is also an older version in Shadow Hearts 2, more basic (no section table) and may contain sequences */ /* parse section */ { From 0fa9df4c7b955eaab5f208bc3d090d88e256aaf5 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 15:22:15 +0200 Subject: [PATCH 114/141] Remove fake extension .tydsp (use .mus) --- doc/FORMATS.md | 4 -- src/formats.c | 2 - src/libvgmstream.vcxproj | 1 - src/libvgmstream.vcxproj.filters | 3 -- src/meta/meta.h | 2 - src/meta/mus_krone.c | 2 +- src/meta/ngc_tydsp.c | 72 -------------------------------- src/vgmstream.c | 1 - src/vgmstream_types.h | 1 - 9 files changed, 1 insertion(+), 87 deletions(-) delete mode 100644 src/meta/ngc_tydsp.c diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 516c5648f..55ab80833 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -420,10 +420,6 @@ different internally (encrypted, different versions, etc) and not always can be - CRI AIX header [*AIX*] - *aix*: `.aix` - Subfiles: *adx* -- **ngc_tydsp.c** - - .tydsp Header [*NGC_TYDSP*] - - *ngc_tydsp*: `.tydsp` - - Codecs: NGC_DSP - **wvs.c** - Swingin' Ape .WVS header [*WVS*] - *wvs_xbox*: `.wvs` diff --git a/src/formats.c b/src/formats.c index 93c31e104..85d69a1e1 100644 --- a/src/formats.c +++ b/src/formats.c @@ -562,7 +562,6 @@ static const char* extension_list[] = { "tun", "txth", "txtp", - "tydsp", "u0", "ue4opus", @@ -1073,7 +1072,6 @@ static const meta_info meta_info_list[] = { {meta_PS2_VAS, "Konami .VAS header"}, {meta_LP_AP_LEP, "Konami LP/AP/LEP header"}, {meta_SDT, "High Voltage .sdt header"}, - {meta_NGC_TYDSP, ".tydsp Header"}, {meta_WVS, "Swingin' Ape .WVS header"}, {meta_DEC, "Falcom .DEC RIFF header"}, {meta_VS, "Melbourne House .VS header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 1171523c3..bab32d8b2 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -524,7 +524,6 @@ - diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index af34e7846..afb0c61e7 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1393,9 +1393,6 @@ meta\Source Files - - meta\Source Files - meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 1bbc59e65..0808c20af 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -257,8 +257,6 @@ VGMSTREAM * init_vgmstream_sdt(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_aix(STREAMFILE * streamFile); -VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE * streamFile); - VGMSTREAM* init_vgmstream_wvs_xbox(STREAMFILE* sf); VGMSTREAM* init_vgmstream_wvs_ngc(STREAMFILE* sf); diff --git a/src/meta/mus_krone.c b/src/meta/mus_krone.c index de14948e4..7b75522ad 100644 --- a/src/meta/mus_krone.c +++ b/src/meta/mus_krone.c @@ -3,7 +3,7 @@ #include "../coding/coding.h" -/* .mus - from Star Wars: The Force Unleashed (Wii) */ +/* .mus - from Krone games [Ty: The Tasmanian Tiger 2 (GC), Star Wars: The Force Unleashed (Wii)] */ VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; uint32_t start_offset, data_size; diff --git a/src/meta/ngc_tydsp.c b/src/meta/ngc_tydsp.c deleted file mode 100644 index 37f3a6037..000000000 --- a/src/meta/ngc_tydsp.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "meta.h" -#include "../util.h" - -/* TYDSP (Ty - The Tasmanian Tiger) */ -VGMSTREAM * init_vgmstream_ngc_tydsp(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; - char filename[PATH_LIMIT]; - off_t start_offset; - int loop_flag; - int channel_count; - - /* check extension, case insensitive */ - streamFile->get_name(streamFile,filename,sizeof(filename)); - if (strcasecmp("tydsp",filename_extension(filename))) goto fail; - - loop_flag = 1; - channel_count = 2; - - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count,loop_flag); - if (!vgmstream) goto fail; - - /* fill in the vital statistics */ - start_offset = read_32bitBE(0x08,streamFile); - vgmstream->channels = channel_count; - vgmstream->sample_rate = (uint16_t)(read_16bitBE(0x6C,streamFile)); - vgmstream->coding_type = coding_NGC_DSP; - vgmstream->num_samples = read_32bitBE(0x00,streamFile); - if (loop_flag) { - vgmstream->loop_start_sample = 0; - vgmstream->loop_end_sample = read_32bitBE(0x00,streamFile); - } - - vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitBE(0x04,streamFile); - vgmstream->meta_type = meta_NGC_TYDSP; - - if (vgmstream->coding_type == coding_NGC_DSP) { - int i; - for (i=0;i<16;i++) { - vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x10+i*2,streamFile); - } - if (vgmstream->channels) { - for (i=0;i<16;i++) { - vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x3E +i*2,streamFile); - } - } - } - - /* open the file for reading */ - { - int i; - STREAMFILE * file; - file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE); - if (!file) goto fail; - for (i=0;ich[i].streamfile = file; - - vgmstream->ch[i].channel_start_offset= - vgmstream->ch[i].offset=start_offset+ - vgmstream->interleave_block_size*i; - - } - } - - return vgmstream; - - /* clean up anything we may have opened */ -fail: - if (vgmstream) close_vgmstream(vgmstream); - return NULL; -} diff --git a/src/vgmstream.c b/src/vgmstream.c index 63d2e822e..de7a7e638 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -103,7 +103,6 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_lp_ap_lep, init_vgmstream_sdt, init_vgmstream_aix, - init_vgmstream_ngc_tydsp, init_vgmstream_wvs_xbox, init_vgmstream_wvs_ngc, init_vgmstream_dc_str, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index ca0f70f81..277846401 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -344,7 +344,6 @@ typedef enum { meta_PS2_VAS, /* Pro Baseball Spirits 5 */ meta_LP_AP_LEP, meta_SDT, /* Baldur's Gate - Dark Alliance */ - meta_NGC_TYDSP, /* Ty - The Tasmanian Tiger */ meta_DC_STR, /* SEGA Stream Asset Builder */ meta_DC_STR_V2, /* variant of SEGA Stream Asset Builder */ meta_SAP, From 065b7ead8766bd393f3e67405fc1dd8344ec113a Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 23 Jul 2023 15:30:36 +0200 Subject: [PATCH 115/141] cleanup: fix typo --- doc/FORMATS.md | 6 +++--- src/formats.c | 2 +- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 2 +- src/meta/meta.h | 2 +- src/meta/{mus_krone.c => mus_krome.c} | 6 +++--- src/vgmstream.c | 2 +- src/vgmstream_types.h | 2 +- 8 files changed, 12 insertions(+), 12 deletions(-) rename src/meta/{mus_krone.c => mus_krome.c} (89%) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index 55ab80833..c583a181d 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -496,9 +496,9 @@ different internally (encrypted, different versions, etc) and not always can be - *ngc_pdt*: `.pdt` - *ngc_pdt_split*: `.pdt` - Codecs: NGC_DSP -- **mus_krone.c** - - Krone .MUS header [*MUS_KRONE*] - - *mus_krone*: `.mus` +- **mus_krome.c** + - Krome .MUS header [*MUS_KROME*] + - *mus_krome*: `.mus` - Codecs: NGC_DSP - **dc_asd.c** - ASD Header [*DC_ASD*] diff --git a/src/formats.c b/src/formats.c index 85d69a1e1..c15c82b63 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1086,7 +1086,7 @@ static const meta_info meta_info_list[] = { {meta_YMF, "Yuke's .YMF Header"}, {meta_FAG, "Radical .FAG Header"}, {meta_PS2_MIHB, "Sony MultiStream MIC header"}, - {meta_MUS_KRONE, "Krone .MUS header"}, + {meta_MUS_KROME, "Krome .MUS header"}, {meta_WII_SNG, "SNG DSP Header"}, {meta_RSD, "Radical RSD header"}, {meta_DC_ASD, "ASD Header"}, diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index bab32d8b2..af4356281 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -503,7 +503,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index afb0c61e7..e7cde615a 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -1330,7 +1330,7 @@ meta\Source Files - + meta\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 0808c20af..56ca00f70 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -296,7 +296,7 @@ VGMSTREAM * init_vgmstream_ps2_mihb(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt_split(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ngc_pdt(STREAMFILE * streamFile); -VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf); VGMSTREAM * init_vgmstream_rsd(STREAMFILE * streamFile); diff --git a/src/meta/mus_krone.c b/src/meta/mus_krome.c similarity index 89% rename from src/meta/mus_krone.c rename to src/meta/mus_krome.c index 7b75522ad..c59d84b02 100644 --- a/src/meta/mus_krone.c +++ b/src/meta/mus_krome.c @@ -3,8 +3,8 @@ #include "../coding/coding.h" -/* .mus - from Krone games [Ty: The Tasmanian Tiger 2 (GC), Star Wars: The Force Unleashed (Wii)] */ -VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { +/* .mus - from Krome games [Ty: The Tasmanian Tiger 2 (GC), Star Wars: The Force Unleashed (Wii)] */ +VGMSTREAM* init_vgmstream_mus_krome(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; uint32_t start_offset, data_size; int channels, loop_flag, interleave; @@ -36,7 +36,7 @@ VGMSTREAM* init_vgmstream_mus_krone(STREAMFILE* sf) { vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_MUS_KRONE; + vgmstream->meta_type = meta_MUS_KROME; vgmstream->num_samples = num_samples; vgmstream->sample_rate = read_u16be(0x6c,sf); diff --git a/src/vgmstream.c b/src/vgmstream.c index de7a7e638..9cc129f0a 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -128,7 +128,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_ps2_mihb, init_vgmstream_ngc_pdt_split, init_vgmstream_ngc_pdt, - init_vgmstream_mus_krone, + init_vgmstream_mus_krome, init_vgmstream_dc_asd, init_vgmstream_spsd, init_vgmstream_rsd, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 277846401..64ded87ea 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -257,7 +257,7 @@ typedef enum { meta_DSP_SADB, /* .sad */ meta_DSP_WSI, /* .wsi */ meta_IDSP_TT, /* Traveller's Tales games */ - meta_MUS_KRONE, + meta_MUS_KROME, meta_DSP_WII_WSD, /* Phantom Brave (WII) */ meta_WII_NDP, /* Vertigo (Wii) */ meta_DSP_YGO, /* Konami: Yu-Gi-Oh! The Falsebound Kingdom (NGC), Hikaru no Go 3 (NGC) */ From 90adcd5164b36e55ef5dbf7d5fc57ee7446ebc7b Mon Sep 17 00:00:00 2001 From: bnnm Date: Wed, 26 Jul 2023 22:42:57 +0200 Subject: [PATCH 116/141] Update version.h --- version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.h b/version.h index ca1a766dd..e1b04cf36 100644 --- a/version.h +++ b/version.h @@ -32,7 +32,7 @@ * versions should return "rNNNN" without extra text commit number text */ -#define VGMSTREAM_VERSION "r1843" +#define VGMSTREAM_VERSION "r1866" #endif #endif From 3c08136b31397867b313e1a56eaf753a7be9475f Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Thu, 27 Jul 2023 00:40:26 +0300 Subject: [PATCH 117/141] VAG: Remove bigfile ignoring temporarily --- src/meta/vag.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/meta/vag.c b/src/meta/vag.c index c8979ea64..de61c1959 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -287,9 +287,10 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { goto fail; } - /* ignore bigfiles and bad extractions (approximate) */ - if (channel_size * channels + interleave * channels + start_offset * channels + 0x8000 < get_streamfile_size(sf) || - channel_size * channels > get_streamfile_size(sf)) { + /* ignore bad extractions (approximate) */ + /* bigfile ignoring breaks some of Jak series' VAGs (unless increased to roughly 1.4 MiB) */ + //if (channel_size * channels + interleave * channels + start_offset * channels + 0x80000 < get_streamfile_size(sf) || + if (channel_size * channels > get_streamfile_size(sf)) { vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n", channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf)); goto fail; From 2e44b1e051d4fac4d61572b398c7eee1900fbb80 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Thu, 27 Jul 2023 00:44:38 +0300 Subject: [PATCH 118/141] VAG: Remove bigfile check temporarily --- src/meta/vag.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/meta/vag.c b/src/meta/vag.c index c8979ea64..de61c1959 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -287,9 +287,10 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { goto fail; } - /* ignore bigfiles and bad extractions (approximate) */ - if (channel_size * channels + interleave * channels + start_offset * channels + 0x8000 < get_streamfile_size(sf) || - channel_size * channels > get_streamfile_size(sf)) { + /* ignore bad extractions (approximate) */ + /* bigfile ignoring breaks some of Jak series' VAGs (unless increased to roughly 1.4 MiB) */ + //if (channel_size * channels + interleave * channels + start_offset * channels + 0x80000 < get_streamfile_size(sf) || + if (channel_size * channels > get_streamfile_size(sf)) { vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n", channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf)); goto fail; From a98780b0ebbd4e277aebbf51243214413ded2258 Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:28:30 +0300 Subject: [PATCH 119/141] VAG: Increase bigfile padding check to 2MiB --- src/meta/vag.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/meta/vag.c b/src/meta/vag.c index de61c1959..791513fa8 100644 --- a/src/meta/vag.c +++ b/src/meta/vag.c @@ -287,10 +287,10 @@ VGMSTREAM* init_vgmstream_vag(STREAMFILE* sf) { goto fail; } - /* ignore bad extractions (approximate) */ - /* bigfile ignoring breaks some of Jak series' VAGs (unless increased to roughly 1.4 MiB) */ - //if (channel_size * channels + interleave * channels + start_offset * channels + 0x80000 < get_streamfile_size(sf) || - if (channel_size * channels > get_streamfile_size(sf)) { + /* ignore bigfiles and bad extractions (approximate) */ + /* padding is set to 2 MiB to avoid breaking Jak series' VAGs */ + if (channel_size * channels + interleave * channels + start_offset * channels + 0x200000 < get_streamfile_size(sf) || + channel_size * channels > get_streamfile_size(sf)) { vgm_logi("VAG: wrong expected (incorrect extraction? %x * %i + %x + %x + ~ vs %x)\n", channel_size, channels, interleave * channels, start_offset * channels, (uint32_t)get_streamfile_size(sf)); goto fail; From a0552a2d7a8d120852c38b901de26978a344edee Mon Sep 17 00:00:00 2001 From: EdnessP <55930127+EdnessP@users.noreply.github.com> Date: Sat, 29 Jul 2023 00:06:32 +0300 Subject: [PATCH 120/141] Reflections IMA ADPCM: Use interleave block size for frame samples --- src/base/decode.c | 5 +++-- src/meta/xa_xa30.c | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/base/decode.c b/src/base/decode.c index 3ac6d89b9..61bc66bba 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -422,10 +422,11 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { case coding_APPLE_IMA4: return 64; case coding_MS_IMA: - case coding_REF_IMA: - return ((vgmstream->frame_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;/* +1 from header sample */ + return ((vgmstream->frame_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1; /* +1 from header sample */ case coding_MS_IMA_mono: return ((vgmstream->frame_size - 0x04) * 2) + 1; /* +1 from header sample */ + case coding_REF_IMA: + return ((vgmstream->interleave_block_size - 0x04 * vgmstream->channels) * 2 / vgmstream->channels) + 1; /* +1 from header sample */ case coding_RAD_IMA: return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels; case coding_NDS_IMA: diff --git a/src/meta/xa_xa30.c b/src/meta/xa_xa30.c index e6f390f79..8c24b8dd6 100644 --- a/src/meta/xa_xa30.c +++ b/src/meta/xa_xa30.c @@ -5,7 +5,7 @@ VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) { VGMSTREAM * vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count, codec; + int loop_flag, channel_count, codec, interleave_block_size; size_t stream_size; int total_subsongs, target_subsong = streamFile->stream_index; @@ -31,6 +31,7 @@ VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) { codec = read_32bitLE(0x0c,streamFile); start_offset = read_32bitLE(0x10 + 0x04*(target_subsong-1),streamFile); stream_size = read_32bitLE(0x18 + 0x04*(target_subsong-1),streamFile); + interleave_block_size = read_32bitLE(0x24, streamFile); /* build the VGMSTREAM */ @@ -47,14 +48,14 @@ VGMSTREAM * init_vgmstream_xa_xa30(STREAMFILE *streamFile) { case 0x00: /* PCM (rare, seen in Driver 3) */ vgmstream->coding_type = coding_PCM16LE; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile) / 2; + vgmstream->interleave_block_size = interleave_block_size / 2; vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16); break; case 0x01: /* MS-IMA variation */ vgmstream->coding_type = coding_REF_IMA; vgmstream->layout_type = layout_none; - vgmstream->interleave_block_size = read_32bitLE(0x24,streamFile); + vgmstream->interleave_block_size = interleave_block_size; vgmstream->num_samples = ms_ima_bytes_to_samples(stream_size, vgmstream->interleave_block_size, channel_count); break; From 8d033e24c7f8c5c857a96effaef8403aba636396 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 30 Jul 2023 23:47:50 +0200 Subject: [PATCH 121/141] minor cleanup --- src/base/mixing.c | 1076 +----------------------------- src/base/mixing_commands.c | 254 +++++++ src/base/mixing_fades.h | 171 +++++ src/base/mixing_macros.c | 578 ++++++++++++++++ src/base/mixing_priv.h | 52 ++ src/libvgmstream.vcxproj | 4 + src/libvgmstream.vcxproj.filters | 12 + 7 files changed, 1097 insertions(+), 1050 deletions(-) create mode 100644 src/base/mixing_commands.c create mode 100644 src/base/mixing_fades.h create mode 100644 src/base/mixing_macros.c create mode 100644 src/base/mixing_priv.h diff --git a/src/base/mixing.c b/src/base/mixing.c index 17ae43979..867f992d2 100644 --- a/src/base/mixing.c +++ b/src/base/mixing.c @@ -1,6 +1,8 @@ #include "../vgmstream.h" #include "../util/channel_mappings.h" #include "mixing.h" +#include "mixing_priv.h" +#include "mixing_fades.h" #include "plugins.h" #include #include @@ -49,215 +51,21 @@ * (and maybe improve memory cache?), though maybe it should call one function per operation. */ -#define VGMSTREAM_MAX_MIXING 512 -#define MIXING_PI 3.14159265358979323846f - - -/* mixing info */ -typedef enum { - MIX_SWAP, - MIX_ADD, - MIX_ADD_COPY, - MIX_VOLUME, - MIX_LIMIT, - MIX_UPMIX, - MIX_DOWNMIX, - MIX_KILLMIX, - MIX_FADE -} mix_command_t; - -typedef struct { - mix_command_t command; - /* common */ - int ch_dst; - int ch_src; - float vol; - - /* fade envelope */ - float vol_start; /* volume from pre to start */ - float vol_end; /* volume from end to post */ - char shape; /* curve type */ - int32_t time_pre; /* position before time_start where vol_start applies (-1 = beginning) */ - int32_t time_start; /* fade start position where vol changes from vol_start to vol_end */ - int32_t time_end; /* fade end position where vol changes from vol_start to vol_end */ - int32_t time_post; /* position after time_end where vol_end applies (-1 = end) */ -} mix_command_data; - -typedef struct { - int mixing_channels; /* max channels needed to mix */ - int output_channels; /* resulting channels after mixing */ - int mixing_on; /* mixing allowed */ - int mixing_count; /* mixing number */ - size_t mixing_size; /* mixing max */ - mix_command_data mixing_chain[VGMSTREAM_MAX_MIXING]; /* effects to apply (could be alloc'ed but to simplify...) */ - float* mixbuf; /* internal mixing buffer */ - - /* fades only apply at some points, other mixes are active */ - int has_non_fade; - int has_fade; -} mixing_data; - - /* ******************************************************************* */ -static int is_fade_active(mixing_data *data, int32_t current_start, int32_t current_end) { - int i; - - for (i = 0; i < data->mixing_count; i++) { - mix_command_data *mix = &data->mixing_chain[i]; - int32_t fade_start, fade_end; - float vol_start = mix->vol_start; - - if (mix->command != MIX_FADE) - continue; - - /* check is current range falls within a fade - * (assuming fades were already optimized on add) */ - if (mix->time_pre < 0 && vol_start == 1.0) { - fade_start = mix->time_start; /* ignore unused */ - } - else { - fade_start = mix->time_pre < 0 ? 0 : mix->time_pre; - } - fade_end = mix->time_post < 0 ? INT_MAX : mix->time_post; - - //;VGM_LOG("MIX: fade test, tp=%i, te=%i, cs=%i, ce=%i\n", mix->time_pre, mix->time_post, current_start, current_end); - if (current_start < fade_end && current_end > fade_start) { - //;VGM_LOG("MIX: fade active, cs=%i < fe=%i and ce=%i > fs=%i\n", current_start, fade_end, current_end, fade_start); - return 1; - } - } - - return 0; -} - -static int32_t get_current_pos(VGMSTREAM* vgmstream, int32_t sample_count) { - int32_t current_pos; - - if (vgmstream->config_enabled) { - return vgmstream->pstate.play_position; - } - - if (vgmstream->loop_flag && vgmstream->loop_count > 0) { - int loop_pre = vgmstream->loop_start_sample; /* samples before looping */ - int loop_into = (vgmstream->current_sample - vgmstream->loop_start_sample); /* samples after loop */ - int loop_samples = (vgmstream->loop_end_sample - vgmstream->loop_start_sample); /* looped section */ - - current_pos = loop_pre + (loop_samples * vgmstream->loop_count) + loop_into - sample_count; - } - else { - current_pos = (vgmstream->current_sample - sample_count); - } - - return current_pos; -} - -static float get_fade_gain_curve(char shape, float index) { - float gain; - - /* don't bother doing calcs near 0.0/1.0 */ - if (index <= 0.0001f || index >= 0.9999f) { - return index; - } - - //todo optimizations: interleave calcs, maybe use cosf, powf, etc? (with extra defines) - - /* (curve math mostly from SoX/FFmpeg) */ - switch(shape) { - /* 2.5f in L/E 'pow' is the attenuation factor, where 5.0 (100db) is common but a bit fast - * (alt calculations with 'exp' from FFmpeg use (factor)*ln(0.1) = -NN.N... */ - - case 'E': /* exponential (for fade-outs, closer to natural decay of sound) */ - //gain = pow(0.1f, (1.0f - index) * 2.5f); - gain = exp(-5.75646273248511f * (1.0f - index)); - break; - case 'L': /* logarithmic (inverse of the above, maybe for crossfades) */ - //gain = 1 - pow(0.1f, (index) * 2.5f); - gain = 1 - exp(-5.75646273248511f * (index)); - break; - - case 'H': /* raised sine wave or cosine wave (for more musical crossfades) */ - gain = (1.0f - cos(index * MIXING_PI)) / 2.0f; - break; - - case 'Q': /* quarter of sine wave (for musical fades) */ - gain = sin(index * MIXING_PI / 2.0f); - break; - - case 'p': /* parabola (maybe for crossfades) */ - gain = 1.0f - sqrt(1.0f - index); - break; - case 'P': /* inverted parabola (maybe for fades) */ - gain = (1.0f - (1.0f - index) * (1.0f - index)); - break; - - case 'T': /* triangular/linear (simpler/sharper fades) */ - default: - gain = index; - break; - } - - return gain; -} - -static int get_fade_gain(mix_command_data *mix, float *out_cur_vol, int32_t current_subpos) { - float cur_vol = 0.0f; - - if ((current_subpos >= mix->time_pre || mix->time_pre < 0) && current_subpos < mix->time_start) { - cur_vol = mix->vol_start; /* before */ - } - else if (current_subpos >= mix->time_end && (current_subpos < mix->time_post || mix->time_post < 0)) { - cur_vol = mix->vol_end; /* after */ - } - else if (current_subpos >= mix->time_start && current_subpos < mix->time_end) { - /* in between */ - float range_vol, range_dur, range_idx, index, gain; - - if (mix->vol_start < mix->vol_end) { /* fade in */ - range_vol = mix->vol_end - mix->vol_start; - range_dur = mix->time_end - mix->time_start; - range_idx = current_subpos - mix->time_start; - index = range_idx / range_dur; - } else { /* fade out */ - range_vol = mix->vol_end - mix->vol_start; - range_dur = mix->time_end - mix->time_start; - range_idx = mix->time_end - current_subpos; - index = range_idx / range_dur; - } - - /* Fading is done like this: - * - find current position within fade duration - * - get linear % (or rather, index from 0.0 .. 1.0) of duration - * - apply shape to % (from linear fade to curved fade) - * - get final volume for that point - * - * Roughly speaking some curve shapes are better for fades (decay rate is more natural - * sounding in that highest to mid/low happens faster but low to lowest takes more time, - * kinda like a gunshot or bell), and others for crossfades (decay of fade-in + fade-out - * is adjusted so that added volume level stays constant-ish). - * - * As curves can fade in two ways ('normal' and curving 'the other way'), they are adjusted - * to get 'normal' shape on both fades (by reversing index and making 1 - gain), thus some - * curves are complementary (exponential fade-in ~= logarithmic fade-out); the following - * are described taking fade-in = normal. +static void sbuf_copy_f32_to_s16(int16_t* buf_s16, float* buf_f32, int samples, int channels) { + for (int s = 0; s < samples * channels; s++) { + /* when casting float to int, value is simply truncated: + * - (int)1.7 = 1, (int)-1.7 = -1 + * alts for more accurate rounding could be: + * - (int)floor(f) + * - (int)(f < 0 ? f - 0.5f : f + 0.5f) + * - (((int) (f1 + 32768.5)) - 32768) + * - etc + * but since +-1 isn't really audible we'll just cast as it's the fastest */ - gain = get_fade_gain_curve(mix->shape, index); - - if (mix->vol_start < mix->vol_end) { /* fade in */ - cur_vol = mix->vol_start + range_vol * gain; - } else { /* fade out */ - cur_vol = mix->vol_end - range_vol * gain; //mix->vol_start - range_vol * (1 - gain); - } - } - else { - /* fade is outside reach */ - goto fail; + buf_s16[s] = clamp16( (int32_t)buf_f32[s] ); } - - *out_cur_vol = cur_vol; - return 1; -fail: - return 0; } void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream) { @@ -288,9 +96,19 @@ void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream) /* use advancing buffer pointers to simplify logic */ - temp_mixbuf = data->mixbuf; + temp_mixbuf = data->mixbuf; /* you'd think using a int32 temp buf would be faster but somehow it's slower? */ temp_outbuf = outbuf; + /* mixing ops are designed to apply in order, all channels per 1 sample 'step'. Since some ops change + * total channels, channel number meaning varies as ops move them around, ex: + * - 4ch w/ "1-2,2+3" = ch1<>ch3, ch2(old ch1)+ch3 = 4ch: ch2 ch1+ch3 ch3 ch4 + * - 4ch w/ "2+3,1-2" = ch2+ch3, ch1<>ch2(modified) = 4ch: ch2+ch3 ch1 ch3 ch4 + * - 2ch w/ "1+2,1u" = ch1+ch2, ch1(add and push rest) = 3ch: ch1' ch1+ch2 ch2 + * - 2ch w/ "1u,1+2" = ch1(add and push rest) = 3ch: ch1'+ch1 ch1 ch2 + * - 2ch w/ "1-2,1d" = ch1<>ch2, ch1(drop and move ch2(old ch1) to ch1) = ch1 + * - 2ch w/ "1d,1-2" = ch1(drop and pull rest), ch1(do nothing, ch2 doesn't exist now) = ch2 + */ + /* apply mixes in order per channel */ for (s = 0; s < sample_count; s++) { /* reset after new sample 'step'*/ @@ -304,15 +122,6 @@ void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream) for (m = 0; m < data->mixing_count; m++) { mix_command_data *mix = &data->mixing_chain[m]; - /* mixing ops are designed to apply in order, all channels per 1 sample 'step'. Since some ops change - * total channels, channel number meaning varies as ops move them around, ex: - * - 4ch w/ "1-2,2+3" = ch1<>ch3, ch2(old ch1)+ch3 = 4ch: ch2 ch1+ch3 ch3 ch4 - * - 4ch w/ "2+3,1-2" = ch2+ch3, ch1<>ch2(modified) = 4ch: ch2+ch3 ch1 ch3 ch4 - * - 2ch w/ "1+2,1u" = ch1+ch2, ch1(add and push rest) = 3ch: ch1' ch1+ch2 ch2 - * - 2ch w/ "1u,1+2" = ch1(add and push rest) = 3ch: ch1'+ch1 ch1 ch2 - * - 2ch w/ "1-2,1d" = ch1<>ch2, ch1(drop and move ch2(old ch1) to ch1) = ch1 - * - 2ch w/ "1d,1-2" = ch1(drop and pull rest), ch1(do nothing, ch2 doesn't exist now) = ch2 - */ switch(mix->command) { case MIX_SWAP: @@ -406,20 +215,8 @@ void mix_vgmstream(sample_t *outbuf, int32_t sample_count, VGMSTREAM* vgmstream) temp_outbuf += vgmstream->channels; } - /* copy resulting mix to output - * (you'd think using a int32 temp buf would be faster but somehow it's slower?) */ - for (s = 0; s < sample_count * data->output_channels; s++) { - /* when casting float to int, value is simply truncated: - * - (int)1.7 = 1, (int)-1.7 = -1 - * alts for more accurate rounding could be: - * - (int)floor(f) - * - (int)(f < 0 ? f - 0.5f : f + 0.5f) - * - (((int) (f1 + 32768.5)) - 32768) - * - etc - * but since +-1 isn't really audible we'll just cast as it's the fastest - */ - outbuf[s] = clamp16( (int32_t)data->mixbuf[s] ); - } + /* copy resulting temp mix to output */ + sbuf_copy_f32_to_s16(outbuf, data->mixbuf, sample_count, data->output_channels); } /* ******************************************************************* */ @@ -460,827 +257,6 @@ void mixing_update_channel(VGMSTREAM* vgmstream) { data->output_channels++; } -/* ******************************************************************* */ - -static int add_mixing(VGMSTREAM* vgmstream, mix_command_data *mix) { - mixing_data *data = vgmstream->mixing_data; - if (!data) return 0; - - - if (data->mixing_on) { - VGM_LOG("MIX: ignoring new mixes when mixing active\n"); - return 0; /* to avoid down/upmixing after activation */ - } - - if (data->mixing_count + 1 > data->mixing_size) { - VGM_LOG("MIX: too many mixes\n"); - return 0; - } - - data->mixing_chain[data->mixing_count] = *mix; /* memcpy */ - data->mixing_count++; - - - if (mix->command == MIX_FADE) { - data->has_fade = 1; - } - else { - data->has_non_fade = 1; - } - - //;VGM_LOG("MIX: total %i\n", data->mixing_count); - return 1; -} - - -void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - - if (ch_dst < 0 || ch_src < 0 || ch_dst == ch_src) return; - if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return; - mix.command = MIX_SWAP; - mix.ch_dst = ch_dst; - mix.ch_src = ch_src; - - add_mixing(vgmstream, &mix); -} - -void mixing_push_add(VGMSTREAM* vgmstream, int ch_dst, int ch_src, double volume) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - if (!data) return; - - //if (volume < 0.0) return; /* negative volume inverts the waveform */ - if (volume == 0.0) return; /* ch_src becomes silent and nothing is added */ - if (ch_dst < 0 || ch_src < 0) return; - if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return; - - mix.command = (volume == 1.0) ? MIX_ADD_COPY : MIX_ADD; - mix.ch_dst = ch_dst; - mix.ch_src = ch_src; - mix.vol = volume; - - //;VGM_LOG("MIX: add %i+%i*%f\n", ch_dst,ch_src,volume); - add_mixing(vgmstream, &mix); -} - -void mixing_push_volume(VGMSTREAM* vgmstream, int ch_dst, double volume) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - - //if (ch_dst < 0) return; /* means all channels */ - //if (volume < 0.0) return; /* negative volume inverts the waveform */ - if (volume == 1.0) return; /* no change */ - if (!data || ch_dst >= data->output_channels) return; - - mix.command = MIX_VOLUME; //if (volume == 0.0) MIX_VOLUME0 /* could simplify */ - mix.ch_dst = ch_dst; - mix.vol = volume; - - //;VGM_LOG("MIX: volume %i*%f\n", ch_dst,volume); - add_mixing(vgmstream, &mix); -} - -void mixing_push_limit(VGMSTREAM* vgmstream, int ch_dst, double volume) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - - //if (ch_dst < 0) return; /* means all channels */ - if (volume < 0.0) return; - if (volume == 1.0) return; /* no actual difference */ - if (!data || ch_dst >= data->output_channels) return; - //if (volume == 0.0) return; /* dumb but whatevs */ - - mix.command = MIX_LIMIT; - mix.ch_dst = ch_dst; - mix.vol = volume; - - add_mixing(vgmstream, &mix); -} - -void mixing_push_upmix(VGMSTREAM* vgmstream, int ch_dst) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - int ok; - - if (ch_dst < 0) return; - if (!data || ch_dst > data->output_channels || data->output_channels +1 > VGMSTREAM_MAX_CHANNELS) return; - /* dst can be == output_channels here, since we are inserting */ - - mix.command = MIX_UPMIX; - mix.ch_dst = ch_dst; - - ok = add_mixing(vgmstream, &mix); - if (ok) { - data->output_channels += 1; - if (data->mixing_channels < data->output_channels) - data->mixing_channels = data->output_channels; - } -} - -void mixing_push_downmix(VGMSTREAM* vgmstream, int ch_dst) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - int ok; - - if (ch_dst < 0) return; - if (!data || ch_dst >= data->output_channels || data->output_channels - 1 < 1) return; - - mix.command = MIX_DOWNMIX; - mix.ch_dst = ch_dst; - - ok = add_mixing(vgmstream, &mix); - if (ok) { - data->output_channels -= 1; - } -} - -void mixing_push_killmix(VGMSTREAM* vgmstream, int ch_dst) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - int ok; - - if (ch_dst <= 0) return; /* can't kill from first channel */ - if (!data || ch_dst >= data->output_channels) return; - - mix.command = MIX_KILLMIX; - mix.ch_dst = ch_dst; - - //;VGM_LOG("MIX: killmix %i\n", ch_dst); - ok = add_mixing(vgmstream, &mix); - if (ok) { - data->output_channels = ch_dst; /* clamp channels */ - } -} - - -static mix_command_data* get_last_fade(mixing_data *data, int target_channel) { - int i; - for (i = data->mixing_count; i > 0; i--) { - mix_command_data *mix = &data->mixing_chain[i-1]; - if (mix->command != MIX_FADE) - continue; - if (mix->ch_dst == target_channel) - return mix; - } - - return NULL; -} - - -void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double vol_end, char shape, - int32_t time_pre, int32_t time_start, int32_t time_end, int32_t time_post) { - mixing_data *data = vgmstream->mixing_data; - mix_command_data mix = {0}; - mix_command_data *mix_prev; - - - //if (ch_dst < 0) return; /* means all channels */ - if (!data || ch_dst >= data->output_channels) return; - if (time_pre > time_start || time_start > time_end || (time_post >= 0 && time_end > time_post)) return; - if (time_start < 0 || time_end < 0) return; - //if (time_pre < 0 || time_post < 0) return; /* special meaning of file start/end */ - //if (vol_start == vol_end) /* weird but let in case of being used to cancel others fades... maybe? */ - - if (shape == '{' || shape == '}') - shape = 'E'; - if (shape == '(' || shape == ')') - shape = 'H'; - - mix.command = MIX_FADE; - mix.ch_dst = ch_dst; - mix.vol_start = vol_start; - mix.vol_end = vol_end; - mix.shape = shape; - mix.time_pre = time_pre; - mix.time_start = time_start; - mix.time_end = time_end; - mix.time_post = time_post; - - - /* cancel fades and optimize a bit when using negative pre/post: - * - fades work like this: - * <----------|----------|----------> - * pre1 start1 end1 post1 - * - when pre and post are set nothing is done (fade is exact and multiple fades may overlap) - * - when previous fade's post or current fade's pre are negative (meaning file end/start) - * they should cancel each other (to allow chaining fade-in + fade-out + fade-in + etc): - * <----------|----------|----------| |----------|----------|----------> - * pre1 start1 end1 post1 pre2 start2 end2 post2 - * - other cases (previous fade is actually after/in-between current fade) are ignored - * as they're uncommon and hard to optimize - * fades cancel fades of the same channel, and 'all channel' (-1) fades also cancel 'all channels' - */ - mix_prev = get_last_fade(data, mix.ch_dst); - if (mix_prev == NULL) { - if (vol_start == 1.0 && time_pre < 0) - time_pre = time_start; /* fade-out helds default volume before fade start can be clamped */ - if (vol_end == 1.0 && time_post < 0) - time_post = time_end; /* fade-in helds default volume after fade end can be clamped */ - } - else if (mix_prev->time_post < 0 || mix.time_pre < 0) { - int is_prev = 1; - /* test if prev is really cancelled by this */ - if ((mix_prev->time_end > mix.time_start) || - (mix_prev->time_post >= 0 && mix_prev->time_post > mix.time_start) || - (mix.time_pre >= 0 && mix.time_pre < mix_prev->time_end)) - is_prev = 0; - - if (is_prev) { - /* change negative values to actual points */ - if (mix_prev->time_post < 0 && mix.time_pre < 0) { - mix_prev->time_post = mix_prev->time_end; - mix.time_pre = mix_prev->time_post; - } - - if (mix_prev->time_post >= 0 && mix.time_pre < 0) { - mix.time_pre = mix_prev->time_post; - } - else if (mix_prev->time_post < 0 && mix.time_pre >= 0) { - mix_prev->time_post = mix.time_pre; - } - /* else: both define start/ends, do nothing */ - } - /* should only modify prev if add_mixing but meh */ - } - - //;VGM_LOG("MIX: fade %i^%f~%f=%c@%i~%i~%i~%i\n", ch_dst, vol_start, vol_end, shape, time_pre, time_start, time_end, time_post); - add_mixing(vgmstream, &mix); -} - -/* ******************************************************************* */ - -#define MIX_MACRO_VOCALS 'v' -#define MIX_MACRO_EQUAL 'e' -#define MIX_MACRO_BGM 'b' - -void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) { - mixing_data *data = vgmstream->mixing_data; - int ch; - - if (!data) - return; - - if (mask == 0) { - mixing_push_volume(vgmstream, -1, volume); - return; - } - - for (ch = 0; ch < data->output_channels; ch++) { - if (!((mask >> ch) & 1)) - continue; - mixing_push_volume(vgmstream, ch, volume); - } -} - -void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) { - mixing_data *data = vgmstream->mixing_data; - int ch; - - if (!data) - return; - - if (mask == 0) { - return; - } - - /* reverse remove all channels (easier this way as when removing channels numbers change) */ - for (ch = data->output_channels - 1; ch >= 0; ch--) { - if ((mask >> ch) & 1) - continue; - mixing_push_downmix(vgmstream, ch); - } -} - - -/* get highest channel count */ -static int get_layered_max_channels(VGMSTREAM* vgmstream) { - int i, max; - layered_layout_data* data; - - if (vgmstream->layout_type != layout_layered) - return 0; - - data = vgmstream->layout_data; - - max = 0; - for (i = 0; i < data->layer_count; i++) { - int output_channels = 0; - - mixing_info(data->layers[i], NULL, &output_channels); - - if (max < output_channels) - max = output_channels; - } - - return max; -} - -static int is_layered_auto(VGMSTREAM* vgmstream, int max, char mode) { - int i; - mixing_data *data = vgmstream->mixing_data; - layered_layout_data* l_data; - - - if (vgmstream->layout_type != layout_layered) - return 0; - - /* no channels set and only vocals for now */ - if (max > 0 || mode != MIX_MACRO_VOCALS) - return 0; - - /* no channel down/upmixing (cannot guess output) */ - for (i = 0; i < data->mixing_count; i++) { - mix_command_t mix = data->mixing_chain[i].command; - if (mix == MIX_UPMIX || mix == MIX_DOWNMIX || mix == MIX_KILLMIX) /*mix == MIX_SWAP || ??? */ - return 0; - } - - /* only previsible cases */ - l_data = vgmstream->layout_data; - for (i = 0; i < l_data->layer_count; i++) { - int output_channels = 0; - - mixing_info(l_data->layers[i], NULL, &output_channels); - - if (output_channels > 8) - return 0; - } - - return 1; -} - - -/* special layering, where channels are respected (so Ls only go to Ls), also more optimized */ -static void mixing_macro_layer_auto(VGMSTREAM* vgmstream, int max, char mode) { - layered_layout_data* ldata = vgmstream->layout_data; - int i, ch; - int target_layer = 0, target_chs = 0, ch_max, target_ch = 0, target_silence = 0; - int ch_num; - - /* With N layers like: (ch1 ch2) (ch1 ch2 ch3 ch4) (ch1 ch2), output is normally 2+4+2=8ch. - * We want to find highest layer (ch1..4) = 4ch, add other channels to it and drop them */ - - /* find target "main" channels (will be first most of the time) */ - ch_num = 0; - ch_max = 0; - for (i = 0; i < ldata->layer_count; i++) { - int layer_chs = 0; - - mixing_info(ldata->layers[i], NULL, &layer_chs); - - if (ch_max < layer_chs || (ch_max == layer_chs && target_silence)) { - target_ch = ch_num; - target_chs = layer_chs; - target_layer = i; - ch_max = layer_chs; - /* avoid using silence as main if possible for minor optimization */ - target_silence = (ldata->layers[i]->coding_type == coding_SILENCE); - } - - ch_num += layer_chs; - } - - /* all silences? */ - if (!target_chs) { - target_ch = 0; - target_chs = 0; - target_layer = 0; - mixing_info(ldata->layers[0], NULL, &target_chs); - } - - /* add other channels to target (assumes standard channel mapping to simplify) - * most of the time all layers will have same number of channels though */ - ch_num = 0; - for (i = 0; i < ldata->layer_count; i++) { - int layer_chs = 0; - - if (target_layer == i) { - ch_num += target_chs; - continue; - } - - mixing_info(ldata->layers[i], NULL, &layer_chs); - - if (ldata->layers[i]->coding_type == coding_SILENCE) { - ch_num += layer_chs; - continue; /* unlikely but sometimes in Wwise */ - } - - if (layer_chs == target_chs) { - /* 1:1 mapping */ - for (ch = 0; ch < layer_chs; ch++) { - mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0); - } - } - else { - const double vol_sqrt = 1 / sqrt(2); - - /* extra mixing for better sound in some cases (assumes layer_chs is lower than target_chs) */ - switch(layer_chs) { - case 1: - mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, vol_sqrt); - mixing_push_add(vgmstream, target_ch + 1, ch_num + 0, vol_sqrt); - break; - case 2: - mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, 1.0); - mixing_push_add(vgmstream, target_ch + 1, ch_num + 1, 1.0); - break; - default: /* less common */ - //TODO add other mixes, depends on target_chs + mapping (ex. 4.0 to 5.0 != 5.1, 2.1 xiph to 5.1 != 5.1 xiph) - for (ch = 0; ch < layer_chs; ch++) { - mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0); - } - break; - } - } - - ch_num += layer_chs; - } - - /* drop non-target channels */ - ch_num = 0; - for (i = 0; i < ldata->layer_count; i++) { - - if (i < target_layer) { /* least common, hopefully (slower to drop chs 1 by 1) */ - int layer_chs = 0; - mixing_info(ldata->layers[i], NULL, &layer_chs); - - for (ch = 0; ch < layer_chs; ch++) { - mixing_push_downmix(vgmstream, ch_num); //+ ch - } - - //ch_num += layer_chs; /* dropped channels change this */ - } - else if (i == target_layer) { - ch_num += target_chs; - } - else { /* most common, hopefully (faster) */ - mixing_push_killmix(vgmstream, ch_num); - break; - } - } -} - - -void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, char mode) { - mixing_data *data = vgmstream->mixing_data; - int current, ch, output_channels, selected_channels; - - if (!data) - return; - - if (is_layered_auto(vgmstream, max, mode)) { - //;VGM_LOG("MIX: auto layer mode\n"); - mixing_macro_layer_auto(vgmstream, max, mode); - return; - } - //;VGM_LOG("MIX: regular layer mode\n"); - - if (max == 0) /* auto calculate */ - max = get_layered_max_channels(vgmstream); - - if (max <= 0 || data->output_channels <= max) - return; - - /* set all channels (non-existant channels will be ignored) */ - if (mask == 0) { - mask = ~mask; - } - - /* save before adding fake channels */ - output_channels = data->output_channels; - - /* count possibly set channels */ - selected_channels = 0; - for (ch = 0; ch < output_channels; ch++) { - selected_channels += (mask >> ch) & 1; - } - - /* make N fake channels at the beginning for easier calcs */ - for (ch = 0; ch < max; ch++) { - mixing_push_upmix(vgmstream, 0); - } - - /* add all layers in this order: ch0: 0, 0+N, 0+N*2 ... / ch1: 1, 1+N ... */ - current = 0; - for (ch = 0; ch < output_channels; ch++) { - double volume = 1.0; - - if (!((mask >> ch) & 1)) - continue; - - /* MIX_MACRO_VOCALS: same volume for all layers (for layered vocals) */ - /* MIX_MACRO_EQUAL: volume adjusted equally for all layers (for generic downmixing) */ - /* MIX_MACRO_BGM: volume adjusted depending on layers (for layered bgm) */ - if (mode == MIX_MACRO_BGM && ch < max) { - /* reduce a bit main channels (see below) */ - int channel_mixes = selected_channels / max; - if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ - channel_mixes += 1; - channel_mixes -= 1; /* better formula? */ - if (channel_mixes <= 0) /* ??? */ - channel_mixes = 1; - - volume = 1 / sqrt(channel_mixes); - } - if ((mode == MIX_MACRO_BGM && ch >= max) || (mode == MIX_MACRO_EQUAL)) { - /* find how many will be mixed in current channel (earlier channels receive more - * mixes than later ones, ex: selected 8ch + max 3ch: ch0=0+3+6, ch1=1+4+7, ch2=2+5) */ - int channel_mixes = selected_channels / max; - if (channel_mixes <= 0) /* ??? */ - channel_mixes = 1; - if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ - channel_mixes += 1; - - volume = 1 / sqrt(channel_mixes); /* "power" add */ - } - //;VGM_LOG("MIX: layer ch=%i, cur=%i, v=%f\n", ch, current, volume); - - mixing_push_add(vgmstream, current, max + ch, volume); /* ch adjusted considering upmixed channels */ - current++; - if (current >= max) - current = 0; - } - - /* remove all mixed channels */ - mixing_push_killmix(vgmstream, max); -} - -void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max) { - mixing_data *data = vgmstream->mixing_data; - int current, ch, track, track_ch, track_num, output_channels; - int32_t change_pos, change_next, change_time; - - if (!data) - return; - if (max <= 0 || data->output_channels <= max) - return; - if (!vgmstream->loop_flag) /* maybe force loop? */ - return; - - /* this probably only makes sense for even channels so upmix before if needed) */ - output_channels = data->output_channels; - if (output_channels % 2) { - mixing_push_upmix(vgmstream, output_channels); - output_channels += 1; - } - - /* set loops to hear all track changes */ - track_num = output_channels / max; - if (vgmstream->config.loop_count < track_num) { - vgmstream->config.loop_count = track_num; - vgmstream->config.loop_count_set = 1; - vgmstream->config.config_set = 1; - } - - ch = 0; - for (track = 0; track < track_num; track++) { - double volume = 1.0; /* won't play at the same time, no volume change needed */ - - int loop_pre = vgmstream->loop_start_sample; - int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample; - change_pos = loop_pre + loop_samples * track; - change_next = loop_pre + loop_samples * (track + 1); - change_time = 15.0 * vgmstream->sample_rate; /* in secs */ - - for (track_ch = 0; track_ch < max; track_ch++) { - if (track > 0) { /* fade-in when prev track fades-out */ - mixing_push_fade(vgmstream, ch + track_ch, 0.0, volume, '(', -1, change_pos, change_pos + change_time, -1); - } - - if (track + 1 < track_num) { /* fade-out when next track fades-in */ - mixing_push_fade(vgmstream, ch + track_ch, volume, 0.0, ')', -1, change_next, change_next + change_time, -1); - } - } - - ch += max; - } - - /* mix all tracks into first */ - current = 0; - for (ch = max; ch < output_channels; ch++) { - mixing_push_add(vgmstream, current, ch, 1.0); /* won't play at the same time, no volume change needed */ - - current++; - if (current >= max) - current = 0; - } - - /* remove unneeded channels */ - mixing_push_killmix(vgmstream, max); -} - -void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max, char mode) { - mixing_data *data = vgmstream->mixing_data; - int current, ch, layer, layer_ch, layer_num, loop, output_channels; - int32_t change_pos, change_time; - - if (!data) - return; - if (max <= 0 || data->output_channels <= max) - return; - if (!vgmstream->loop_flag) /* maybe force loop? */ - return; - - /* this probably only makes sense for even channels so upmix before if needed) */ - output_channels = data->output_channels; - if (output_channels % 2) { - mixing_push_upmix(vgmstream, output_channels); - output_channels += 1; - } - - /* set loops to hear all track changes */ - layer_num = output_channels / max; - if (vgmstream->config.loop_count < layer_num) { - vgmstream->config.loop_count = layer_num; - vgmstream->config.loop_count_set = 1; - vgmstream->config.config_set = 1; - } - - /* MIX_MACRO_VOCALS: constant volume - * MIX_MACRO_EQUAL: sets fades to successively lower/equalize volume per loop for each layer - * (to keep final volume constant-ish), ex. 3 layers/loops, 2 max: - * - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]-- - * - layer1 (ch2+3): loop0 --[0.0]--, loop1 (=0.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]-- - * - layer2 (ch4+5): loop0 --[0.0]--, loop1 ---[0.0]--, loop2 (=0.0..0.5, loop3 --[0.5/end]-- - * MIX_MACRO_BGM: similar but 1st layer (main) has higher/delayed volume: - * - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..1.0, loop2 )=1.0..0.7, loop3 --[0.7/end]-- - */ - for (loop = 1; loop < layer_num; loop++) { - double volume1 = 1.0; - double volume2 = 1.0; - - int loop_pre = vgmstream->loop_start_sample; - int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample; - change_pos = loop_pre + loop_samples * loop; - change_time = 10.0 * vgmstream->sample_rate; /* in secs */ - - if (mode == MIX_MACRO_EQUAL) { - volume1 = 1 / sqrt(loop + 0); - volume2 = 1 / sqrt(loop + 1); - } - - ch = 0; - for (layer = 0; layer < layer_num; layer++) { - char type; - - if (mode == MIX_MACRO_BGM) { - if (layer == 0) { - volume1 = 1 / sqrt(loop - 1 <= 0 ? 1 : loop - 1); - volume2 = 1 / sqrt(loop + 0); - } - else { - volume1 = 1 / sqrt(loop + 0); - volume2 = 1 / sqrt(loop + 1); - } - } - - if (layer > loop) { /* not playing yet (volume is implicitly 0.0 from first fade in) */ - continue; - } else if (layer == loop) { /* fades in for the first time */ - volume1 = 0.0; - type = '('; - } else { /* otherwise fades out to match other layers's volume */ - type = ')'; - } - - //;VGM_LOG("MIX: loop=%i, layer %i, vol1=%f, vol2=%f\n", loop, layer, volume1, volume2); - - for (layer_ch = 0; layer_ch < max; layer_ch++) { - mixing_push_fade(vgmstream, ch + layer_ch, volume1, volume2, type, -1, change_pos, change_pos + change_time, -1); - } - - ch += max; - } - } - - /* mix all tracks into first */ - current = 0; - for (ch = max; ch < output_channels; ch++) { - mixing_push_add(vgmstream, current, ch, 1.0); - - current++; - if (current >= max) - current = 0; - } - - /* remove unneeded channels */ - mixing_push_killmix(vgmstream, max); -} - - -typedef enum { - pos_FL = 0, - pos_FR = 1, - pos_FC = 2, - pos_LFE = 3, - pos_BL = 4, - pos_BR = 5, - pos_FLC = 6, - pos_FRC = 7, - pos_BC = 8, - pos_SL = 9, - pos_SR = 10, -} mixing_position_t; - -void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) { - mixing_data *data = vgmstream->mixing_data; - int ch, output_channels, mp_in, mp_out, ch_in, ch_out; - channel_mapping_t input_mapping, output_mapping; - const double vol_max = 1.0; - const double vol_sqrt = 1 / sqrt(2); - const double vol_half = 1 / 2; - double matrix[16][16] = {{0}}; - - - if (!data) - return; - if (max <= 1 || data->output_channels <= max || max >= 8) - return; - - /* assume WAV defaults if not set */ - input_mapping = vgmstream->channel_layout; - if (input_mapping == 0) { - switch(data->output_channels) { - case 1: input_mapping = mapping_MONO; break; - case 2: input_mapping = mapping_STEREO; break; - case 3: input_mapping = mapping_2POINT1; break; - case 4: input_mapping = mapping_QUAD; break; - case 5: input_mapping = mapping_5POINT0; break; - case 6: input_mapping = mapping_5POINT1; break; - case 7: input_mapping = mapping_7POINT0; break; - case 8: input_mapping = mapping_7POINT1; break; - default: return; - } - } - - /* build mapping matrix[input channel][output channel] = volume, - * using standard WAV/AC3 downmix formulas - * - https://www.audiokinetic.com/library/edge/?source=Help&id=downmix_tables - * - https://www.audiokinetic.com/library/edge/?source=Help&id=standard_configurations - */ - switch(max) { - case 1: - output_mapping = mapping_MONO; - matrix[pos_FL][pos_FC] = vol_sqrt; - matrix[pos_FR][pos_FC] = vol_sqrt; - matrix[pos_FC][pos_FC] = vol_max; - matrix[pos_SL][pos_FC] = vol_half; - matrix[pos_SR][pos_FC] = vol_half; - matrix[pos_BL][pos_FC] = vol_half; - matrix[pos_BR][pos_FC] = vol_half; - break; - case 2: - output_mapping = mapping_STEREO; - matrix[pos_FL][pos_FL] = vol_max; - matrix[pos_FR][pos_FR] = vol_max; - matrix[pos_FC][pos_FL] = vol_sqrt; - matrix[pos_FC][pos_FR] = vol_sqrt; - matrix[pos_SL][pos_FL] = vol_sqrt; - matrix[pos_SR][pos_FR] = vol_sqrt; - matrix[pos_BL][pos_FL] = vol_sqrt; - matrix[pos_BR][pos_FR] = vol_sqrt; - break; - default: - /* not sure if +3ch would use FC/LFE, SL/BR and whatnot without passing extra config, so ignore for now */ - return; - } - - /* save and make N fake channels at the beginning for easier calcs */ - output_channels = data->output_channels; - for (ch = 0; ch < max; ch++) { - mixing_push_upmix(vgmstream, 0); - } - - /* downmix */ - ch_in = 0; - for (mp_in = 0; mp_in < 16; mp_in++) { - /* read input mapping (ex. 5.1) and find channel */ - if (!(input_mapping & (1< max) - break; - } - - ch_in++; - if (ch_in >= output_channels) - break; - } - - /* remove unneeded channels */ - mixing_push_killmix(vgmstream, max); -} /* ******************************************************************* */ diff --git a/src/base/mixing_commands.c b/src/base/mixing_commands.c new file mode 100644 index 000000000..44c138d90 --- /dev/null +++ b/src/base/mixing_commands.c @@ -0,0 +1,254 @@ +#include "../vgmstream.h" +#include "../util/channel_mappings.h" +#include "mixing.h" +#include "mixing_priv.h" +#include +#include + + +static int add_mixing(VGMSTREAM* vgmstream, mix_command_data *mix) { + mixing_data *data = vgmstream->mixing_data; + if (!data) return 0; + + + if (data->mixing_on) { + VGM_LOG("MIX: ignoring new mixes when mixing active\n"); + return 0; /* to avoid down/upmixing after activation */ + } + + if (data->mixing_count + 1 > data->mixing_size) { + VGM_LOG("MIX: too many mixes\n"); + return 0; + } + + data->mixing_chain[data->mixing_count] = *mix; /* memcpy */ + data->mixing_count++; + + + if (mix->command == MIX_FADE) { + data->has_fade = 1; + } + else { + data->has_non_fade = 1; + } + + //;VGM_LOG("MIX: total %i\n", data->mixing_count); + return 1; +} + + +void mixing_push_swap(VGMSTREAM* vgmstream, int ch_dst, int ch_src) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + + if (ch_dst < 0 || ch_src < 0 || ch_dst == ch_src) return; + if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return; + mix.command = MIX_SWAP; + mix.ch_dst = ch_dst; + mix.ch_src = ch_src; + + add_mixing(vgmstream, &mix); +} + +void mixing_push_add(VGMSTREAM* vgmstream, int ch_dst, int ch_src, double volume) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + if (!data) return; + + //if (volume < 0.0) return; /* negative volume inverts the waveform */ + if (volume == 0.0) return; /* ch_src becomes silent and nothing is added */ + if (ch_dst < 0 || ch_src < 0) return; + if (!data || ch_dst >= data->output_channels || ch_src >= data->output_channels) return; + + mix.command = (volume == 1.0) ? MIX_ADD_COPY : MIX_ADD; + mix.ch_dst = ch_dst; + mix.ch_src = ch_src; + mix.vol = volume; + + //;VGM_LOG("MIX: add %i+%i*%f\n", ch_dst,ch_src,volume); + add_mixing(vgmstream, &mix); +} + +void mixing_push_volume(VGMSTREAM* vgmstream, int ch_dst, double volume) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + + //if (ch_dst < 0) return; /* means all channels */ + //if (volume < 0.0) return; /* negative volume inverts the waveform */ + if (volume == 1.0) return; /* no change */ + if (!data || ch_dst >= data->output_channels) return; + + mix.command = MIX_VOLUME; //if (volume == 0.0) MIX_VOLUME0 /* could simplify */ + mix.ch_dst = ch_dst; + mix.vol = volume; + + //;VGM_LOG("MIX: volume %i*%f\n", ch_dst,volume); + add_mixing(vgmstream, &mix); +} + +void mixing_push_limit(VGMSTREAM* vgmstream, int ch_dst, double volume) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + + //if (ch_dst < 0) return; /* means all channels */ + if (volume < 0.0) return; + if (volume == 1.0) return; /* no actual difference */ + if (!data || ch_dst >= data->output_channels) return; + //if (volume == 0.0) return; /* dumb but whatevs */ + + mix.command = MIX_LIMIT; + mix.ch_dst = ch_dst; + mix.vol = volume; + + add_mixing(vgmstream, &mix); +} + +void mixing_push_upmix(VGMSTREAM* vgmstream, int ch_dst) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + int ok; + + if (ch_dst < 0) return; + if (!data || ch_dst > data->output_channels || data->output_channels +1 > VGMSTREAM_MAX_CHANNELS) return; + /* dst can be == output_channels here, since we are inserting */ + + mix.command = MIX_UPMIX; + mix.ch_dst = ch_dst; + + ok = add_mixing(vgmstream, &mix); + if (ok) { + data->output_channels += 1; + if (data->mixing_channels < data->output_channels) + data->mixing_channels = data->output_channels; + } +} + +void mixing_push_downmix(VGMSTREAM* vgmstream, int ch_dst) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + int ok; + + if (ch_dst < 0) return; + if (!data || ch_dst >= data->output_channels || data->output_channels - 1 < 1) return; + + mix.command = MIX_DOWNMIX; + mix.ch_dst = ch_dst; + + ok = add_mixing(vgmstream, &mix); + if (ok) { + data->output_channels -= 1; + } +} + +void mixing_push_killmix(VGMSTREAM* vgmstream, int ch_dst) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + int ok; + + if (ch_dst <= 0) return; /* can't kill from first channel */ + if (!data || ch_dst >= data->output_channels) return; + + mix.command = MIX_KILLMIX; + mix.ch_dst = ch_dst; + + //;VGM_LOG("MIX: killmix %i\n", ch_dst); + ok = add_mixing(vgmstream, &mix); + if (ok) { + data->output_channels = ch_dst; /* clamp channels */ + } +} + + +static mix_command_data* get_last_fade(mixing_data *data, int target_channel) { + int i; + for (i = data->mixing_count; i > 0; i--) { + mix_command_data *mix = &data->mixing_chain[i-1]; + if (mix->command != MIX_FADE) + continue; + if (mix->ch_dst == target_channel) + return mix; + } + + return NULL; +} + + +void mixing_push_fade(VGMSTREAM* vgmstream, int ch_dst, double vol_start, double vol_end, char shape, + int32_t time_pre, int32_t time_start, int32_t time_end, int32_t time_post) { + mixing_data *data = vgmstream->mixing_data; + mix_command_data mix = {0}; + mix_command_data *mix_prev; + + + //if (ch_dst < 0) return; /* means all channels */ + if (!data || ch_dst >= data->output_channels) return; + if (time_pre > time_start || time_start > time_end || (time_post >= 0 && time_end > time_post)) return; + if (time_start < 0 || time_end < 0) return; + //if (time_pre < 0 || time_post < 0) return; /* special meaning of file start/end */ + //if (vol_start == vol_end) /* weird but let in case of being used to cancel others fades... maybe? */ + + if (shape == '{' || shape == '}') + shape = 'E'; + if (shape == '(' || shape == ')') + shape = 'H'; + + mix.command = MIX_FADE; + mix.ch_dst = ch_dst; + mix.vol_start = vol_start; + mix.vol_end = vol_end; + mix.shape = shape; + mix.time_pre = time_pre; + mix.time_start = time_start; + mix.time_end = time_end; + mix.time_post = time_post; + + + /* cancel fades and optimize a bit when using negative pre/post: + * - fades work like this: + * <----------|----------|----------> + * pre1 start1 end1 post1 + * - when pre and post are set nothing is done (fade is exact and multiple fades may overlap) + * - when previous fade's post or current fade's pre are negative (meaning file end/start) + * they should cancel each other (to allow chaining fade-in + fade-out + fade-in + etc): + * <----------|----------|----------| |----------|----------|----------> + * pre1 start1 end1 post1 pre2 start2 end2 post2 + * - other cases (previous fade is actually after/in-between current fade) are ignored + * as they're uncommon and hard to optimize + * fades cancel fades of the same channel, and 'all channel' (-1) fades also cancel 'all channels' + */ + mix_prev = get_last_fade(data, mix.ch_dst); + if (mix_prev == NULL) { + if (vol_start == 1.0 && time_pre < 0) + time_pre = time_start; /* fade-out helds default volume before fade start can be clamped */ + if (vol_end == 1.0 && time_post < 0) + time_post = time_end; /* fade-in helds default volume after fade end can be clamped */ + } + else if (mix_prev->time_post < 0 || mix.time_pre < 0) { + int is_prev = 1; + /* test if prev is really cancelled by this */ + if ((mix_prev->time_end > mix.time_start) || + (mix_prev->time_post >= 0 && mix_prev->time_post > mix.time_start) || + (mix.time_pre >= 0 && mix.time_pre < mix_prev->time_end)) + is_prev = 0; + + if (is_prev) { + /* change negative values to actual points */ + if (mix_prev->time_post < 0 && mix.time_pre < 0) { + mix_prev->time_post = mix_prev->time_end; + mix.time_pre = mix_prev->time_post; + } + + if (mix_prev->time_post >= 0 && mix.time_pre < 0) { + mix.time_pre = mix_prev->time_post; + } + else if (mix_prev->time_post < 0 && mix.time_pre >= 0) { + mix_prev->time_post = mix.time_pre; + } + /* else: both define start/ends, do nothing */ + } + /* should only modify prev if add_mixing but meh */ + } + + //;VGM_LOG("MIX: fade %i^%f~%f=%c@%i~%i~%i~%i\n", ch_dst, vol_start, vol_end, shape, time_pre, time_start, time_end, time_post); + add_mixing(vgmstream, &mix); +} diff --git a/src/base/mixing_fades.h b/src/base/mixing_fades.h new file mode 100644 index 000000000..dcf66d338 --- /dev/null +++ b/src/base/mixing_fades.h @@ -0,0 +1,171 @@ +#ifndef _MIXING_FADE_H_ +#define _MIXING_FADE_H_ + +#include "mixing_priv.h" +#include +#include + +#define MIXING_PI 3.14159265358979323846f + + +static inline int is_fade_active(mixing_data *data, int32_t current_start, int32_t current_end) { + int i; + + for (i = 0; i < data->mixing_count; i++) { + mix_command_data *mix = &data->mixing_chain[i]; + int32_t fade_start, fade_end; + float vol_start = mix->vol_start; + + if (mix->command != MIX_FADE) + continue; + + /* check is current range falls within a fade + * (assuming fades were already optimized on add) */ + if (mix->time_pre < 0 && vol_start == 1.0) { + fade_start = mix->time_start; /* ignore unused */ + } + else { + fade_start = mix->time_pre < 0 ? 0 : mix->time_pre; + } + fade_end = mix->time_post < 0 ? INT_MAX : mix->time_post; + + //;VGM_LOG("MIX: fade test, tp=%i, te=%i, cs=%i, ce=%i\n", mix->time_pre, mix->time_post, current_start, current_end); + if (current_start < fade_end && current_end > fade_start) { + //;VGM_LOG("MIX: fade active, cs=%i < fe=%i and ce=%i > fs=%i\n", current_start, fade_end, current_end, fade_start); + return 1; + } + } + + return 0; +} + +static inline int32_t get_current_pos(VGMSTREAM* vgmstream, int32_t sample_count) { + int32_t current_pos; + + if (vgmstream->config_enabled) { + return vgmstream->pstate.play_position; + } + + if (vgmstream->loop_flag && vgmstream->loop_count > 0) { + int loop_pre = vgmstream->loop_start_sample; /* samples before looping */ + int loop_into = (vgmstream->current_sample - vgmstream->loop_start_sample); /* samples after loop */ + int loop_samples = (vgmstream->loop_end_sample - vgmstream->loop_start_sample); /* looped section */ + + current_pos = loop_pre + (loop_samples * vgmstream->loop_count) + loop_into - sample_count; + } + else { + current_pos = (vgmstream->current_sample - sample_count); + } + + return current_pos; +} + +static inline float get_fade_gain_curve(char shape, float index) { + float gain; + + /* don't bother doing calcs near 0.0/1.0 */ + if (index <= 0.0001f || index >= 0.9999f) { + return index; + } + + //todo optimizations: interleave calcs, maybe use cosf, powf, etc? (with extra defines) + + /* (curve math mostly from SoX/FFmpeg) */ + switch(shape) { + /* 2.5f in L/E 'pow' is the attenuation factor, where 5.0 (100db) is common but a bit fast + * (alt calculations with 'exp' from FFmpeg use (factor)*ln(0.1) = -NN.N... */ + + case 'E': /* exponential (for fade-outs, closer to natural decay of sound) */ + //gain = pow(0.1f, (1.0f - index) * 2.5f); + gain = exp(-5.75646273248511f * (1.0f - index)); + break; + case 'L': /* logarithmic (inverse of the above, maybe for crossfades) */ + //gain = 1 - pow(0.1f, (index) * 2.5f); + gain = 1 - exp(-5.75646273248511f * (index)); + break; + + case 'H': /* raised sine wave or cosine wave (for more musical crossfades) */ + gain = (1.0f - cos(index * MIXING_PI)) / 2.0f; + break; + + case 'Q': /* quarter of sine wave (for musical fades) */ + gain = sin(index * MIXING_PI / 2.0f); + break; + + case 'p': /* parabola (maybe for crossfades) */ + gain = 1.0f - sqrt(1.0f - index); + break; + case 'P': /* inverted parabola (maybe for fades) */ + gain = (1.0f - (1.0f - index) * (1.0f - index)); + break; + + case 'T': /* triangular/linear (simpler/sharper fades) */ + default: + gain = index; + break; + } + + return gain; +} + +static int get_fade_gain(mix_command_data *mix, float *out_cur_vol, int32_t current_subpos) { + float cur_vol = 0.0f; + + if ((current_subpos >= mix->time_pre || mix->time_pre < 0) && current_subpos < mix->time_start) { + cur_vol = mix->vol_start; /* before */ + } + else if (current_subpos >= mix->time_end && (current_subpos < mix->time_post || mix->time_post < 0)) { + cur_vol = mix->vol_end; /* after */ + } + else if (current_subpos >= mix->time_start && current_subpos < mix->time_end) { + /* in between */ + float range_vol, range_dur, range_idx, index, gain; + + if (mix->vol_start < mix->vol_end) { /* fade in */ + range_vol = mix->vol_end - mix->vol_start; + range_dur = mix->time_end - mix->time_start; + range_idx = current_subpos - mix->time_start; + index = range_idx / range_dur; + } else { /* fade out */ + range_vol = mix->vol_end - mix->vol_start; + range_dur = mix->time_end - mix->time_start; + range_idx = mix->time_end - current_subpos; + index = range_idx / range_dur; + } + + /* Fading is done like this: + * - find current position within fade duration + * - get linear % (or rather, index from 0.0 .. 1.0) of duration + * - apply shape to % (from linear fade to curved fade) + * - get final volume for that point + * + * Roughly speaking some curve shapes are better for fades (decay rate is more natural + * sounding in that highest to mid/low happens faster but low to lowest takes more time, + * kinda like a gunshot or bell), and others for crossfades (decay of fade-in + fade-out + * is adjusted so that added volume level stays constant-ish). + * + * As curves can fade in two ways ('normal' and curving 'the other way'), they are adjusted + * to get 'normal' shape on both fades (by reversing index and making 1 - gain), thus some + * curves are complementary (exponential fade-in ~= logarithmic fade-out); the following + * are described taking fade-in = normal. + */ + gain = get_fade_gain_curve(mix->shape, index); + + if (mix->vol_start < mix->vol_end) { /* fade in */ + cur_vol = mix->vol_start + range_vol * gain; + } else { /* fade out */ + cur_vol = mix->vol_end - range_vol * gain; //mix->vol_start - range_vol * (1 - gain); + } + } + else { + /* fade is outside reach */ + goto fail; + } + + *out_cur_vol = cur_vol; + return 1; +fail: + return 0; +} + +#endif diff --git a/src/base/mixing_macros.c b/src/base/mixing_macros.c new file mode 100644 index 000000000..1df002ee6 --- /dev/null +++ b/src/base/mixing_macros.c @@ -0,0 +1,578 @@ +#include "../vgmstream.h" +#include "../util/channel_mappings.h" +#include "mixing.h" +#include "mixing_priv.h" +#include +#include + + +#define MIX_MACRO_VOCALS 'v' +#define MIX_MACRO_EQUAL 'e' +#define MIX_MACRO_BGM 'b' + +void mixing_macro_volume(VGMSTREAM* vgmstream, double volume, uint32_t mask) { + mixing_data *data = vgmstream->mixing_data; + int ch; + + if (!data) + return; + + if (mask == 0) { + mixing_push_volume(vgmstream, -1, volume); + return; + } + + for (ch = 0; ch < data->output_channels; ch++) { + if (!((mask >> ch) & 1)) + continue; + mixing_push_volume(vgmstream, ch, volume); + } +} + +void mixing_macro_track(VGMSTREAM* vgmstream, uint32_t mask) { + mixing_data *data = vgmstream->mixing_data; + int ch; + + if (!data) + return; + + if (mask == 0) { + return; + } + + /* reverse remove all channels (easier this way as when removing channels numbers change) */ + for (ch = data->output_channels - 1; ch >= 0; ch--) { + if ((mask >> ch) & 1) + continue; + mixing_push_downmix(vgmstream, ch); + } +} + + +/* get highest channel count */ +static int get_layered_max_channels(VGMSTREAM* vgmstream) { + int i, max; + layered_layout_data* data; + + if (vgmstream->layout_type != layout_layered) + return 0; + + data = vgmstream->layout_data; + + max = 0; + for (i = 0; i < data->layer_count; i++) { + int output_channels = 0; + + mixing_info(data->layers[i], NULL, &output_channels); + + if (max < output_channels) + max = output_channels; + } + + return max; +} + +static int is_layered_auto(VGMSTREAM* vgmstream, int max, char mode) { + int i; + mixing_data *data = vgmstream->mixing_data; + layered_layout_data* l_data; + + + if (vgmstream->layout_type != layout_layered) + return 0; + + /* no channels set and only vocals for now */ + if (max > 0 || mode != MIX_MACRO_VOCALS) + return 0; + + /* no channel down/upmixing (cannot guess output) */ + for (i = 0; i < data->mixing_count; i++) { + mix_command_t mix = data->mixing_chain[i].command; + if (mix == MIX_UPMIX || mix == MIX_DOWNMIX || mix == MIX_KILLMIX) /*mix == MIX_SWAP || ??? */ + return 0; + } + + /* only previsible cases */ + l_data = vgmstream->layout_data; + for (i = 0; i < l_data->layer_count; i++) { + int output_channels = 0; + + mixing_info(l_data->layers[i], NULL, &output_channels); + + if (output_channels > 8) + return 0; + } + + return 1; +} + + +/* special layering, where channels are respected (so Ls only go to Ls), also more optimized */ +static void mixing_macro_layer_auto(VGMSTREAM* vgmstream, int max, char mode) { + layered_layout_data* ldata = vgmstream->layout_data; + int i, ch; + int target_layer = 0, target_chs = 0, ch_max, target_ch = 0, target_silence = 0; + int ch_num; + + /* With N layers like: (ch1 ch2) (ch1 ch2 ch3 ch4) (ch1 ch2), output is normally 2+4+2=8ch. + * We want to find highest layer (ch1..4) = 4ch, add other channels to it and drop them */ + + /* find target "main" channels (will be first most of the time) */ + ch_num = 0; + ch_max = 0; + for (i = 0; i < ldata->layer_count; i++) { + int layer_chs = 0; + + mixing_info(ldata->layers[i], NULL, &layer_chs); + + if (ch_max < layer_chs || (ch_max == layer_chs && target_silence)) { + target_ch = ch_num; + target_chs = layer_chs; + target_layer = i; + ch_max = layer_chs; + /* avoid using silence as main if possible for minor optimization */ + target_silence = (ldata->layers[i]->coding_type == coding_SILENCE); + } + + ch_num += layer_chs; + } + + /* all silences? */ + if (!target_chs) { + target_ch = 0; + target_chs = 0; + target_layer = 0; + mixing_info(ldata->layers[0], NULL, &target_chs); + } + + /* add other channels to target (assumes standard channel mapping to simplify) + * most of the time all layers will have same number of channels though */ + ch_num = 0; + for (i = 0; i < ldata->layer_count; i++) { + int layer_chs = 0; + + if (target_layer == i) { + ch_num += target_chs; + continue; + } + + mixing_info(ldata->layers[i], NULL, &layer_chs); + + if (ldata->layers[i]->coding_type == coding_SILENCE) { + ch_num += layer_chs; + continue; /* unlikely but sometimes in Wwise */ + } + + if (layer_chs == target_chs) { + /* 1:1 mapping */ + for (ch = 0; ch < layer_chs; ch++) { + mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0); + } + } + else { + const double vol_sqrt = 1 / sqrt(2); + + /* extra mixing for better sound in some cases (assumes layer_chs is lower than target_chs) */ + switch(layer_chs) { + case 1: + mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, vol_sqrt); + mixing_push_add(vgmstream, target_ch + 1, ch_num + 0, vol_sqrt); + break; + case 2: + mixing_push_add(vgmstream, target_ch + 0, ch_num + 0, 1.0); + mixing_push_add(vgmstream, target_ch + 1, ch_num + 1, 1.0); + break; + default: /* less common */ + //TODO add other mixes, depends on target_chs + mapping (ex. 4.0 to 5.0 != 5.1, 2.1 xiph to 5.1 != 5.1 xiph) + for (ch = 0; ch < layer_chs; ch++) { + mixing_push_add(vgmstream, target_ch + ch, ch_num + ch, 1.0); + } + break; + } + } + + ch_num += layer_chs; + } + + /* drop non-target channels */ + ch_num = 0; + for (i = 0; i < ldata->layer_count; i++) { + + if (i < target_layer) { /* least common, hopefully (slower to drop chs 1 by 1) */ + int layer_chs = 0; + mixing_info(ldata->layers[i], NULL, &layer_chs); + + for (ch = 0; ch < layer_chs; ch++) { + mixing_push_downmix(vgmstream, ch_num); //+ ch + } + + //ch_num += layer_chs; /* dropped channels change this */ + } + else if (i == target_layer) { + ch_num += target_chs; + } + else { /* most common, hopefully (faster) */ + mixing_push_killmix(vgmstream, ch_num); + break; + } + } +} + + +void mixing_macro_layer(VGMSTREAM* vgmstream, int max, uint32_t mask, char mode) { + mixing_data *data = vgmstream->mixing_data; + int current, ch, output_channels, selected_channels; + + if (!data) + return; + + if (is_layered_auto(vgmstream, max, mode)) { + //;VGM_LOG("MIX: auto layer mode\n"); + mixing_macro_layer_auto(vgmstream, max, mode); + return; + } + //;VGM_LOG("MIX: regular layer mode\n"); + + if (max == 0) /* auto calculate */ + max = get_layered_max_channels(vgmstream); + + if (max <= 0 || data->output_channels <= max) + return; + + /* set all channels (non-existant channels will be ignored) */ + if (mask == 0) { + mask = ~mask; + } + + /* save before adding fake channels */ + output_channels = data->output_channels; + + /* count possibly set channels */ + selected_channels = 0; + for (ch = 0; ch < output_channels; ch++) { + selected_channels += (mask >> ch) & 1; + } + + /* make N fake channels at the beginning for easier calcs */ + for (ch = 0; ch < max; ch++) { + mixing_push_upmix(vgmstream, 0); + } + + /* add all layers in this order: ch0: 0, 0+N, 0+N*2 ... / ch1: 1, 1+N ... */ + current = 0; + for (ch = 0; ch < output_channels; ch++) { + double volume = 1.0; + + if (!((mask >> ch) & 1)) + continue; + + /* MIX_MACRO_VOCALS: same volume for all layers (for layered vocals) */ + /* MIX_MACRO_EQUAL: volume adjusted equally for all layers (for generic downmixing) */ + /* MIX_MACRO_BGM: volume adjusted depending on layers (for layered bgm) */ + if (mode == MIX_MACRO_BGM && ch < max) { + /* reduce a bit main channels (see below) */ + int channel_mixes = selected_channels / max; + if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ + channel_mixes += 1; + channel_mixes -= 1; /* better formula? */ + if (channel_mixes <= 0) /* ??? */ + channel_mixes = 1; + + volume = 1 / sqrt(channel_mixes); + } + if ((mode == MIX_MACRO_BGM && ch >= max) || (mode == MIX_MACRO_EQUAL)) { + /* find how many will be mixed in current channel (earlier channels receive more + * mixes than later ones, ex: selected 8ch + max 3ch: ch0=0+3+6, ch1=1+4+7, ch2=2+5) */ + int channel_mixes = selected_channels / max; + if (channel_mixes <= 0) /* ??? */ + channel_mixes = 1; + if (current < selected_channels % (channel_mixes * max)) /* may be simplified? */ + channel_mixes += 1; + + volume = 1 / sqrt(channel_mixes); /* "power" add */ + } + //;VGM_LOG("MIX: layer ch=%i, cur=%i, v=%f\n", ch, current, volume); + + mixing_push_add(vgmstream, current, max + ch, volume); /* ch adjusted considering upmixed channels */ + current++; + if (current >= max) + current = 0; + } + + /* remove all mixed channels */ + mixing_push_killmix(vgmstream, max); +} + +void mixing_macro_crosstrack(VGMSTREAM* vgmstream, int max) { + mixing_data *data = vgmstream->mixing_data; + int current, ch, track, track_ch, track_num, output_channels; + int32_t change_pos, change_next, change_time; + + if (!data) + return; + if (max <= 0 || data->output_channels <= max) + return; + if (!vgmstream->loop_flag) /* maybe force loop? */ + return; + + /* this probably only makes sense for even channels so upmix before if needed) */ + output_channels = data->output_channels; + if (output_channels % 2) { + mixing_push_upmix(vgmstream, output_channels); + output_channels += 1; + } + + /* set loops to hear all track changes */ + track_num = output_channels / max; + if (vgmstream->config.loop_count < track_num) { + vgmstream->config.loop_count = track_num; + vgmstream->config.loop_count_set = 1; + vgmstream->config.config_set = 1; + } + + ch = 0; + for (track = 0; track < track_num; track++) { + double volume = 1.0; /* won't play at the same time, no volume change needed */ + + int loop_pre = vgmstream->loop_start_sample; + int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample; + change_pos = loop_pre + loop_samples * track; + change_next = loop_pre + loop_samples * (track + 1); + change_time = 15.0 * vgmstream->sample_rate; /* in secs */ + + for (track_ch = 0; track_ch < max; track_ch++) { + if (track > 0) { /* fade-in when prev track fades-out */ + mixing_push_fade(vgmstream, ch + track_ch, 0.0, volume, '(', -1, change_pos, change_pos + change_time, -1); + } + + if (track + 1 < track_num) { /* fade-out when next track fades-in */ + mixing_push_fade(vgmstream, ch + track_ch, volume, 0.0, ')', -1, change_next, change_next + change_time, -1); + } + } + + ch += max; + } + + /* mix all tracks into first */ + current = 0; + for (ch = max; ch < output_channels; ch++) { + mixing_push_add(vgmstream, current, ch, 1.0); /* won't play at the same time, no volume change needed */ + + current++; + if (current >= max) + current = 0; + } + + /* remove unneeded channels */ + mixing_push_killmix(vgmstream, max); +} + +void mixing_macro_crosslayer(VGMSTREAM* vgmstream, int max, char mode) { + mixing_data *data = vgmstream->mixing_data; + int current, ch, layer, layer_ch, layer_num, loop, output_channels; + int32_t change_pos, change_time; + + if (!data) + return; + if (max <= 0 || data->output_channels <= max) + return; + if (!vgmstream->loop_flag) /* maybe force loop? */ + return; + + /* this probably only makes sense for even channels so upmix before if needed) */ + output_channels = data->output_channels; + if (output_channels % 2) { + mixing_push_upmix(vgmstream, output_channels); + output_channels += 1; + } + + /* set loops to hear all track changes */ + layer_num = output_channels / max; + if (vgmstream->config.loop_count < layer_num) { + vgmstream->config.loop_count = layer_num; + vgmstream->config.loop_count_set = 1; + vgmstream->config.config_set = 1; + } + + /* MIX_MACRO_VOCALS: constant volume + * MIX_MACRO_EQUAL: sets fades to successively lower/equalize volume per loop for each layer + * (to keep final volume constant-ish), ex. 3 layers/loops, 2 max: + * - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]-- + * - layer1 (ch2+3): loop0 --[0.0]--, loop1 (=0.0..0.7, loop2 )=0.7..0.5, loop3 --[0.5/end]-- + * - layer2 (ch4+5): loop0 --[0.0]--, loop1 ---[0.0]--, loop2 (=0.0..0.5, loop3 --[0.5/end]-- + * MIX_MACRO_BGM: similar but 1st layer (main) has higher/delayed volume: + * - layer0 (ch0+1): loop0 --[1.0]--, loop1 )=1.0..1.0, loop2 )=1.0..0.7, loop3 --[0.7/end]-- + */ + for (loop = 1; loop < layer_num; loop++) { + double volume1 = 1.0; + double volume2 = 1.0; + + int loop_pre = vgmstream->loop_start_sample; + int loop_samples = vgmstream->loop_end_sample - vgmstream->loop_start_sample; + change_pos = loop_pre + loop_samples * loop; + change_time = 10.0 * vgmstream->sample_rate; /* in secs */ + + if (mode == MIX_MACRO_EQUAL) { + volume1 = 1 / sqrt(loop + 0); + volume2 = 1 / sqrt(loop + 1); + } + + ch = 0; + for (layer = 0; layer < layer_num; layer++) { + char type; + + if (mode == MIX_MACRO_BGM) { + if (layer == 0) { + volume1 = 1 / sqrt(loop - 1 <= 0 ? 1 : loop - 1); + volume2 = 1 / sqrt(loop + 0); + } + else { + volume1 = 1 / sqrt(loop + 0); + volume2 = 1 / sqrt(loop + 1); + } + } + + if (layer > loop) { /* not playing yet (volume is implicitly 0.0 from first fade in) */ + continue; + } else if (layer == loop) { /* fades in for the first time */ + volume1 = 0.0; + type = '('; + } else { /* otherwise fades out to match other layers's volume */ + type = ')'; + } + + //;VGM_LOG("MIX: loop=%i, layer %i, vol1=%f, vol2=%f\n", loop, layer, volume1, volume2); + + for (layer_ch = 0; layer_ch < max; layer_ch++) { + mixing_push_fade(vgmstream, ch + layer_ch, volume1, volume2, type, -1, change_pos, change_pos + change_time, -1); + } + + ch += max; + } + } + + /* mix all tracks into first */ + current = 0; + for (ch = max; ch < output_channels; ch++) { + mixing_push_add(vgmstream, current, ch, 1.0); + + current++; + if (current >= max) + current = 0; + } + + /* remove unneeded channels */ + mixing_push_killmix(vgmstream, max); +} + + +typedef enum { + pos_FL = 0, + pos_FR = 1, + pos_FC = 2, + pos_LFE = 3, + pos_BL = 4, + pos_BR = 5, + pos_FLC = 6, + pos_FRC = 7, + pos_BC = 8, + pos_SL = 9, + pos_SR = 10, +} mixing_position_t; + +void mixing_macro_downmix(VGMSTREAM* vgmstream, int max /*, mapping_t output_mapping*/) { + mixing_data *data = vgmstream->mixing_data; + int ch, output_channels, mp_in, mp_out, ch_in, ch_out; + channel_mapping_t input_mapping, output_mapping; + const double vol_max = 1.0; + const double vol_sqrt = 1 / sqrt(2); + const double vol_half = 1 / 2; + double matrix[16][16] = {{0}}; + + + if (!data) + return; + if (max <= 1 || data->output_channels <= max || max >= 8) + return; + + /* assume WAV defaults if not set */ + input_mapping = vgmstream->channel_layout; + if (input_mapping == 0) { + switch(data->output_channels) { + case 1: input_mapping = mapping_MONO; break; + case 2: input_mapping = mapping_STEREO; break; + case 3: input_mapping = mapping_2POINT1; break; + case 4: input_mapping = mapping_QUAD; break; + case 5: input_mapping = mapping_5POINT0; break; + case 6: input_mapping = mapping_5POINT1; break; + case 7: input_mapping = mapping_7POINT0; break; + case 8: input_mapping = mapping_7POINT1; break; + default: return; + } + } + + /* build mapping matrix[input channel][output channel] = volume, + * using standard WAV/AC3 downmix formulas + * - https://www.audiokinetic.com/library/edge/?source=Help&id=downmix_tables + * - https://www.audiokinetic.com/library/edge/?source=Help&id=standard_configurations + */ + switch(max) { + case 1: + output_mapping = mapping_MONO; + matrix[pos_FL][pos_FC] = vol_sqrt; + matrix[pos_FR][pos_FC] = vol_sqrt; + matrix[pos_FC][pos_FC] = vol_max; + matrix[pos_SL][pos_FC] = vol_half; + matrix[pos_SR][pos_FC] = vol_half; + matrix[pos_BL][pos_FC] = vol_half; + matrix[pos_BR][pos_FC] = vol_half; + break; + case 2: + output_mapping = mapping_STEREO; + matrix[pos_FL][pos_FL] = vol_max; + matrix[pos_FR][pos_FR] = vol_max; + matrix[pos_FC][pos_FL] = vol_sqrt; + matrix[pos_FC][pos_FR] = vol_sqrt; + matrix[pos_SL][pos_FL] = vol_sqrt; + matrix[pos_SR][pos_FR] = vol_sqrt; + matrix[pos_BL][pos_FL] = vol_sqrt; + matrix[pos_BR][pos_FR] = vol_sqrt; + break; + default: + /* not sure if +3ch would use FC/LFE, SL/BR and whatnot without passing extra config, so ignore for now */ + return; + } + + /* save and make N fake channels at the beginning for easier calcs */ + output_channels = data->output_channels; + for (ch = 0; ch < max; ch++) { + mixing_push_upmix(vgmstream, 0); + } + + /* downmix */ + ch_in = 0; + for (mp_in = 0; mp_in < 16; mp_in++) { + /* read input mapping (ex. 5.1) and find channel */ + if (!(input_mapping & (1< max) + break; + } + + ch_in++; + if (ch_in >= output_channels) + break; + } + + /* remove unneeded channels */ + mixing_push_killmix(vgmstream, max); +} diff --git a/src/base/mixing_priv.h b/src/base/mixing_priv.h new file mode 100644 index 000000000..a21f83d86 --- /dev/null +++ b/src/base/mixing_priv.h @@ -0,0 +1,52 @@ +#ifndef _MIXING_PRIV_H_ +#define _MIXING_PRIV_H_ + +#include "../vgmstream.h" +#define VGMSTREAM_MAX_MIXING 512 + +/* mixing info */ +typedef enum { + MIX_SWAP, + MIX_ADD, + MIX_ADD_COPY, + MIX_VOLUME, + MIX_LIMIT, + MIX_UPMIX, + MIX_DOWNMIX, + MIX_KILLMIX, + MIX_FADE +} mix_command_t; + +typedef struct { + mix_command_t command; + /* common */ + int ch_dst; + int ch_src; + float vol; + + /* fade envelope */ + float vol_start; /* volume from pre to start */ + float vol_end; /* volume from end to post */ + char shape; /* curve type */ + int32_t time_pre; /* position before time_start where vol_start applies (-1 = beginning) */ + int32_t time_start; /* fade start position where vol changes from vol_start to vol_end */ + int32_t time_end; /* fade end position where vol changes from vol_start to vol_end */ + int32_t time_post; /* position after time_end where vol_end applies (-1 = end) */ +} mix_command_data; + +typedef struct { + int mixing_channels; /* max channels needed to mix */ + int output_channels; /* resulting channels after mixing */ + int mixing_on; /* mixing allowed */ + int mixing_count; /* mixing number */ + size_t mixing_size; /* mixing max */ + mix_command_data mixing_chain[VGMSTREAM_MAX_MIXING]; /* effects to apply (could be alloc'ed but to simplify...) */ + float* mixbuf; /* internal mixing buffer */ + + /* fades only apply at some points, other mixes are active */ + int has_non_fade; + int has_fade; +} mixing_data; + + +#endif diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index af4356281..9e8b13da6 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -88,6 +88,8 @@ + + @@ -197,6 +199,8 @@ + + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index e7cde615a..726b131d6 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -89,6 +89,12 @@ base\Header Files + + base\Header Files + + + base\Header Files + base\Header Files @@ -412,6 +418,12 @@ base\Source Files + + base\Source Files + + + base\Source Files + base\Source Files From 76aeb25038cae59b11fc72e23d6e7fdde58f5f66 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 15 Aug 2023 19:48:14 +0200 Subject: [PATCH 122/141] Add FSB key --- src/meta/fsb_keys.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/meta/fsb_keys.h b/src/meta/fsb_keys.h index b852a04ec..38d14d8b8 100644 --- a/src/meta/fsb_keys.h +++ b/src/meta/fsb_keys.h @@ -71,6 +71,7 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSB5_STD, FSBKEY_ADD("281ad163160cfc16f9a22c6755a64fad") }, // Ash Echoes beta (Android) { MODE_FSB5_STD, FSBKEY_ADD("Aurogon666") }, // Afterimage demo (PC) { MODE_FSB5_STD, FSBKEY_ADD("IfYouLikeThosesSoundsWhyNotRenumerateTheir2Authors?") }, // Blanc (PC/Switch) + { MODE_FSB5_STD, FSBKEY_ADD("L36nshM520") }, // Nishuihan Mobile (Android) }; static const int fsbkey_list_count = sizeof(fsbkey_list) / sizeof(fsbkey_list[0]); From 21c92d3d8cfbd30e01d089795a2f671b9a6e430e Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 15 Aug 2023 19:48:43 +0200 Subject: [PATCH 123/141] Add HCA key --- src/meta/hca_keys.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/meta/hca_keys.h b/src/meta/hca_keys.h index 95fee4ebe..6d44f509c 100644 --- a/src/meta/hca_keys.h +++ b/src/meta/hca_keys.h @@ -1248,6 +1248,9 @@ static const hcakey_info hcakey_list[] = { // Tower of Sky (Android) {5893902754391672}, // 0014F0792C042678 + // The Irregular at Magic High School: Reloaded Memory (Android) + {7181280307767738368}, // 63A9086451010000 + }; #endif/*_HCA_KEYS_H_*/ From dcadb19e3575f22d5496e5e1baa8be1c50611dd4 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 15 Aug 2023 19:48:54 +0200 Subject: [PATCH 124/141] logs --- src/meta/fsb5_fev.c | 15 ++++++++++----- src/meta/txth.c | 10 +++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/meta/fsb5_fev.c b/src/meta/fsb5_fev.c index 6a59ae3d7..8ba874523 100644 --- a/src/meta/fsb5_fev.c +++ b/src/meta/fsb5_fev.c @@ -18,12 +18,12 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) { /* checks */ if (!is_id32be(0x00,sf, "RIFF")) - goto fail; + return NULL; if (!is_id32be(0x08,sf, "FEV ")) - goto fail; + return NULL; if (!check_extensions(sf, "bank")) - goto fail; + return NULL; version = read_u32le(0x14,sf); /* newer FEV have some kind of sub-version at 0x18 */ @@ -102,8 +102,10 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) { off_t fsb5_offset = read_u32le(bank_offset + 0x04 + entry_size*i + 0x00,sf); size_t fsb5_size = read_u32le(bank_offset+0x08 + entry_size*i,sf); int fsb5_subsongs = get_subsongs(sf, fsb5_offset, fsb5_size); - if (!fsb5_subsongs) + if (!fsb5_subsongs) { + vgm_logi("FSB: couldn't load bank (encrypted?)\n"); goto fail; + } /* target in range */ if (target_subsong >= total_subsongs + 1 && target_subsong < total_subsongs + 1 + fsb5_subsongs) { @@ -140,7 +142,10 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) { vgmstream = (read_u32be(0x00, temp_sf) == 0x46534235) ? /* "FSB5" (better flag?)*/ init_vgmstream_fsb5(temp_sf) : init_vgmstream_fsb_encrypted(temp_sf); - if (!vgmstream) goto fail; + if (!vgmstream) { + vgm_logi("FSB: couldn't load bank (encrypted?)\n"); + goto fail; + } vgmstream->stream_index = sf->stream_index; //target_subsong; /* 0-index matters */ vgmstream->num_streams = total_subsongs; diff --git a/src/meta/txth.c b/src/meta/txth.c index 6cc2a04e2..b3e0aff9e 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -1983,7 +1983,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_logi("TXTH: wrong offset over file size (%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; } @@ -1996,7 +1996,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ offset = offset + subsong_spacing * (txth->target_subsong - 1); if (txth->debug) - vgm_logi("TXTH: use value at 0x%x (%s %ib)\n", offset, big_endian ? "BE" : "LE", size * 8); + vgm_logi("TXTH: use value at 0x%x (%s %ib)\n", offset, big_endian ? "BE" : "LE", size * 8); switch(size) { case 1: value = read_u8(offset,sf); break; @@ -2015,7 +2015,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ value_read = 1; if (txth->debug) - vgm_logi(hex ? "TXTH: use constant 0x%x\n" : "TXTH: use constant %i\n", value); + vgm_logi(hex ? "TXTH: use constant 0x%x\n" : "TXTH: use constant %i\n", value); } else { /* known field */ if ((n = is_string_field(val,"interleave"))) value = txth->interleave; @@ -2074,7 +2074,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ value_read = 1; if (txth->debug) - vgm_logi("TXTH: use field value 0x%x\n", value); + vgm_logi("TXTH: use field value 0x%x\n", value); } /* apply simple left-to-right math though, for now "(" ")" are counted and validated @@ -2117,7 +2117,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_ *out_value = result; if (txth->debug) - vgm_logi("TXTH: final value: %u (0x%x)\n", result, result); + vgm_logi("TXTH: final value: %u (0x%x)\n", result, result); return 1; fail: From 2930c8d20ba57253943429c9b2ce41b2ba16cdea Mon Sep 17 00:00:00 2001 From: Adam Gashlin Date: Thu, 17 Aug 2023 21:44:37 -0700 Subject: [PATCH 125/141] Handle 32-bit float PCM RIFF --- src/meta/riff.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/meta/riff.c b/src/meta/riff.c index 2e5a73fde..b206a07c0 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -177,6 +177,14 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk goto fail; } break; + case 0x003: /* floating point PCM */ + if (fmt->bps == 32) { + fmt->coding_type = coding_PCMFLOAT; + } else { + goto fail; + } + fmt->interleave = fmt->block_size / fmt->channels; + break; case 0x0011: /* MS-IMA ADPCM [Layton Brothers: Mystery Room (iOS/Android)] */ if (fmt->bps != 4) goto fail; @@ -704,6 +712,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { case coding_PCM24LE: case coding_PCM16LE: case coding_PCM8_U: + case coding_PCMFLOAT: vgmstream->num_samples = pcm_bytes_to_samples(data_size, fmt.channels, fmt.bps); break; From 3a49c090a09b5c7d95a3f158009dbfe8d0d6c08e Mon Sep 17 00:00:00 2001 From: Adam Gashlin Date: Thu, 17 Aug 2023 22:20:22 -0700 Subject: [PATCH 126/141] Support 32-bit integer PCM in RIFF From masters for a Sonic Origins mod --- src/base/decode.c | 9 +++++++++ src/coding/coding.h | 1 + src/coding/pcm_decoder.c | 15 +++++++++++++++ src/formats.c | 1 + src/meta/riff.c | 4 ++++ src/vgmstream_types.h | 1 + 6 files changed, 31 insertions(+) diff --git a/src/base/decode.c b/src/base/decode.c index 61bc66bba..3a9d2a1e8 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -367,6 +367,7 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { case coding_PCMFLOAT: case coding_PCM24LE: case coding_PCM24BE: + case coding_PCM32LE: return 1; #ifdef VGM_USE_VORBIS case coding_OGG_VORBIS: @@ -594,6 +595,7 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) { case coding_ALAW: return 0x01; case coding_PCMFLOAT: + case coding_PCM32LE: return 0x04; case coding_PCM24LE: case coding_PCM24BE: @@ -907,6 +909,13 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ } break; + case coding_PCM32LE: + for (ch = 0; ch < vgmstream->channels; ch++) { + decode_pcm32le(&vgmstream->ch[ch], buffer+ch, + vgmstream->channels, vgmstream->samples_into_block, samples_to_do); + } + break; + case coding_NDS_IMA: for (ch = 0; ch < vgmstream->channels; ch++) { decode_nds_ima(&vgmstream->ch[ch], buffer+ch, diff --git a/src/coding/coding.h b/src/coding/coding.h index c41f7f5b7..edceec6cc 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -96,6 +96,7 @@ void decode_alaw(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, void decode_pcmfloat(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int big_endian); void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_pcm24be(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); +void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); int32_t pcm24_bytes_to_samples(size_t bytes, int channels); int32_t pcm16_bytes_to_samples(size_t bytes, int channels); diff --git a/src/coding/pcm_decoder.c b/src/coding/pcm_decoder.c index 7a1e61e08..9b7dcccba 100644 --- a/src/coding/pcm_decoder.c +++ b/src/coding/pcm_decoder.c @@ -238,11 +238,26 @@ void decode_pcm24le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci } } +void decode_pcm32le(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + int32_t sample_count; + + for (i=first_sample,sample_count=0; ioffset + i * 0x04; + int32_t v = read_s32le(offset, stream->streamfile); + outbuf[sample_count] = (v >> 16); + } +} + int32_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample) { if (channels <= 0 || bits_per_sample <= 0) return 0; return ((int64_t)bytes * 8) / channels / bits_per_sample; } +int32_t pcm32_bytes_to_samples(size_t bytes, int channels) { + return pcm_bytes_to_samples(bytes, channels, 32); +} + int32_t pcm24_bytes_to_samples(size_t bytes, int channels) { return pcm_bytes_to_samples(bytes, channels, 24); } diff --git a/src/formats.c b/src/formats.c index c15c82b63..0a3974985 100644 --- a/src/formats.c +++ b/src/formats.c @@ -765,6 +765,7 @@ static const coding_info coding_info_list[] = { {coding_PCMFLOAT, "32-bit float PCM"}, {coding_PCM24LE, "24-bit Little Endian PCM"}, {coding_PCM24BE, "24-bit Big Endian PCM"}, + {coding_PCM32LE, "32-bit Little Endian PCM"}, {coding_CRI_ADX, "CRI ADX 4-bit ADPCM"}, {coding_CRI_ADX_fixed, "CRI ADX 4-bit ADPCM (fixed coefficients)"}, diff --git a/src/meta/riff.c b/src/meta/riff.c index 2e5a73fde..e349056a8 100644 --- a/src/meta/riff.c +++ b/src/meta/riff.c @@ -146,6 +146,9 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk case 0x0001: /* PCM */ switch (fmt->bps) { + case 32: + fmt->coding_type = coding_PCM32LE; + break; case 24: /* Omori (PC) */ fmt->coding_type = coding_PCM24LE; break; @@ -701,6 +704,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) { /* samples, codec init (after setting coding to ensure proper close on failure) */ switch (fmt.coding_type) { + case coding_PCM32LE: case coding_PCM24LE: case coding_PCM16LE: case coding_PCM8_U: diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 64ded87ea..9e5c053a1 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -26,6 +26,7 @@ typedef enum { coding_PCMFLOAT, /* 32-bit float PCM */ coding_PCM24LE, /* little endian 24-bit PCM */ coding_PCM24BE, /* big endian 24-bit PCM */ + coding_PCM32LE, /* little endian 32-bit PCM */ /* ADPCM */ coding_CRI_ADX, /* CRI ADX */ From 651a66624e835d70335831411b92c861b8976b22 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 19 Aug 2023 23:28:05 +0200 Subject: [PATCH 127/141] Add ADM2 .wem [The Grand Tour Game (PC)] --- src/formats.c | 2 +- src/meta/adm3.c | 169 +++++++++++++++++++++++++++++------------- src/meta/meta.h | 1 + src/vgmstream.c | 1 + src/vgmstream_types.h | 2 +- 5 files changed, 122 insertions(+), 53 deletions(-) diff --git a/src/formats.c b/src/formats.c index 0a3974985..49719912e 100644 --- a/src/formats.c +++ b/src/formats.c @@ -1402,7 +1402,7 @@ static const meta_info meta_info_list[] = { {meta_SSPF, "Konami SSPF header"}, {meta_S3V, "Konami S3V header"}, {meta_ESF, "Eurocom ESF header"}, - {meta_ADM3, "Crankcase ADM3 header"}, + {meta_ADM, "Crankcase ADMx header"}, {meta_TT_AD, "Traveller's Tales AUDIO_DATA header"}, {meta_SNDZ, "Sony SNDZ header"}, {meta_VAB, "Sony VAB header"}, diff --git a/src/meta/adm3.c b/src/meta/adm3.c index f38ed06ba..d38fd5989 100644 --- a/src/meta/adm3.c +++ b/src/meta/adm3.c @@ -5,6 +5,7 @@ typedef struct { int total_subsongs; int target_subsong; + int version; uint32_t stream_offset; uint32_t stream_size; @@ -13,51 +14,70 @@ typedef struct { int sample_rate; int channels; int32_t num_samples; -} adm3_header_t; +} adm_header_t; -static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf); +static int parse_adm(adm_header_t* adm, STREAMFILE* sf); +static VGMSTREAM* init_vgmstream_adm(STREAMFILE* sf, int version); + +/* ADM2 - Crankcase Audio REV plugin file [The Grand Tour Game (PC)] */ +VGMSTREAM* init_vgmstream_adm2(STREAMFILE* sf) { + + /* checks */ + if (!is_id32be(0x00,sf, "ADM2")) + return NULL; + if (!check_extensions(sf, "wem")) + return NULL; + + return init_vgmstream_adm(sf, 2); +} /* ADM3 - Crankcase Audio REV plugin file [Cyberpunk 2077 (PC), MotoGP 21 (PC)] */ VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - adm3_header_t adm3 = {0}; - /* checks */ if (!is_id32be(0x00,sf, "ADM3")) - goto fail; + return NULL; if (!check_extensions(sf, "wem")) - goto fail; + return NULL; - adm3.target_subsong = sf->stream_index; - if (adm3.target_subsong == 0) adm3.target_subsong = 1; + return init_vgmstream_adm(sf, 3); +} - /* ADM3 are files used with the Wwise Crankaudio plugin, that simulate engine noises with +static VGMSTREAM* init_vgmstream_adm(STREAMFILE* sf, int version) { + VGMSTREAM* vgmstream = NULL; + adm_header_t adm = {0}; + + /* ADMx are files used with the Wwise Crankaudio plugin, that simulate engine noises with * base internal samples and some internal RPM config (probably). Actual file seems to * define some combo of samples, this only plays those separate samples. * Decoder is basically Apple's IMA (internally just "ADPCMDecoder") but transforms to float * each sample during decode by multiplying by 0.000030518509 */ - if (!parse_adm3(&adm3, sf)) + adm.target_subsong = sf->stream_index; + if (adm.target_subsong == 0) adm.target_subsong = 1; + + adm.version = version; + + if (!parse_adm(&adm, sf)) goto fail; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(adm3.channels, adm3.loop_flag); + vgmstream = allocate_vgmstream(adm.channels, adm.loop_flag); if (!vgmstream) goto fail; - vgmstream->meta_type = meta_ADM3; - vgmstream->sample_rate = adm3.sample_rate; - vgmstream->num_samples = adm3.num_samples; /* slightly lower than bytes-to-samples */ - vgmstream->num_streams = adm3.total_subsongs; - vgmstream->stream_size = adm3.stream_size; + vgmstream->meta_type = meta_ADM; + vgmstream->sample_rate = adm.sample_rate; + vgmstream->num_samples = adm.num_samples; /* slightly lower than bytes-to-samples */ + vgmstream->num_streams = adm.total_subsongs; + vgmstream->stream_size = adm.stream_size; vgmstream->coding_type = coding_APPLE_IMA4; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x22; - if (!vgmstream_open_stream(vgmstream, sf, adm3.stream_offset)) + if (!vgmstream_open_stream(vgmstream, sf, adm.stream_offset)) goto fail; return vgmstream; @@ -67,11 +87,37 @@ VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf) { } -static int parse_type(adm3_header_t* adm3, STREAMFILE* sf, uint32_t offset) { +static int parse_type(adm_header_t* adm, STREAMFILE* sf, uint32_t offset) { + + /* ADM2 chunks */ + if (is_id32be(offset, sf, "GRN1")) { + /* 0x74: offset to floats? */ + offset = read_u32le(offset + 0x78, sf); /* to SMP1 */ + if (!parse_type(adm, sf, offset)) + goto fail; + } + else if (is_id32be(offset, sf, "SMP1")) { + adm->total_subsongs++; - if (is_id32be(offset, sf, "RMP1")) { + if (adm->target_subsong == adm->total_subsongs) { + /* 0x04 always 0 */ + /* 0x08 version? (0x00030000) */ + adm->channels = read_u16le(offset + 0x0c, sf); + /* 0x0e 0x0001? */ + /* 0x10 header size (0x2c) */ + adm->sample_rate = read_s32le(offset + 0x14, sf); + adm->num_samples = read_s32le(offset + 0x18, sf); + adm->stream_size = read_u32le(offset + 0x1c, sf); + adm->stream_offset = read_u32le(offset + 0x20, sf); + /* rest: null */ + VGM_LOG("so=%x %x\n", adm->stream_size, adm->stream_offset); + } + } + + /* ADM3 chunks */ + else if (is_id32be(offset, sf, "RMP1")) { offset = read_u32le(offset + 0x1c, sf); - if (!parse_type(adm3, sf, offset)) + if (!parse_type(adm, sf, offset)) goto fail; /* 0x24: offset to GRN1 */ } @@ -87,30 +133,30 @@ static int parse_type(adm3_header_t* adm3, STREAMFILE* sf, uint32_t offset) { if (smp2_unk != 1) goto fail; - if (!parse_type(adm3, sf, smp2_offset)) /* SMP2 */ + if (!parse_type(adm, sf, smp2_offset)) /* SMP2 */ goto fail; } } else if (is_id32be(offset, sf, "SMP2")) { - adm3->total_subsongs++; + adm->total_subsongs++; - if (adm3->target_subsong == adm3->total_subsongs) { + if (adm->target_subsong == adm->total_subsongs) { /* 0x04 always 0 */ - /* 0x08 always 0x00040000 */ - adm3->channels = read_u32le(offset + 0x0c, sf); + /* 0x08 version? (0x00040000) */ + adm->channels = read_u32le(offset + 0x0c, sf); /* usually 4, with different sounds*/ /* 0x10 float pitch? */ /* 0x14 int pitch? */ /* 0x18 0x0001? */ - /* 0x1a 0x0030? (header size?) */ - adm3->sample_rate = read_s32le(offset + 0x1c, sf); - adm3->num_samples = read_s32le(offset + 0x20, sf); - adm3->stream_size = read_u32le(offset + 0x24, sf); + /* 0x1a header size (0x30) */ + adm->sample_rate = read_s32le(offset + 0x1c, sf); + adm->num_samples = read_s32le(offset + 0x20, sf); + adm->stream_size = read_u32le(offset + 0x24, sf); /* 0x28 1? */ - adm3->stream_offset = read_u32le(offset + 0x2c, sf); + adm->stream_offset = read_u32le(offset + 0x2c, sf); } } else { - VGM_LOG("ADM3: unknown at %x\n", offset); + VGM_LOG("ADM: unknown at %x\n", offset); goto fail; } @@ -119,31 +165,52 @@ static int parse_type(adm3_header_t* adm3, STREAMFILE* sf, uint32_t offset) { return 0; } -static int parse_adm3(adm3_header_t* adm3, STREAMFILE* sf) { +static int parse_adm(adm_header_t* adm, STREAMFILE* sf) { uint32_t offset; /* 0x04: null */ - /* 0x08: version? */ + /* 0x08: version? (ADM2: 0x00050000, ADM3: 0x00060000) */ /* 0x0c: header size */ /* 0x10: data start */ - /* rest unknown, looks mostly the same between files */ - - /* higher ramp, N samples from low to high */ - offset = read_u32le(0x0FC, sf); - if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */ - if (read_u32le(0x100, sf) != 1) goto fail; - - /* lower ramp, also N samples */ - offset = read_u32le(0x104, sf); - if (!parse_type(adm3, sf, offset)) goto fail; /* RMP1 */ - if (read_u32le(0x108, sf) != 1) goto fail; - - /* idle engine */ - offset = read_u32le(0x10c, sf); - if (!parse_type(adm3, sf, offset)) goto fail; /* SMP2 */ - if (read_u32le(0x110, sf) != 1) goto fail; + /* rest unknown, looks mostly the same between files (some floats and stuff) */ + + switch(adm->version) { + case 2: + /* low to high */ + offset = read_u32le(0x104, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* GRN1 */ + + /* high to low */ + offset = read_u32le(0x108, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* GRN1 */ + + /* idle engine */ + offset = read_u32le(0x10c, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* SMP1 */ + break; + + case 3: + /* higher ramp, N samples from low to high */ + offset = read_u32le(0x0FC, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* RMP1 */ + if (read_u32le(0x100, sf) != 1) goto fail; + + /* lower ramp, also N samples */ + offset = read_u32le(0x104, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* RMP1 */ + if (read_u32le(0x108, sf) != 1) goto fail; + + /* idle engine */ + offset = read_u32le(0x10c, sf); + if (!parse_type(adm, sf, offset)) goto fail; /* SMP2 */ + if (read_u32le(0x110, sf) != 1) goto fail; + break; + + default: + goto fail; + } - if (adm3->target_subsong < 0 || adm3->target_subsong > adm3->total_subsongs || adm3->total_subsongs < 1) + if (adm->target_subsong < 0 || adm->target_subsong > adm->total_subsongs || adm->total_subsongs < 1) goto fail; return 1; diff --git a/src/meta/meta.h b/src/meta/meta.h index 56ca00f70..61ace4d51 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -953,6 +953,7 @@ VGMSTREAM* init_vgmstream_s3v(STREAMFILE* sf); VGMSTREAM* init_vgmstream_esf(STREAMFILE* sf); +VGMSTREAM* init_vgmstream_adm2(STREAMFILE* sf); VGMSTREAM* init_vgmstream_adm3(STREAMFILE* sf); VGMSTREAM* init_vgmstream_tt_ad(STREAMFILE* sf); diff --git a/src/vgmstream.c b/src/vgmstream.c index 9cc129f0a..208b82220 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -522,6 +522,7 @@ init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_squeakstream, init_vgmstream_squeaksample, init_vgmstream_snds, + init_vgmstream_adm2, /* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */ init_vgmstream_scd_pcm, diff --git a/src/vgmstream_types.h b/src/vgmstream_types.h index 9e5c053a1..73c333bd9 100644 --- a/src/vgmstream_types.h +++ b/src/vgmstream_types.h @@ -691,7 +691,7 @@ typedef enum { meta_SSPF, meta_S3V, meta_ESF, - meta_ADM3, + meta_ADM, meta_TT_AD, meta_SNDZ, meta_VAB, From fbcd503bd7212244cf0223e4ba8bdd6a8048bcdd Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 19 Aug 2023 23:30:25 +0200 Subject: [PATCH 128/141] cleanup: adm3.c to adm.c --- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 2 +- src/meta/{adm3.c => adm.c} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/meta/{adm3.c => adm.c} (100%) diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 9e8b13da6..dfef25a8d 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -337,7 +337,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 726b131d6..bd93d3ea2 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -832,7 +832,7 @@ meta\Source Files - + meta\Source Files diff --git a/src/meta/adm3.c b/src/meta/adm.c similarity index 100% rename from src/meta/adm3.c rename to src/meta/adm.c From 64bc7ac18c3e7f0a9559d2f8aaa0090e39224148 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 19 Aug 2023 23:30:35 +0200 Subject: [PATCH 129/141] doc --- doc/FORMATS.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/FORMATS.md b/doc/FORMATS.md index c583a181d..ab20740b1 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -273,7 +273,7 @@ different internally (encrypted, different versions, etc) and not always can be - RIFX WAVE header (smpl looping) [*RIFX_WAVE_smpl*] - *riff*: `.wav .lwav .xwav .mwv .da .dax .cd .med .snd .adx .adp .xss .xsew .adpcm .adw .wd .(extensionless) .sbv .wvx .str .at3 .rws .aud .at9 .ckd .saf .ima .nsa .pcm .xvag .ogg .logg .p1d .xms .mus .dat .ldat` - *rifx*: `.wav .lwav` - - Codecs: AICA_int PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int + - Codecs: AICA_int PCM32LE PCM24LE PCM16BE PCM16LE PCM8_U MSADPCM IMA PCMFLOAT MS_IMA AICA MPEG_custom XBOX_IMA MS_IMA_3BIT DVI_IMA L5_555 OGG_VORBIS ATRAC9 ATRAC3 MPEG MSADPCM_int - **nwa.c** - VisualArt's NWA header (NWAINFO.INI looping) [*NWA_NWAINFOINI*] - VisualArt's NWA header (Gameexe.ini looping) [*NWA_GAMEEXEINI*] @@ -1735,8 +1735,9 @@ different internally (encrypted, different versions, etc) and not always can be - Eurocom ESF header [*ESF*] - *esf*: `.esf` - Codecs: DVI_IMA PCM8_U PCM16LE -- **adm3.c** - - Crankcase ADM3 header [*ADM3*] +- **adm.c** + - Crankcase ADMx header [*ADM*] + - *adm2*: `.wem` - *adm3*: `.wem` - Codecs: APPLE_IMA4 - **tt_ad.c** From 046918589a55f62e251fc91c05e088fdd9503f59 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 19 Aug 2023 23:31:40 +0200 Subject: [PATCH 130/141] Add .ogg loops [Tsuki ni Yorisou Otome no Sahou (PC)] --- src/meta/ogg_vorbis.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/meta/ogg_vorbis.c b/src/meta/ogg_vorbis.c index d9e242895..e1b84c02d 100644 --- a/src/meta/ogg_vorbis.c +++ b/src/meta/ogg_vorbis.c @@ -614,6 +614,7 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start, const char* comment = NULL; while (ogg_vorbis_get_comment(data, &comment)) { + ;VGM_LOG("OGG: user_comment=%s\n", comment); if (strstr(comment,"loop_start=") == comment || /* Phantasy Star Online: Blue Burst (PC) (no loop_end pair) */ strstr(comment,"LOOP_START=") == comment || /* Phantasy Star Online: Blue Burst (PC), common */ @@ -702,18 +703,26 @@ static VGMSTREAM* _init_vgmstream_ogg_vorbis_config(STREAMFILE* sf, off_t start, force_seek = 1; } + else if (strstr(comment,"COMMENT=*loopsample,") == comment) { /* Tsuki ni Yorisou Otome no Sahou (PC) */ + int unk0; // always 0 (delay?) + int unk1; // always -1 (loop flag? but non-looped files have no comment) + int m = sscanf(comment,"COMMENT=*loopsample,%d,%d,%d,%d", &unk0, &loop_start, &loop_end, &unk1); + if (m == 4) { + loop_flag = 1; + loop_end_found = 1; + } + } + /* Hatsune Miku Project DIVA games, though only 'Arcade Future Tone' has >4ch files * ENCODER tag is common but ogg_vorbis_encode looks unique enough * (arcade ends with "2010-11-26" while consoles have "2011-02-07" */ - if (strstr(comment, "ENCODER=ogg_vorbis_encode/") == comment) { + else if (strstr(comment, "ENCODER=ogg_vorbis_encode/") == comment) { disable_reordering = 1; } - if (strstr(comment, "TITLE=") == comment) { + else if (strstr(comment, "TITLE=") == comment) { strncpy(name, comment + 6, sizeof(name) - 1); } - - ;VGM_LOG("OGG: user_comment=%s\n", comment); } } From a7dab77b7703c6a78175b3b6d933e7d8bef66a65 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 19 Aug 2023 23:35:28 +0200 Subject: [PATCH 131/141] Fix foobar .txtp to .ogg issues in rare cases --- fb2k/foo_vgmstream.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fb2k/foo_vgmstream.cpp b/fb2k/foo_vgmstream.cpp index 928e483f1..2f19c3409 100644 --- a/fb2k/foo_vgmstream.cpp +++ b/fb2k/foo_vgmstream.cpp @@ -7,6 +7,7 @@ #endif #include #include +#include #include @@ -351,12 +352,22 @@ bool input_vgmstream::g_is_our_path(const char * p_path, const char * p_extensio VGMSTREAM* input_vgmstream::init_vgmstream_foo(t_uint32 p_subsong, const char * const filename, abort_callback & p_abort) { VGMSTREAM* vgmstream = NULL; + /* Workaround for a foobar bug (mainly for complex TXTP): + * When converting to .ogg foobar calls oggenc, that calls setlocale(LC_ALL, "") to use system's locale. + * After that, text parsing using sscanf that expects US locale for "N.N" decimals fails in some locales, + * so reset it here just in case + * (maybe should be done on lib and/or restore original locale but it's not common to change it in C) */ + //const char* original_locale = setlocale(LC_ALL, NULL); + setlocale(LC_ALL, "C"); + STREAMFILE* sf = open_foo_streamfile(filename, &p_abort, &stats); if (sf) { sf->stream_index = p_subsong; vgmstream = init_vgmstream_from_STREAMFILE(sf); close_streamfile(sf); } + + //setlocale(LC_ALL, original_locale); return vgmstream; } From 474c15723a2eff245238713aa7938f8b00972501 Mon Sep 17 00:00:00 2001 From: NicknineTheEagle Date: Tue, 22 Aug 2023 14:58:43 +0300 Subject: [PATCH 132/141] 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 58e0de211..c7ddc43e1 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 133/141] 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 d0cd061ec..03e1723a7 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 134/141] 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 bae933ff0..191515ae5 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; From b2eb542b1be028573683b22d66445d8a36ba11ca Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 13:23:24 +0200 Subject: [PATCH 135/141] Adjust ADX decoding for v04 files --- src/base/decode.c | 2 +- src/coding/adx_decoder.c | 13 ++++++++++--- src/coding/coding.h | 2 +- src/meta/adx.c | 1 + 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/base/decode.c b/src/base/decode.c index 3a9d2a1e8..cd92ca140 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -790,7 +790,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ for (ch = 0; ch < vgmstream->channels; ch++) { decode_adx(&vgmstream->ch[ch], buffer+ch, vgmstream->channels, vgmstream->samples_into_block, samples_to_do, - vgmstream->interleave_block_size, vgmstream->coding_type); + vgmstream->interleave_block_size, vgmstream->coding_type, vgmstream->codec_config); } break; case coding_NGC_DSP: diff --git a/src/coding/adx_decoder.c b/src/coding/adx_decoder.c index 36e2099ec..732cd60d6 100644 --- a/src/coding/adx_decoder.c +++ b/src/coding/adx_decoder.c @@ -1,7 +1,7 @@ #include "coding.h" #include "../util.h" -void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_size, coding_t coding_type) { +void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_size, coding_t coding_type, uint32_t codec_config) { uint8_t frame[0x12] = {0}; off_t frame_offset; int i, frames_in, sample_count = 0; @@ -9,6 +9,7 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int scale, coef1, coef2; int32_t hist1 = stream->adpcm_history1_32; int32_t hist2 = stream->adpcm_history2_32; + int version = codec_config; /* external interleave (fixed size), mono */ @@ -50,7 +51,7 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, break; case coding_CRI_ADX_enc_8: case coding_CRI_ADX_enc_9: - scale = ((scale ^ stream->adx_xor) & 0x1fff) + 1; + scale = ((scale ^ stream->adx_xor) & 0x1fff) + 1; /* this seems to be used even in unencrypted ADX (compatible) */ coef1 = stream->adpcm_coef[0]; coef2 = stream->adpcm_coef[1]; break; @@ -69,7 +70,13 @@ void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, sample = i&1 ? /* high nibble first */ get_low_nibble_signed(nibbles): get_high_nibble_signed(nibbles); - sample = sample * scale + (coef1 * hist1 >> 12) + (coef2 * hist2 >> 12); + + /* Early (v3 ADX only) libs decode slightly differently (quieter?), while later libs (v4 ADX) tweaked it. V4 libs playing v3 files + * seem to behave like V4 though, so it's not detectable but not that common (ex. ports of old games reusing v3 ADX) */ + if (version == 0x0300) + sample = sample * scale + ((coef1 * hist1) >> 12) + ((coef2 * hist2) >> 12); /* V3 lib */ + else + sample = sample * scale + ((coef1 * hist1 + coef2 * hist2) >> 12); /* V4 lib */ sample = clamp16(sample); outbuf[sample_count] = sample; diff --git a/src/coding/coding.h b/src/coding/coding.h index edceec6cc..7425dcf79 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -8,7 +8,7 @@ #include "hca_decoder_clhca.h" /* adx_decoder */ -void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type); +void decode_adx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int32_t frame_bytes, coding_t coding_type, uint32_t codec_config); void adx_next_key(VGMSTREAMCHANNEL* stream); diff --git a/src/meta/adx.c b/src/meta/adx.c index 2e7091044..f972923ef 100644 --- a/src/meta/adx.c +++ b/src/meta/adx.c @@ -183,6 +183,7 @@ VGMSTREAM* init_vgmstream_adx_subkey(STREAMFILE* sf, uint16_t subkey) { vgmstream->loop_start_sample = loop_start_sample; vgmstream->loop_end_sample = loop_end_sample; + vgmstream->codec_config = version; vgmstream->coding_type = coding_type; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = frame_size; From 54350d4851d4d39aec4f61653fe8aa3b12565f62 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 13:23:40 +0200 Subject: [PATCH 136/141] Add .xai XA [Quake II (PS1)] --- src/formats.c | 1 + src/meta/xa.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/formats.c b/src/formats.c index 49719912e..533b834e4 100644 --- a/src/formats.c +++ b/src/formats.c @@ -649,6 +649,7 @@ static const char* extension_list[] = { "xa", "xa2", "xa30", + "xai", "xag", //txth/reserved [Tamsoft's PS2 games] "xau", "xav", diff --git a/src/meta/xa.c b/src/meta/xa.c index 3bd7745e4..6200a5c4a 100644 --- a/src/meta/xa.c +++ b/src/meta/xa.c @@ -39,8 +39,9 @@ VGMSTREAM* init_vgmstream_xa(STREAMFILE* sf) { * .pxa: Mortal Kombat 4 (PS1) * .grn: Micro Machines (CDi) * .an2: Croc (PS1) movies + * .xai: Quake II (PS1) * (extensionless): bigfiles [Castlevania: Symphony of the Night (PS1)] */ - if (!check_extensions(sf,"xa,str,pxa,grn,an2,")) + if (!check_extensions(sf,"xa,str,pxa,grn,an2,,xai")) goto fail; /* Proper XA comes in raw (BIN 2352 mode2/form2) CD sectors, that contain XA subheaders. From 094fe8f97402ec469b2b38b08e32c9b8ebf4de7d Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 13:24:05 +0200 Subject: [PATCH 137/141] cleanup: restructure bnk_sony parsing --- src/meta/bnk_sony.c | 1437 +++++++++++++++++++++++-------------------- 1 file changed, 763 insertions(+), 674 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index 3016b985f..bed7e9b3d 100644 --- a/src/meta/bnk_sony.c +++ b/src/meta/bnk_sony.c @@ -3,682 +3,87 @@ #include "../coding/coding.h" #include "../util/endianness.h" -typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec; -uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t note, int16_t fine); +typedef enum { NONE, PSX, PCM16, ATRAC9, HEVAG } bnk_codec; -/* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */ -VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { - VGMSTREAM* vgmstream = NULL; - char bank_name[STREAM_NAME_SIZE] /*[8]*/, stream_name[STREAM_NAME_SIZE] /*[16]*/; - uint32_t start_offset, stream_offset, bank_name_offset = 0, stream_name_offset = 0; - uint32_t stream_size, interleave = 0; - int channels = 0, loop_flag, sample_rate, big_endian; - int32_t loop_start = 0, loop_end = 0; - uint16_t center_note, center_fine, flags, pitch; - uint32_t atrac9_info = 0; - - int total_subsongs, target_subsong = sf->stream_index; - read_u16_t read_u16; - read_u32_t read_u32; - read_f32_t read_f32; +typedef struct { bnk_codec codec; + int big_endian; + /* bank related (internal)*/ + int sblk_version; + uint32_t sblk_offset; + uint32_t data_offset; + uint32_t data_size; - /* bnk/SCREAM tool version */ - if (read_u32be(0x00,sf) == 0x03) { /* PS3 */ - read_u32 = read_u32be; - read_u16 = read_u16be; - read_f32 = read_f32be; - big_endian = 1; - } - else if (read_u32le(0x00,sf) == 0x03) { /* PS2/PSP/Vita/PS4 */ - read_u32 = read_u32le; - read_u16 = read_u16le; - read_f32 = read_f32le; - big_endian = 0; - } - else { - return NULL; - } - - /* checks */ - if (!check_extensions(sf, "bnk")) - return NULL; - - uint32_t sblk_offset, data_offset, data_size; - int parts, sblk_version; - - parts = read_u32(0x04,sf); - if (parts < 2 || parts > 3) - return NULL; - /* in theory a bank can contain multiple blocks */ - - /* section sizes don't include padding (sometimes aligned to 0x10/0x800) */ - sblk_offset = read_u32(0x08,sf); - //sblk_size = read_u32(0x0c,sf); - data_offset = read_u32(0x10,sf); - data_size = read_u32(0x14,sf); - - /* ZLSD small footer, rare in earlier versions and more common later [Yakuza 6's Puyo Puyo (PS4)] */ - //if (sblk_offset >= 0x20) { - // zlsd_offset = read_u32(0x18,sf); - // zlsd_size = read_u32(0x1c,sf); - //} - - if (sblk_offset > 0x20) - return NULL; - - /* SE banks, also used for music. Most table fields seems reserved/defaults and - * don't change much between subsongs or files, so they aren't described in detail. - * Entry sizes are variable (usually flag + extra size xN) so table offsets are needed. */ - - - /* SBlk part: parse header */ - if (read_u32(sblk_offset+0x00,sf) != get_id32be("klBS")) /* SBlk = SFX block */ - return NULL; - sblk_version = read_u32(sblk_offset+0x04,sf); - /* 0x08: flags? (sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4, 0x05=PS5) - * - 04: non-fixed bank? - * - 100: has names - * - 200: has user data */ - /* version < v0x1a: - * - 0x0c: block id - * - 0x10: block number - * - 0x11: padding - * version >= v0x1a: - * - 0x0c: hash (0x10) - * - 0x1c: filename (0x100?) */ - //;VGM_LOG("BNK: sblk_offset=%lx, data_offset=%lx, sblk_version %x\n", sblk_offset, data_offset, sblk_version); - - { - int i; - bool is_negative; - uint32_t table1_offset, table2_offset, table3_offset, table4_offset; - uint32_t section_entries, material_entries, stream_entries; - uint32_t table1_entry_size; - uint32_t table1_suboffset, table2_suboffset; - uint32_t table2_entry_offset = 0, table3_entry_offset = 0; - int table4_entry_id = -1; - uint32_t table4_entry_idx, table4_entries_offset, table4_names_offset; - uint32_t entry_offset, entry_count; - - - switch(sblk_version) { - case 0x01: /* Ratchet & Clank (PS2) */ - section_entries = read_u16(sblk_offset+0x16,sf); /* entry size: ~0x0c */ - material_entries = read_u16(sblk_offset+0x18,sf); /* entry size: ~0x28 */ - stream_entries = read_u16(sblk_offset+0x1a,sf); /* entry size: none (count) */ - table1_offset = sblk_offset + read_u32(sblk_offset+0x1c,sf); - table2_offset = sblk_offset + read_u32(sblk_offset+0x20,sf); - table3_offset = table2_offset; /* mixed table in this version */ - table4_offset = 0; /* not included */ - - table1_entry_size = 0; /* not used */ - table1_suboffset = 0; - table2_suboffset = 0; - break; - - case 0x03: /* Yu-Gi-Oh! GX - The Beginning of Destiny (PS2) */ - case 0x04: /* Test banks */ - case 0x05: /* Ratchet & Clank (PS3) */ - case 0x08: /* Playstation Home Arcade (Vita) */ - case 0x09: /* Puyo Puyo Tetris (PS4) */ - section_entries = read_u16(sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds) */ - material_entries = read_u16(sblk_offset+0x18,sf); /* entry size: ~0x08 (NumGrains) */ - stream_entries = read_u16(sblk_offset+0x1a,sf); /* entry size: ~0x18 + variable (NumWaveforms) */ - table1_offset = sblk_offset + read_u32(sblk_offset+0x1c,sf); /* sound offset */ - table2_offset = sblk_offset + read_u32(sblk_offset+0x20,sf); /* grain offset */ - /* 0x24: VAG address? */ - /* 0x28: data size */ - /* 0x2c: RAM size */ - /* 0x30: next block offset */ - table3_offset = sblk_offset + read_u32(sblk_offset+0x34,sf); /* grain data? */ - table4_offset = sblk_offset + read_u32(sblk_offset+0x38,sf); /* block names */ - /* 0x3c: SFXUD? */ - - table1_entry_size = 0x0c; - table1_suboffset = 0x08; - table2_suboffset = 0x00; - break; - - case 0x0d: /* Polara (Vita), Crypt of the Necrodancer (Vita) */ - case 0x0e: /* Yakuza 6's Puyo Puyo (PS4) */ - case 0x0f: /* Ikaruga (PS4) */ - case 0x10: /* Ginga Force (PS4) */ - table1_offset = sblk_offset + read_u32(sblk_offset+0x18,sf); - table2_offset = sblk_offset + read_u32(sblk_offset+0x1c,sf); - table3_offset = sblk_offset + read_u32(sblk_offset+0x2c,sf); - table4_offset = sblk_offset + read_u32(sblk_offset+0x30,sf); - section_entries = read_u16(sblk_offset+0x38,sf); /* entry size: ~0x24 */ - material_entries = read_u16(sblk_offset+0x3a,sf); /* entry size: ~0x08 */ - stream_entries = read_u16(sblk_offset+0x3c,sf); /* entry size: ~0x5c + variable */ - - table1_entry_size = 0x24; - table1_suboffset = 0x0c; - table2_suboffset = 0x00; - break; - - case 0x1a: /* Demon's Souls (PS5) */ - case 0x23: /* The Last of Us (PC) */ - - default: - vgm_logi("BNK: unknown version %x (report)\n", sblk_version); - goto fail; - } - - //;VGM_LOG("BNK: table offsets=%x, %x, %x, %x\n", table1_offset,table2_offset,table3_offset,table4_offset); - //;VGM_LOG("BNK: table entries=%i, %i, %i\n", section_entries,material_entries,stream_entries); - - - /* table defs: - * - table1: sections, point to some materials (may be less than streams/materials) - * (a "sound" that has N grains, and is triggered by games like a cue) - * - table2: materials, point to all sounds or others subtypes (may be more than sounds) - * (a "grain" that does actions like play or changes volume) - * - table3: sounds, point to streams (multiple sounds can repeat stream) - * (a "waveform" being the actual stream) - * - table4: names define section names (not all sounds may have a name) - * - * approximate table parsing - * - check materials and skip non-sounds to get table3 offsets (since table3 entry size isn't always constant) - * - get stream offsets - * - find if one section points to the selected material, and get section name = stream name */ - - /* parse materials */ - total_subsongs = 0; - if (target_subsong == 0) target_subsong = 1; - - switch(sblk_version) { - case 0x01: - /* table2/3 has size 0x28 entries, seemingly: - * 0x00: subtype(01=sound) - * 0x08: same as other versions (pitch, flags, offset...) - * rest: padding - * 0x18: stream offset - * there is no stream size like in v0x03 - */ - - for (i = 0; i < material_entries; i++) { - uint32_t table2_type = read_u32(table2_offset + (i*0x28) + 0x00, sf); - - if (table2_type != 0x01) - continue; - - total_subsongs++; - if (total_subsongs == target_subsong) { - table2_entry_offset = 0; - table3_entry_offset = (i*0x28) + 0x08; - /* continue to count all subsongs */ - } - - } - - break; - - default: - for (i = 0; i < material_entries; i++) { - uint32_t table2_value, table2_subinfo, table2_subtype; - - table2_value = read_u32(table2_offset+(i*0x08)+table2_suboffset+0x00,sf); - table2_subinfo = (table2_value >> 0) & 0xFFFF; - table2_subtype = (table2_value >> 16) & 0xFFFF; - if (table2_subtype != 0x0100) - continue; /* not sounds (ex. 1: waveform, 42: silence, 25: random, etc) */ - - total_subsongs++; - if (total_subsongs == target_subsong) { - table2_entry_offset = (i*0x08); - table3_entry_offset = table2_subinfo; - /* continue to count all subsongs */ - } - } - - break; - } - - - //;VGM_LOG("BNK: subsongs %i, table2_entry=%x, table3_entry=%x\n", total_subsongs,table2_entry_offset,table3_entry_offset); - - if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail; - /* this means some subsongs repeat streams, that can happen in some sfx banks, whatevs */ - if (total_subsongs != stream_entries) { - VGM_LOG("BNK: subsongs %i vs table3 %i don't match (repeated streams?)\n", total_subsongs, stream_entries); - /* TODO: find dupes? */ - } - - //;VGM_LOG("BNK: header entry at %lx\n", table3_offset+table3_entry_offset); - - /* parse sounds */ - switch(sblk_version) { - case 0x01: - case 0x03: - case 0x04: - case 0x05: - case 0x08: - case 0x09: - /* "tone" */ - /* 0x00: priority */ - /* 0x01: volume */ - center_note = read_u8 (table3_offset+table3_entry_offset+0x02,sf); - center_fine = read_u8 (table3_offset+table3_entry_offset+0x03,sf); - /* 0x04: pan */ - /* 0x06: map low */ - /* 0x07: map high */ - /* 0x08: pitch bend low */ - /* 0x09: pitch bend high */ - /* 0x0a: ADSR1 */ - /* 0x0c: ADSR2 */ - flags = read_u16(table3_offset+table3_entry_offset+0x0e,sf); - stream_offset = read_u32(table3_offset+table3_entry_offset+0x10,sf); - stream_size = read_u32(table3_offset+table3_entry_offset+0x14,sf); - - /* if it isn't, then it's treated as 44100 base? (PS1?) */ - is_negative = center_note >> 7; /* center_note & 0x80; */ - - if (is_negative) - center_note = 0x100 - center_note; - - /* note/fine seems to always be set to 0x3C/0x00 */ - pitch = ps_note_to_pitch(center_note, center_fine, 0x3C, 0x00); - - if (pitch > 0x4000) - pitch = 0x4000; /* 192000 Hz max */ - - if (!is_negative) /* PS1 mode? */ - pitch = (pitch * 44100) / 48000; - - sample_rate = (pitch * 48000) / 0x1000; - - /* waves can set base sample rate (48/44/22/11/8khz) + pitch in semitones, then converted to center+fine - * 48000 + pitch 0.00 > center=0xc4, fine=0x00 - * 48000 + pitch 0.10 > center=0xc4, fine=0x0c - * 48000 + pitch 0.50 > center=0xc4, fine=0x3f - * 48000 + pitch 0.99 > center=0xc4, fine=0x7d - * 48000 + pitch 1.00 > center=0xc5, fine=0x00 - * 48000 + pitch 12.00 > center=0xd0, fine=0x00 - * 48000 + pitch 24.00 > center=0xdc, fine=0x00 - * 48000 + pitch 56.00 > center=0xfc, fine=0x00 - * 48000 + pitch 68.00 > center=0x08, fine=0x00 > ? - * 48000 + pitch -12.00 > center=0xb8, fine=0x00 - * 48000 + pitch -0.10 > center=0xc3, fine=0x72 - * 48000 + pitch -0.001 > not allowed - * 8000 + pitch 1.00 > center=0xa4, fine=0x7c - * 8000 + pitch -12.00 > center=0x98, fine=0x7c - * 8000 + pitch -48.00 > center=0x74, fine=0x7c - */ - break; - - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - flags = read_u8 (table3_offset+table3_entry_offset+0x12,sf); - stream_offset = read_u32(table3_offset+table3_entry_offset+0x44,sf); - stream_size = read_u32(table3_offset+table3_entry_offset+0x48,sf); - sample_rate = (int)read_f32(table3_offset+table3_entry_offset+0x4c,sf); - break; - - default: - VGM_LOG("BNK: missing version\n"); - goto fail; - } - - //;VGM_LOG("BNK: stream at %lx + %x\n", stream_offset, stream_size); - - /* parse names */ - /* table4 can be nonexistent */ - if (table4_offset > sblk_offset) { - switch (sblk_version) { - case 0x03: - for (i = 0; i < section_entries; i++) { - entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); - entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); - - /* is table2_entry_offset in the range of the expected section */ - if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { - table4_entry_id = i; - break; - } - } - - /* table4: - * 0x00: bank name (optional) - * 0x08: name section offset - * 0x0C-0x14: 3 null pointers (reserved?) - * 0x18-0x58: 32 name chunk offset indices - */ - - /* Name chunks are organised as - * (name[0] + name[4] + name[8] + name[12]) & 0x1F; - * and using that as the index for the chunk offsets - * name_sect_offset + (chunk_idx[result] * 0x14); - */ - if (read_u8(table4_offset, sf)) - bank_name_offset = table4_offset; - - table4_entries_offset = table4_offset + 0x18; - table4_names_offset = table4_offset + read_u32(table4_offset + 0x08, sf); - - for (i = 0; i < 32; i++) { - table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf); - stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14); - /* searches the chunk until it finds the target name/index, or breaks at empty name */ - while (read_u8(stream_name_offset, sf)) { - /* in case it goes somewhere out of bounds unexpectedly */ - if (((read_u8(stream_name_offset + 0x00, sf) + read_u8(stream_name_offset + 0x04, sf) + - read_u8(stream_name_offset + 0x08, sf) + read_u8(stream_name_offset + 0x0C, sf)) & 0x1F) != i) - goto fail; - if (read_u16(stream_name_offset + 0x10, sf) == table4_entry_id) - goto loop_break; /* to break out of the for+while loop simultaneously */ - //break; - stream_name_offset += 0x14; - } - } - //goto fail; /* didn't find any valid index? */ - stream_name_offset = 0; - loop_break: - break; - - case 0x04: - case 0x05: - /* a mix of v3 table1 parsing + v8-v16 table4 parsing */ - for (i = 0; i < section_entries; i++) { - entry_offset = read_u32(table1_offset + (i * table1_entry_size) + 0x08, sf); - entry_count = read_u8(table1_offset + (i * table1_entry_size) + 0x04, sf); - - if (table2_entry_offset >= entry_offset && table2_entry_offset < entry_offset + (entry_count * 0x08)) { - table4_entry_id = i; - break; - } - } - - /* table4: - * 0x00: bank name (optional) - * 0x08: name entries offset - * 0x0C: name section offset - * - * name entries offset: - * 0x00: name offset in name section - * 0x04: name hash(?) - * 0x08: ? (2x int16) - * 0x0C: section index (int16) - */ - if (read_u8(table4_offset, sf)) - bank_name_offset = table4_offset; - - table4_entries_offset = table4_offset + read_u32(table4_offset + 0x08, sf); - table4_names_offset = table4_offset + read_u32(table4_offset + 0x0C, sf); - - for (i = 0; i < section_entries; i++) { - if (read_u16(table4_entries_offset + (i * 0x10) + 0x0C, sf) == table4_entry_id) { - stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10), sf); - break; - } - } - break; - - case 0x08: - case 0x09: - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - /* find if this sound has an assigned name in table1 */ - for (i = 0; i < section_entries; i++) { - entry_offset = read_u16(table1_offset + (i * table1_entry_size) + table1_suboffset + 0x00, sf); - - /* rarely (ex. Polara sfx) one name applies to multiple materials, - * from current entry_offset to next entry_offset (section offsets should be in order) */ - if (entry_offset <= table2_entry_offset) { - table4_entry_id = i; - //break; - } - } - - /* table4: */ - /* 0x00: bank name (optional) */ - /* 0x08: header size */ - /* 0x0c: table4 size */ - /* variable: entries */ - /* variable: names (null terminated) */ - if (read_u8(table4_offset, sf)) - bank_name_offset = table4_offset; - - table4_entries_offset = table4_offset + read_u32(table4_offset + 0x08, sf); - table4_names_offset = table4_entries_offset + (0x10 * section_entries); - //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); - - /* get assigned name from table4 names */ - for (i = 0; i < section_entries; i++) { - int entry_id = read_u32(table4_entries_offset + (i * 0x10) + 0x0c, sf); - if (entry_id == table4_entry_id) { - stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10) + 0x00, sf); - break; - } - } - break; - - default: - break; - } - - //;VGM_LOG("BNK: stream_offset=%lx, stream_size=%x, stream_name_offset=%lx\n", stream_offset, stream_size, stream_name_offset); - } - } - - - /* data part: parse extradata before the codec, if needed */ - { - int type, loop_length; - size_t extradata_size = 0, postdata_size = 0; - start_offset = data_offset + stream_offset; - - switch(sblk_version) { - case 0x01: - case 0x03: - case 0x04: - case 0x05: - channels = 1; - - /* early versions don't have PS-ADPCM size, could check next offset but it's all kind of loopy */ - if (sblk_version <= 0x03 && stream_size == 0 && (flags & 0x80) == 0) { - uint32_t offset; - uint32_t max_offset = get_streamfile_size(sf); - - stream_size += 0x10; - for (offset = data_offset + stream_offset + 0x10; offset < max_offset; offset += 0x10) { - - /* beginning frame (if file loops won't have end frame) - * checking the entire 16 byte block, as it is possible - * for just the first 8 bytes to be empty [Bully (PS2)] */ - if (read_u32be(offset + 0x00, sf) == 0x00000000 && read_u32be(offset + 0x04, sf) == 0x00000000 && - read_u32be(offset + 0x08, sf) == 0x00000000 && read_u32be(offset + 0x0C, sf) == 0x00000000) - break; - - stream_size += 0x10; - - /* end frame */ - if (read_u32be(offset + 0x00, sf) == 0x00077777 && read_u32be(offset + 0x04, sf) == 0x77777777) - break; - } - - //;VGM_LOG("BNK: stream offset=%lx + %lx, new size=%x\n", data_offset, stream_offset, stream_size); - } - - - /* hack for PS3 files that use dual subsongs as stereo */ - if (total_subsongs == 2 && stream_size * 2 == data_size) { - channels = 2; - stream_size = stream_size * channels; - total_subsongs = 1; - start_offset -= stream_offset; /* also channels may be inverted [Fat Princess (PS3)] */ - } - interleave = stream_size / channels; - - /* PS Home Arcade has other flags? supposedly: - * 01 = reverb - * 02 = vol scale 20 - * 04 = vol scale 50 - * 06 = vol scale 100 - * 08 = noise - * 10 = no dry - * 20 = no steal - * 40 = loop VAG - * 80 = PCM - * 100 = has advanced packets - * 200 = send LFE - * 400 = send center - */ - if ((flags & 0x80) && sblk_version <= 3) { - codec = PCM16; /* rare [Wipeout HD (PS3)]-v3 */ - } - else { - loop_flag = ps_find_loop_offsets(sf, start_offset, stream_size, channels, interleave, &loop_start, &loop_end); - loop_flag = (flags & 0x40); /* only applies to PS-ADPCM flags */ - - codec = PSX; - } - - //postdata_size = 0x10; /* last frame may be garbage */ - break; - - case 0x08: - case 0x09: - type = read_u16(start_offset+0x00,sf); - extradata_size = 0x08 + read_u32(start_offset+0x04,sf); /* 0x14 for AT9 */ + uint32_t table1_offset; /* usually sounds/cues (point to grains) */ + uint32_t table2_offset; /* usually grains/materials (point to waves) */ + uint32_t table3_offset; /* usually waves (point to streams) */ + uint32_t table4_offset; /* usually names */ + uint32_t section_entries; + uint32_t material_entries; + uint32_t stream_entries; + uint32_t table1_suboffset; + uint32_t table2_suboffset; + uint32_t table1_entry_size; + uint32_t table2_entry_offset; + uint32_t table3_entry_offset; - switch(type) { - case 0x00: - channels = 1; - codec = PSX; - interleave = 0x10; - break; - - case 0x01: - channels = 1; - codec = PCM16; - interleave = 0x01; - break; - - - case 0x02: /* ATRAC9 mono */ - case 0x05: /* ATRAC9 stereo */ - if (read_u32(start_offset+0x08,sf) + 0x08 != extradata_size) { /* repeat? */ - VGM_LOG("BNK: unknown subtype\n"); - goto fail; - } - channels = (type == 0x02) ? 1 : 2; - - atrac9_info = read_u32be(start_offset+0x0c,sf); - /* 0x10: null? */ - loop_length = read_u32(start_offset+0x14,sf); - loop_start = read_u32(start_offset+0x18,sf); - loop_end = loop_start + loop_length; /* loop_start is -1 if not set */ - - codec = ATRAC9; - break; - - default: - vgm_logi("BNK: unknown type %x (report)\n", type); - goto fail; - } - break; - - case 0x0d: - case 0x0e: - case 0x0f: - case 0x10: - type = read_u16(start_offset+0x00,sf); - if (read_u32(start_offset+0x04,sf) != 0x01) { /* type? */ - VGM_LOG("BNK: unknown subtype\n"); - goto fail; - } - extradata_size = 0x10 + read_u32(start_offset+0x08,sf); /* 0x80 for AT9, 0x10 for PCM/PS-ADPCM */ - /* 0x0c: null? */ - - switch(type) { - case 0x02: /* ATRAC9 mono */ - case 0x05: /* ATRAC9 stereo */ - if (read_u32(start_offset+0x10,sf) + 0x10 != extradata_size) /* repeat? */ - goto fail; - channels = (type == 0x02) ? 1 : 2; - - atrac9_info = read_u32be(start_offset+0x14,sf); - /* 0x18: null? */ - /* 0x1c: channels? */ - /* 0x20: null? */ - - loop_length = read_u32(start_offset+0x24,sf); - loop_start = read_u32(start_offset+0x28,sf); - loop_end = loop_start + loop_length; /* loop_start is -1 if not set */ - - codec = ATRAC9; - break; - - case 0x01: /* PCM16LE mono? (NekoBuro/Polara sfx) */ - case 0x04: /* PCM16LE stereo? (NekoBuro/Polara sfx) */ - /* 0x10: null? */ - channels = read_u32(start_offset+0x14,sf); - interleave = 0x02; - loop_start = read_u32(start_offset+0x18,sf); - loop_length = read_u32(start_offset+0x1c,sf); - loop_end = loop_start + loop_length; /* loop_start is -1 if not set */ + /* stream related */ + int total_subsongs; + int target_subsong; - codec = PCM16; - break; + int channels; + int loop_flag; + int sample_rate; + int32_t loop_start; + int32_t loop_end; - case 0x00: /* HEVAG (test banks) */ - case 0x03: /* HEVAG (Ikaruga) */ - /* 0x10: null? */ - channels = read_u32(start_offset+0x14,sf); - interleave = 0x10; + uint32_t start_offset; + uint32_t stream_offset; + uint32_t bank_name_offset; + uint32_t stream_name_offset; - loop_start = read_u32(start_offset+0x18,sf); - loop_length = read_u32(start_offset+0x1c,sf); - loop_end = loop_start + loop_length; /* loop_start is -1 if not set */ + uint32_t stream_size; + uint32_t interleave; - codec = HEVAG; - //TODO: in v0x0f right before start_offset is the .vag filename, see if offset can be found - break; + uint16_t stream_flags; + uint32_t atrac9_info; +} bnk_header_t; - default: - vgm_logi("BNK: unknown type %x (report)\n", type); - goto fail; - } - break; +static bool parse_bnk_v3(STREAMFILE* sf, bnk_header_t* h); - default: - vgm_logi("BNK: unknown data version %x (report)\n", sblk_version); - goto fail; - } - start_offset += extradata_size; - stream_size -= extradata_size; - stream_size -= postdata_size; - //;VGM_LOG("BNK: offset=%lx, size=%x\n", start_offset, stream_size); - } +/* .BNK - Sony's SCREAM bank format [The Sly Collection (PS3), Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */ +VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + char bank_name[STREAM_NAME_SIZE] /*[8]*/, stream_name[STREAM_NAME_SIZE] /*[16]*/; + bnk_header_t h = {0}; - loop_flag = (loop_start >= 0) && (loop_end > 0); + /* checks */ + if (!parse_bnk_v3(sf, &h)) + return NULL; + if (!check_extensions(sf, "bnk")) + return NULL; /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channels,loop_flag); + vgmstream = allocate_vgmstream(h.channels, h.loop_flag); if (!vgmstream) goto fail; - vgmstream->sample_rate = sample_rate; - vgmstream->num_streams = total_subsongs; - vgmstream->stream_size = stream_size; + vgmstream->sample_rate = h.sample_rate; + vgmstream->num_streams = h.total_subsongs; + vgmstream->stream_size = h.stream_size; vgmstream->meta_type = meta_BNK_SONY; - switch(codec) { + switch(h.codec) { #ifdef VGM_USE_ATRAC9 case ATRAC9: { atrac9_config cfg = {0}; cfg.channels = vgmstream->channels; - cfg.config_data = atrac9_info; + cfg.config_data = h.atrac9_info; //cfg.encoder_delay = 0x00; //todo vgmstream->codec_data = init_atrac9(&cfg); @@ -686,55 +91,55 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { vgmstream->coding_type = coding_ATRAC9; vgmstream->layout_type = layout_none; - vgmstream->num_samples = atrac9_bytes_to_samples(stream_size, vgmstream->codec_data); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->num_samples = atrac9_bytes_to_samples(h.stream_size, vgmstream->codec_data); + vgmstream->loop_start_sample = h.loop_start; + vgmstream->loop_end_sample = h.loop_end; break; } #endif case PCM16: - vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE; + vgmstream->coding_type = h.big_endian ? coding_PCM16BE : coding_PCM16LE; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h.interleave; - vgmstream->num_samples = pcm_bytes_to_samples(stream_size, vgmstream->channels, 16); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->num_samples = pcm_bytes_to_samples(h.stream_size, vgmstream->channels, 16); + vgmstream->loop_start_sample = h.loop_start; + vgmstream->loop_end_sample = h.loop_end; break; case PSX: vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h.interleave; - vgmstream->num_samples = ps_bytes_to_samples(stream_size,channels); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->num_samples = ps_bytes_to_samples(h.stream_size, h.channels); + vgmstream->loop_start_sample = h.loop_start; + vgmstream->loop_end_sample = h.loop_end; break; case HEVAG: vgmstream->coding_type = coding_HEVAG; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = interleave; + vgmstream->interleave_block_size = h.interleave; - vgmstream->num_samples = ps_bytes_to_samples(stream_size,channels); - vgmstream->loop_start_sample = loop_start; - vgmstream->loop_end_sample = loop_end; + vgmstream->num_samples = ps_bytes_to_samples(h.stream_size, h.channels); + vgmstream->loop_start_sample = h.loop_start; + vgmstream->loop_end_sample = h.loop_end; break; default: goto fail; } - if (!bank_name_offset && stream_name_offset) - read_string(vgmstream->stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); - else if (bank_name_offset && stream_name_offset) { - read_string(bank_name, STREAM_NAME_SIZE, bank_name_offset, sf); - read_string(stream_name, STREAM_NAME_SIZE, stream_name_offset, sf); + if (!h.bank_name_offset && h.stream_name_offset) + read_string(vgmstream->stream_name, STREAM_NAME_SIZE, h.stream_name_offset, sf); + else if (h.bank_name_offset && h.stream_name_offset) { + read_string(bank_name, STREAM_NAME_SIZE, h.bank_name_offset, sf); + read_string(stream_name, STREAM_NAME_SIZE, h.stream_name_offset, sf); snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", bank_name, stream_name); } - if (!vgmstream_open_stream(vgmstream, sf, start_offset)) + if (!vgmstream_open_stream(vgmstream, sf, h.start_offset)) goto fail; return vgmstream; fail: @@ -763,12 +168,12 @@ VGMSTREAM * init_vgmstream_bnk_sony_v2(STREAMFILE *sf) { } #endif -uint16_t note_pitch_table[12] = { +static const uint16_t note_pitch_table[12] = { 0x8000, 0x879C, 0x8FAC, 0x9837, 0xA145, 0xAADC, 0xB504, 0xBFC8, 0xCB2F, 0xD744, 0xE411, 0xF1A1 }; -uint16_t fine_pitch_table[128] = { +static const uint16_t fine_pitch_table[128] = { 0x8000, 0x800E, 0x801D, 0x802C, 0x803B, 0x804A, 0x8058, 0x8067, 0x8076, 0x8085, 0x8094, 0x80A3, 0x80B1, 0x80C0, 0x80CF, 0x80DE, 0x80ED, 0x80FC, 0x810B, 0x811A, 0x8129, 0x8138, 0x8146, 0x8155, @@ -787,7 +192,7 @@ uint16_t fine_pitch_table[128] = { 0x871F, 0x872E, 0x873E, 0x874E, 0x875D, 0x876D, 0x877D, 0x878C }; -uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t note, int16_t fine) { +static uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t note, int16_t fine) { /* Derived from OpenGOAL, Copyright (c) 2020-2022 OpenGOAL Team, ISC License * * Permission to use, copy, modify, and/or distribute this software for any @@ -850,3 +255,687 @@ uint16_t ps_note_to_pitch(uint16_t center_note, uint16_t center_fine, uint16_t n return pitch; } + + +/* base part: read section info */ +static bool process_tables(STREAMFILE* sf, bnk_header_t* h) { + read_u16_t read_u16 = h->big_endian ? read_u16be : read_u16le; + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + + /* - table1: sections, point to some materials (may be less than streams/materials) + * (a "sound" that has N grains, and is triggered by games like a cue) + * - table2: materials, point to all sounds or others subtypes (may be more than sounds) + * (a "grain" that does actions like play or changes volume) + * - table3: sounds, point to streams (multiple sounds can repeat stream) + * (a "waveform" being the actual stream) + * - table4: names define section names (not all sounds may have a name) + * + * approximate table parsing + * - check materials and skip non-sounds to get table3 offsets (since table3 entry size isn't always constant) + * - get stream offsets + * - find if one section points to the selected material, and get section name = stream name */ + + switch(h->sblk_version) { + case 0x01: /* Ratchet & Clank (PS2) */ + h->section_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c */ + h->material_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x28 */ + h->stream_entries = read_u16(h->sblk_offset+0x1a,sf); /* entry size: none (count) */ + h->table1_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); + h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x20,sf); + h->table3_offset = h->table2_offset; /* mixed table in this version */ + h->table4_offset = 0; /* not included */ + + h->table1_entry_size = 0; /* not used */ + h->table1_suboffset = 0; + h->table2_suboffset = 0; + break; + + case 0x03: /* Yu-Gi-Oh! GX - The Beginning of Destiny (PS2) */ + case 0x04: /* Test banks */ + case 0x05: /* Ratchet & Clank (PS3) */ + case 0x08: /* Playstation Home Arcade (Vita) */ + case 0x09: /* Puyo Puyo Tetris (PS4) */ + h->section_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds) */ + h->material_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x08 (NumGrains) */ + h->stream_entries = read_u16(h->sblk_offset+0x1a,sf); /* entry size: ~0x18 + variable (NumWaveforms) */ + h->table1_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); /* sound offset */ + h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x20,sf); /* grain offset */ + /* 0x24: VAG address? */ + /* 0x28: data size */ + /* 0x2c: RAM size */ + /* 0x30: next block offset */ + h->table3_offset = h->sblk_offset + read_u32(h->sblk_offset+0x34,sf); /* grain data? */ + h->table4_offset = h->sblk_offset + read_u32(h->sblk_offset+0x38,sf); /* block names */ + /* 0x3c: SFXUD? */ + + h->table1_entry_size = 0x0c; + h->table1_suboffset = 0x08; + h->table2_suboffset = 0x00; + break; + + case 0x0d: /* Polara (Vita), Crypt of the Necrodancer (Vita) */ + case 0x0e: /* Yakuza 6's Puyo Puyo (PS4) */ + case 0x0f: /* Ikaruga (PS4) */ + case 0x10: /* Ginga Force (PS4) */ + h->table1_offset = h->sblk_offset + read_u32(h->sblk_offset+0x18,sf); + h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); + h->table3_offset = h->sblk_offset + read_u32(h->sblk_offset+0x2c,sf); + h->table4_offset = h->sblk_offset + read_u32(h->sblk_offset+0x30,sf); + h->section_entries = read_u16(h->sblk_offset+0x38,sf); /* entry size: ~0x24 */ + h->material_entries = read_u16(h->sblk_offset+0x3a,sf); /* entry size: ~0x08 */ + h->stream_entries = read_u16(h->sblk_offset+0x3c,sf); /* entry size: ~0x5c + variable */ + + h->table1_entry_size = 0x24; + h->table1_suboffset = 0x0c; + h->table2_suboffset = 0x00; + break; + + case 0x1a: /* Demon's Souls (PS5) */ + case 0x23: /* The Last of Us (PC) */ + default: + vgm_logi("BNK: unknown version %x (report)\n", h->sblk_version); + goto fail; + } + + //;VGM_LOG("BNK: table offsets=%x, %x, %x, %x\n", h->table1_offset, h->table2_offset, h->table3_offset, h->table4_offset); + //;VGM_LOG("BNK: table entries=%i, %i, %i\n", h->section_entries, h->material_entries, h->stream_entries); + + return true; +fail: + return false; +} + +/* header part: read wave info */ +static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { + read_u16_t read_u16 = h->big_endian ? read_u16be : read_u16le; + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + read_f32_t read_f32 = h->big_endian ? read_f32be : read_f32le; + int i; + uint32_t sndh_offset; + + /* parse materials */ + h->total_subsongs = 0; + h->target_subsong = sf->stream_index; + if (h->target_subsong == 0) h->target_subsong = 1; + + switch(h->sblk_version) { + case 0x01: + /* table2/3 has size 0x28 entries, seemingly: + * 0x00: subtype(01=sound) + * 0x08: same as other versions (pitch, flags, offset...) + * rest: padding + * 0x18: stream offset + * there is no stream size like in v0x03 + */ + + for (i = 0; i < h->material_entries; i++) { + uint32_t table2_type = read_u32(h->table2_offset + (i*0x28) + 0x00, sf); + + if (table2_type != 0x01) + continue; + + h->total_subsongs++; + if (h->total_subsongs == h->target_subsong) { + h->table2_entry_offset = 0; + h->table3_entry_offset = (i*0x28) + 0x08; + /* continue to count all subsongs */ + } + + } + + break; + + default: + for (i = 0; i < h->material_entries; i++) { + uint32_t table2_value, table2_subinfo, table2_subtype; + + table2_value = read_u32(h->table2_offset+(i*0x08) + h->table2_suboffset + 0x00,sf); + table2_subinfo = (table2_value >> 0) & 0xFFFF; + table2_subtype = (table2_value >> 16) & 0xFFFF; + if (table2_subtype != 0x0100) + continue; /* not sounds (ex. 1: waveform, 42: silence, 25: random, etc) */ + + h->total_subsongs++; + if (h->total_subsongs == h->target_subsong) { + h->table2_entry_offset = (i*0x08); + h->table3_entry_offset = table2_subinfo; + /* continue to count all subsongs */ + } + } + + break; + } + + + //;VGM_LOG("BNK: subsongs %i, table2_entry=%x, table3_entry=%x\n", h->total_subsongs, h->table2_entry_offset, h->table3_entry_offset); + if (h->target_subsong < 0 || h->target_subsong > h->total_subsongs || h->total_subsongs < 1) + goto fail; + /* this means some subsongs repeat streams, that can happen in some sfx banks, whatevs */ + if (h->total_subsongs != h->stream_entries) { + VGM_LOG("BNK: subsongs %i vs table3 %i don't match (repeated streams?)\n", h->total_subsongs, h->stream_entries); + /* TODO: find dupes? */ + } + + //;VGM_LOG("BNK: header entry at %lx\n", h->table3_offset + h->table3_entry_offset); + + sndh_offset = h->table3_offset + h->table3_entry_offset; + + /* parse sounds */ + switch(h->sblk_version) { + case 0x01: + case 0x03: + case 0x04: + case 0x05: + case 0x08: + case 0x09: { + uint16_t center_note, center_fine, pitch; + bool is_negative; + + /* "tone" */ + /* 0x00: priority */ + /* 0x01: volume */ + center_note = read_u8 (sndh_offset + 0x02,sf); + center_fine = read_u8 (sndh_offset + 0x03,sf); + /* 0x04: pan */ + /* 0x06: map low */ + /* 0x07: map high */ + /* 0x08: pitch bend low */ + /* 0x09: pitch bend high */ + /* 0x0a: ADSR1 */ + /* 0x0c: ADSR2 */ + h->stream_flags = read_u16(sndh_offset + 0x0e,sf); + h->stream_offset = read_u32(sndh_offset + 0x10,sf); + h->stream_size = read_u32(sndh_offset + 0x14,sf); + + /* if it isn't, then it's treated as 44100 base? (PS1?) */ + is_negative = center_note >> 7; /* center_note & 0x80; */ + + if (is_negative) + center_note = 0x100 - center_note; + + /* note/fine seems to always be set to 0x3C/0x00 */ + pitch = ps_note_to_pitch(center_note, center_fine, 0x3C, 0x00); + + if (pitch > 0x4000) + pitch = 0x4000; /* 192000 Hz max */ + + if (!is_negative) /* PS1 mode? */ + pitch = (pitch * 44100) / 48000; + + h->sample_rate = (pitch * 48000) / 0x1000; + + /* waves can set base sample rate (48/44/22/11/8khz) + pitch in semitones, then converted to center+fine + * 48000 + pitch 0.00 > center=0xc4, fine=0x00 + * 48000 + pitch 0.10 > center=0xc4, fine=0x0c + * 48000 + pitch 0.50 > center=0xc4, fine=0x3f + * 48000 + pitch 0.99 > center=0xc4, fine=0x7d + * 48000 + pitch 1.00 > center=0xc5, fine=0x00 + * 48000 + pitch 12.00 > center=0xd0, fine=0x00 + * 48000 + pitch 24.00 > center=0xdc, fine=0x00 + * 48000 + pitch 56.00 > center=0xfc, fine=0x00 + * 48000 + pitch 68.00 > center=0x08, fine=0x00 > ? + * 48000 + pitch -12.00 > center=0xb8, fine=0x00 + * 48000 + pitch -0.10 > center=0xc3, fine=0x72 + * 48000 + pitch -0.001 > not allowed + * 8000 + pitch 1.00 > center=0xa4, fine=0x7c + * 8000 + pitch -12.00 > center=0x98, fine=0x7c + * 8000 + pitch -48.00 > center=0x74, fine=0x7c + */ + break; + } + + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + h->stream_flags = read_u8 (sndh_offset+0x12,sf); + h->stream_offset = read_u32(sndh_offset+0x44,sf); + h->stream_size = read_u32(sndh_offset+0x48,sf); + h->sample_rate = (int)read_f32(sndh_offset+0x4c,sf); + break; + + default: + VGM_LOG("BNK: missing version\n"); + goto fail; + } + + //;VGM_LOG("BNK: stream at %lx + %x\n", h->stream_offset, h->stream_size); + + return true; +fail: + return false; +} + +/* name part: read names */ +static bool process_names(STREAMFILE* sf, bnk_header_t* h) { + read_u16_t read_u16 = h->big_endian ? read_u16be : read_u16le; + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + + /* table4 can be nonexistent */ + if (h->table4_offset <= h->sblk_offset) + return true; + + int i; + int table4_entry_id = -1; + uint32_t table4_entry_idx, table4_entries_offset, table4_names_offset; + uint32_t entry_offset, entry_count; + + switch (h->sblk_version) { + case 0x03: + for (i = 0; i < h->section_entries; i++) { + entry_offset = read_u32(h->table1_offset + (i * h->table1_entry_size) + 0x08, sf); + entry_count = read_u8(h->table1_offset + (i * h->table1_entry_size) + 0x04, sf); + + /* is table2_entry_offset in the range of the expected section */ + if (h->table2_entry_offset >= entry_offset && h->table2_entry_offset < entry_offset + (entry_count * 0x08)) { + table4_entry_id = i; + break; + } + } + + /* table4: + * 0x00: bank name (optional) + * 0x08: name section offset + * 0x0C-0x14: 3 null pointers (reserved?) + * 0x18-0x58: 32 name chunk offset indices + */ + + /* Name chunks are organised as + * (name[0] + name[4] + name[8] + name[12]) & 0x1F; + * and using that as the index for the chunk offsets + * name_sect_offset + (chunk_idx[result] * 0x14); + */ + if (read_u8(h->table4_offset, sf)) + h->bank_name_offset = h->table4_offset; + + table4_entries_offset = h->table4_offset + 0x18; + table4_names_offset = h->table4_offset + read_u32(h->table4_offset + 0x08, sf); + + for (i = 0; i < 32; i++) { + table4_entry_idx = read_u16(table4_entries_offset + (i * 2), sf); + h->stream_name_offset = table4_names_offset + (table4_entry_idx * 0x14); + /* searches the chunk until it finds the target name/index, or breaks at empty name */ + while (read_u8(h->stream_name_offset, sf)) { + /* in case it goes somewhere out of bounds unexpectedly */ + if (((read_u8(h->stream_name_offset + 0x00, sf) + read_u8(h->stream_name_offset + 0x04, sf) + + read_u8(h->stream_name_offset + 0x08, sf) + read_u8(h->stream_name_offset + 0x0C, sf)) & 0x1F) != i) + goto fail; + if (read_u16(h->stream_name_offset + 0x10, sf) == table4_entry_id) + goto loop_break; /* to break out of the for+while loop simultaneously */ + //break; + h->stream_name_offset += 0x14; + } + } + //goto fail; /* didn't find any valid index? */ + h->stream_name_offset = 0; + loop_break: + break; + + case 0x04: + case 0x05: + /* a mix of v3 table1 parsing + v8-v16 table4 parsing */ + for (i = 0; i < h->section_entries; i++) { + entry_offset = read_u32(h->table1_offset + (i * h->table1_entry_size) + 0x08, sf); + entry_count = read_u8(h->table1_offset + (i * h->table1_entry_size) + 0x04, sf); + + if (h->table2_entry_offset >= entry_offset && h->table2_entry_offset < entry_offset + (entry_count * 0x08)) { + table4_entry_id = i; + break; + } + } + + /* table4: + * 0x00: bank name (optional) + * 0x08: name entries offset + * 0x0C: name section offset + * + * name entries offset: + * 0x00: name offset in name section + * 0x04: name hash(?) + * 0x08: ? (2x int16) + * 0x0C: section index (int16) + */ + if (read_u8(h->table4_offset, sf)) + h->bank_name_offset = h->table4_offset; + + table4_entries_offset = h->table4_offset + read_u32(h->table4_offset + 0x08, sf); + table4_names_offset = h->table4_offset + read_u32(h->table4_offset + 0x0C, sf); + + for (i = 0; i < h->section_entries; i++) { + if (read_u16(table4_entries_offset + (i * 0x10) + 0x0C, sf) == table4_entry_id) { + h->stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10), sf); + break; + } + } + break; + + case 0x08: + case 0x09: + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + /* find if this sound has an assigned name in table1 */ + for (i = 0; i < h->section_entries; i++) { + entry_offset = read_u16(h->table1_offset + (i * h->table1_entry_size) + h->table1_suboffset + 0x00, sf); + + /* rarely (ex. Polara sfx) one name applies to multiple materials, + * from current entry_offset to next entry_offset (section offsets should be in order) */ + if (entry_offset <= h->table2_entry_offset) { + table4_entry_id = i; + //break; + } + } + + /* table4: */ + /* 0x00: bank name (optional) */ + /* 0x08: header size */ + /* 0x0c: table4 size */ + /* variable: entries */ + /* variable: names (null terminated) */ + if (read_u8(h->table4_offset, sf)) + h->bank_name_offset = h->table4_offset; + + table4_entries_offset = h->table4_offset + read_u32(h->table4_offset + 0x08, sf); + table4_names_offset = table4_entries_offset + (0x10 * h->section_entries); + //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); + + /* get assigned name from table4 names */ + for (i = 0; i < h->section_entries; i++) { + int entry_id = read_u32(table4_entries_offset + (i * 0x10) + 0x0c, sf); + if (entry_id == table4_entry_id) { + h->stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10) + 0x00, sf); + break; + } + } + break; + + default: + 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); + + return true; +fail: + return false; +} + +/* data part: parse extradata before the codec */ +static bool process_data(STREAMFILE* sf, bnk_header_t* h) { + read_u16_t read_u16 = h->big_endian ? read_u16be : read_u16le; + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + + int subtype, loop_length; + uint32_t extradata_size = 0, postdata_size = 0; + + h->start_offset = h->data_offset + h->stream_offset; + + switch(h->sblk_version) { + case 0x01: + case 0x03: + case 0x04: + case 0x05: + h->channels = 1; + + /* early versions don't have PS-ADPCM size, could check next offset but it's all kind of loopy */ + if (h->sblk_version <= 0x03 && h->stream_size == 0 && (h->stream_flags & 0x80) == 0) { + uint32_t offset; + uint32_t max_offset = get_streamfile_size(sf); + + h->stream_size += 0x10; + for (offset = h->data_offset + h->stream_offset + 0x10; offset < max_offset; offset += 0x10) { + + /* beginning frame (if file loops won't have end frame) + * checking the entire 16 byte block, as it is possible + * for just the first 8 bytes to be empty [Bully (PS2)] */ + if (read_u32be(offset + 0x00, sf) == 0x00000000 && read_u32be(offset + 0x04, sf) == 0x00000000 && + read_u32be(offset + 0x08, sf) == 0x00000000 && read_u32be(offset + 0x0C, sf) == 0x00000000) + break; + + h->stream_size += 0x10; + + /* end frame */ + if (read_u32be(offset + 0x00, sf) == 0x00077777 && read_u32be(offset + 0x04, sf) == 0x77777777) + break; + } + + //;VGM_LOG("BNK: stream offset=%lx + %lx, new size=%x\n", h->data_offset, stream_offset, stream_size); + } + + + /* hack for PS3 files that use dual subsongs as stereo */ + if (h->total_subsongs == 2 && h->stream_size * 2 == h->data_size) { + h->channels = 2; + h->stream_size = h->stream_size * h->channels; + h->total_subsongs = 1; + h->start_offset -= h->stream_offset; /* also channels may be inverted [Fat Princess (PS3)] */ + } + h->interleave = h->stream_size / h->channels; + + /* PS Home Arcade has other flags? supposedly: + * 01 = reverb + * 02 = vol scale 20 + * 04 = vol scale 50 + * 06 = vol scale 100 + * 08 = noise + * 10 = no dry + * 20 = no steal + * 40 = loop VAG + * 80 = PCM + * 100 = has advanced packets + * 200 = send LFE + * 400 = send center + */ + if ((h->stream_flags & 0x80) && h->sblk_version <= 3) { + h->codec = PCM16; /* rare [Wipeout HD (PS3)]-v3 */ + } + else { + h->loop_flag = ps_find_loop_offsets(sf, h->start_offset, h->stream_size, h->channels, h->interleave, &h->loop_start, &h->loop_end); + h->loop_flag = (h->stream_flags & 0x40); /* only applies to PS-ADPCM flags */ + + h->codec = PSX; + } + + //postdata_size = 0x10; /* last frame may be garbage */ + break; + + 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 */ + + switch(subtype) { + case 0x00: + h->channels = 1; + h->codec = PSX; + h->interleave = 0x10; + break; + + case 0x01: + h->channels = 1; + h->codec = PCM16; + 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; + } + 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 */ + + h->codec = ATRAC9; + break; + + default: + vgm_logi("BNK: unknown subtype %x (report)\n", subtype); + goto fail; + } + break; + + case 0x0d: + case 0x0e: + case 0x0f: + case 0x10: + subtype = read_u16(h->start_offset+0x00,sf); + if (read_u32(h->start_offset+0x04,sf) != 0x01) { /* type? */ + VGM_LOG("BNK: unknown subtype\n"); + goto fail; + } + extradata_size = 0x10 + read_u32(h->start_offset+0x08,sf); /* 0x80 for AT9, 0x10 for PCM/PS-ADPCM */ + /* 0x0c: null? */ + + switch(subtype) { + case 0x02: /* ATRAC9 mono */ + case 0x05: /* ATRAC9 stereo */ + if (read_u32(h->start_offset+0x10,sf) + 0x10 != extradata_size) /* repeat? */ + goto fail; + h->channels = (subtype == 0x02) ? 1 : 2; + + h->atrac9_info = read_u32be(h->start_offset+0x14,sf); + /* 0x18: null? */ + /* 0x1c: channels? */ + /* 0x20: null? */ + + loop_length = read_u32(h->start_offset+0x24,sf); + h->loop_start = read_u32(h->start_offset+0x28,sf); + h->loop_end = h->loop_start + loop_length; /* loop_start is -1 if not set */ + + h->codec = ATRAC9; + break; + + case 0x01: /* PCM16LE mono? (NekoBuro/Polara sfx) */ + case 0x04: /* PCM16LE stereo? (NekoBuro/Polara sfx) */ + /* 0x10: null? */ + h->channels = read_u32(h->start_offset+0x14,sf); + h->interleave = 0x02; + + h->loop_start = read_u32(h->start_offset+0x18,sf); + loop_length = read_u32(h->start_offset+0x1c,sf); + h->loop_end = h->loop_start + loop_length; /* loop_start is -1 if not set */ + + h->codec = PCM16; + break; + + case 0x00: /* HEVAG (test banks) */ + case 0x03: /* HEVAG (Ikaruga) */ + /* 0x10: null? */ + h->channels = read_u32(h->start_offset+0x14,sf); + h->interleave = 0x10; + + h->loop_start = read_u32(h->start_offset+0x18,sf); + loop_length = read_u32(h->start_offset+0x1c,sf); + h->loop_end = h->loop_start + loop_length; /* loop_start is -1 if not set */ + + h->codec = HEVAG; + //TODO: in v0x0f right before start_offset is the .vag filename, see if offset can be found + break; + + default: + vgm_logi("BNK: unknown subtype %x (report)\n", subtype); + goto fail; + } + break; + + default: + vgm_logi("BNK: unknown data version %x (report)\n", h->sblk_version); + goto fail; + } + + h->start_offset += extradata_size; + h->stream_size -= extradata_size; + h->stream_size -= postdata_size; + //;VGM_LOG("BNK: offset=%lx, size=%x\n", h->start_offset, h->stream_size); + + return true; +fail: + return false; +} + + +/* parse SCREAM bnk (usually SFX but also used for music) */ +static bool parse_bnk_v3(STREAMFILE* sf, bnk_header_t* h) { + + /* bnk/SCREAM tool version (v2 is a bit different, not seen v1) */ + if (read_u32be(0x00,sf) == 0x03) { /* PS3 */ + h->big_endian = 1; + } + else if (read_u32le(0x00,sf) == 0x03) { /* PS2/PSP/Vita/PS4 */ + h->big_endian = 0; + } + else { + return false; + } + + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + + int sections = read_u32(0x04,sf); /* SBlk, data, ZLSD */ + if (sections < 2 || sections > 3) + return false; + /* in theory a bank can contain multiple blocks but only those are used */ + + /* section sizes don't include padding (sometimes aligned to 0x10/0x800) */ + h->sblk_offset = read_u32(0x08,sf); + //h->sblk_size = read_u32(0x0c,sf); + h->data_offset = read_u32(0x10,sf); + h->data_size = read_u32(0x14,sf); + /* ZLSD small empty footer, rare in earlier versions and common later [Yakuza 6's Puyo Puyo (PS4)] */ + //if (h->sblk_offset >= 0x20) { + // zlsd_offset = read_u32(0x18,sf); + // zlsd_size = read_u32(0x1c,sf); + //} + + if (h->sblk_offset > 0x20) + return false; + + /* Most table fields seems reserved/defaults and don't change much between subsongs or files, + * so they aren't described in detail. Entry sizes are variable (usually flag + extra size xN) + * so table offsets are needed. */ + + + /* SBlk part: parse header */ + if (read_u32(h->sblk_offset+0x00,sf) != get_id32be("klBS")) /* SBlk = SFX block */ + return false; + h->sblk_version = read_u32(h->sblk_offset+0x04,sf); + /* 0x08: flags? (h->sblk_version>=0x0d?, 0x03=Vita, 0x06=PS4, 0x05=PS5, 0x07=PS5) + * - 04: non-fixed bank? + * - 100: 'has names' + * - 200: 'has user data' */ + /* version < v0x1a: + * - 0x0c: block id + * - 0x10: block number + * - 0x11: padding + * version >= v0x1a: + * - 0x0c: hash (0x10) + * - 0x1c: filename (0x100?) + * version ~= v0x23: + * - 0x0c: null (depends on flags? v1a=0x05, v23=0x07) + * - 0x10: hash (0x10) + * - 0x20: filename (0x100?) + */ + //;VGM_LOG("BNK: h->sblk_offset=%lx, h->data_offset=%lx, h->sblk_version %x\n", h->sblk_offset, h->data_offset, h->sblk_version); + + if (!process_tables(sf, h)) + goto fail; + if (!process_headers(sf, h)) + goto fail; + if (!process_names(sf, h)) + goto fail; + if (!process_data(sf, h)) + goto fail; + + h->loop_flag = (h->loop_start >= 0) && (h->loop_end > 0); + + return true; +fail: + return false; +} From c8bfca47427f4539a095a60a96c445744150bd03 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 17:24:22 +0200 Subject: [PATCH 138/141] Add some .bnk versions [The Last of Us (PC)] --- src/meta/bnk_sony.c | 212 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 178 insertions(+), 34 deletions(-) diff --git a/src/meta/bnk_sony.c b/src/meta/bnk_sony.c index bed7e9b3d..0e10d4795 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, PSX, PCM16, ATRAC9, HEVAG } bnk_codec; +typedef enum { NONE, DUMMY, PSX, PCM16, ATRAC9, HEVAG, RIFF_ATRAC9 } bnk_codec; typedef struct { bnk_codec codec; @@ -14,13 +14,15 @@ typedef struct { uint32_t sblk_offset; uint32_t data_offset; uint32_t data_size; + uint32_t zlsd_offset; + uint32_t zlsd_size; uint32_t table1_offset; /* usually sounds/cues (point to grains) */ uint32_t table2_offset; /* usually grains/materials (point to waves) */ uint32_t table3_offset; /* usually waves (point to streams) */ uint32_t table4_offset; /* usually names */ - uint32_t section_entries; - uint32_t material_entries; + uint32_t sounds_entries; + uint32_t grains_entries; uint32_t stream_entries; uint32_t table1_suboffset; uint32_t table2_suboffset; @@ -36,6 +38,7 @@ typedef struct { int channels; int loop_flag; int sample_rate; + int32_t num_samples; int32_t loop_start; int32_t loop_end; @@ -43,6 +46,7 @@ typedef struct { uint32_t stream_offset; uint32_t bank_name_offset; uint32_t stream_name_offset; + uint32_t stream_name_size; uint32_t stream_size; uint32_t interleave; @@ -77,7 +81,32 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { vgmstream->meta_type = meta_BNK_SONY; + if (!h.stream_name_size) + h.stream_name_size = STREAM_NAME_SIZE; + + if (!h.bank_name_offset && h.stream_name_offset) { + read_string(vgmstream->stream_name, h.stream_name_size, h.stream_name_offset, 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); + } + + switch(h.codec) { + case DUMMY: { + VGMSTREAM* temp_vs = NULL; + + temp_vs = init_vgmstream_silence_container(h.total_subsongs); + if (!temp_vs) goto fail; + + temp_vs->meta_type = vgmstream->meta_type; + + close_vgmstream(vgmstream); + return temp_vs; + } + #ifdef VGM_USE_ATRAC9 case ATRAC9: { atrac9_config cfg = {0}; @@ -95,7 +124,28 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { vgmstream->loop_start_sample = h.loop_start; vgmstream->loop_end_sample = h.loop_end; break; - } + } + + case RIFF_ATRAC9: { + VGMSTREAM* temp_vs = NULL; + STREAMFILE* temp_sf = NULL; + + + temp_sf = setup_subfile_streamfile(sf, h.start_offset, h.stream_size, "at9"); + if (!temp_sf) goto fail; + + temp_vs = init_vgmstream_riff(temp_sf); + close_streamfile(temp_sf); + if (!temp_vs) goto fail; + + temp_vs->num_streams = vgmstream->num_streams; + temp_vs->stream_size = vgmstream->stream_size; + temp_vs->meta_type = vgmstream->meta_type; + strcpy(temp_vs->stream_name, vgmstream->stream_name); + + close_vgmstream(vgmstream); + return temp_vs; + } #endif case PCM16: vgmstream->coding_type = h.big_endian ? coding_PCM16BE : coding_PCM16LE; @@ -131,13 +181,6 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) { goto fail; } - if (!h.bank_name_offset && h.stream_name_offset) - read_string(vgmstream->stream_name, STREAM_NAME_SIZE, h.stream_name_offset, sf); - else if (h.bank_name_offset && h.stream_name_offset) { - read_string(bank_name, STREAM_NAME_SIZE, h.bank_name_offset, sf); - read_string(stream_name, STREAM_NAME_SIZE, h.stream_name_offset, sf); - snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s/%s", bank_name, stream_name); - } if (!vgmstream_open_stream(vgmstream, sf, h.start_offset)) goto fail; @@ -277,8 +320,8 @@ static bool process_tables(STREAMFILE* sf, bnk_header_t* h) { switch(h->sblk_version) { case 0x01: /* Ratchet & Clank (PS2) */ - h->section_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c */ - h->material_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x28 */ + h->sounds_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c */ + h->grains_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x28 */ h->stream_entries = read_u16(h->sblk_offset+0x1a,sf); /* entry size: none (count) */ h->table1_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x20,sf); @@ -295,8 +338,8 @@ static bool process_tables(STREAMFILE* sf, bnk_header_t* h) { case 0x05: /* Ratchet & Clank (PS3) */ case 0x08: /* Playstation Home Arcade (Vita) */ case 0x09: /* Puyo Puyo Tetris (PS4) */ - h->section_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds) */ - h->material_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x08 (NumGrains) */ + h->sounds_entries = read_u16(h->sblk_offset+0x16,sf); /* entry size: ~0x0c (NumSounds) */ + h->grains_entries = read_u16(h->sblk_offset+0x18,sf); /* entry size: ~0x08 (NumGrains) */ h->stream_entries = read_u16(h->sblk_offset+0x1a,sf); /* entry size: ~0x18 + variable (NumWaveforms) */ h->table1_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); /* sound offset */ h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x20,sf); /* grain offset */ @@ -321,8 +364,8 @@ static bool process_tables(STREAMFILE* sf, bnk_header_t* h) { h->table2_offset = h->sblk_offset + read_u32(h->sblk_offset+0x1c,sf); h->table3_offset = h->sblk_offset + read_u32(h->sblk_offset+0x2c,sf); h->table4_offset = h->sblk_offset + read_u32(h->sblk_offset+0x30,sf); - h->section_entries = read_u16(h->sblk_offset+0x38,sf); /* entry size: ~0x24 */ - h->material_entries = read_u16(h->sblk_offset+0x3a,sf); /* entry size: ~0x08 */ + h->sounds_entries = read_u16(h->sblk_offset+0x38,sf); /* entry size: ~0x24 */ + h->grains_entries = read_u16(h->sblk_offset+0x3a,sf); /* entry size: ~0x08 */ h->stream_entries = read_u16(h->sblk_offset+0x3c,sf); /* entry size: ~0x5c + variable */ h->table1_entry_size = 0x24; @@ -330,15 +373,28 @@ static bool process_tables(STREAMFILE* sf, bnk_header_t* h) { h->table2_suboffset = 0x00; break; + /* later version have a few more tables (some optional) and work slightly differently (header is part of wave) */ case 0x1a: /* Demon's Souls (PS5) */ - case 0x23: /* The Last of Us (PC) */ + case 0x23: { /* The Last of Us (PC) */ + uint32_t tables_offset = h->sblk_offset + (h->sblk_version <= 0x1a ? 0x120 : 0x128); + uint32_t counts_offset = tables_offset + (h->sblk_version <= 0x1a ? 0x98 : 0xb0); + + //h->table1_offset = h->sblk_offset + read_u32(tables_offset+0x00,sf); /* sounds/cues */ + //h->table2_offset = 0; + h->table3_offset = h->sblk_offset + read_u32(tables_offset+0x08,sf); /* wave offsets with info (integrated grains+waves?)*/ + //h->sounds_entries = read_u16(counts_offset+0x00,sf); + //h->grains_entries = read_u16(counts_offset+0x02,sf); + h->stream_entries = read_u16(counts_offset+0x06,sf); + break; + } + default: vgm_logi("BNK: unknown version %x (report)\n", h->sblk_version); goto fail; } //;VGM_LOG("BNK: table offsets=%x, %x, %x, %x\n", h->table1_offset, h->table2_offset, h->table3_offset, h->table4_offset); - //;VGM_LOG("BNK: table entries=%i, %i, %i\n", h->section_entries, h->material_entries, h->stream_entries); + //;VGM_LOG("BNK: table entries=%i, %i, %i\n", h->sounds_entries, h->grains_entries, h->stream_entries); return true; fail: @@ -368,7 +424,7 @@ static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { * there is no stream size like in v0x03 */ - for (i = 0; i < h->material_entries; i++) { + for (i = 0; i < h->grains_entries; i++) { uint32_t table2_type = read_u32(h->table2_offset + (i*0x28) + 0x00, sf); if (table2_type != 0x01) @@ -385,8 +441,14 @@ static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { break; + case 0x1a: + case 0x23: + h->total_subsongs = h->stream_entries; + h->table3_entry_offset = (h->target_subsong - 1) * 0x08; + break; + default: - for (i = 0; i < h->material_entries; i++) { + for (i = 0; i < h->grains_entries; i++) { uint32_t table2_value, table2_subinfo, table2_subtype; table2_value = read_u32(h->table2_offset+(i*0x08) + h->table2_suboffset + 0x00,sf); @@ -416,7 +478,7 @@ static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { /* TODO: find dupes? */ } - //;VGM_LOG("BNK: header entry at %lx\n", h->table3_offset + h->table3_entry_offset); + //;VGM_LOG("BNK: header entry at %x\n", h->table3_offset + h->table3_entry_offset); sndh_offset = h->table3_offset + h->table3_entry_offset; @@ -494,6 +556,12 @@ static bool process_headers(STREAMFILE* sf, bnk_header_t* h) { h->sample_rate = (int)read_f32(sndh_offset+0x4c,sf); break; + case 0x1a: /* Demon's Souls (PS5) */ + case 0x23: /* The Last of Us (PC) */ + h->stream_offset = read_u32(sndh_offset+0x00,sf); + /* rest is part of data, handled later */ + break; + default: VGM_LOG("BNK: missing version\n"); goto fail; @@ -522,7 +590,7 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { switch (h->sblk_version) { case 0x03: - for (i = 0; i < h->section_entries; i++) { + for (i = 0; i < h->sounds_entries; i++) { entry_offset = read_u32(h->table1_offset + (i * h->table1_entry_size) + 0x08, sf); entry_count = read_u8(h->table1_offset + (i * h->table1_entry_size) + 0x04, sf); @@ -574,7 +642,7 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { case 0x04: case 0x05: /* a mix of v3 table1 parsing + v8-v16 table4 parsing */ - for (i = 0; i < h->section_entries; i++) { + for (i = 0; i < h->sounds_entries; i++) { entry_offset = read_u32(h->table1_offset + (i * h->table1_entry_size) + 0x08, sf); entry_count = read_u8(h->table1_offset + (i * h->table1_entry_size) + 0x04, sf); @@ -601,7 +669,7 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { table4_entries_offset = h->table4_offset + read_u32(h->table4_offset + 0x08, sf); table4_names_offset = h->table4_offset + read_u32(h->table4_offset + 0x0C, sf); - for (i = 0; i < h->section_entries; i++) { + for (i = 0; i < h->sounds_entries; i++) { if (read_u16(table4_entries_offset + (i * 0x10) + 0x0C, sf) == table4_entry_id) { h->stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10), sf); break; @@ -616,7 +684,7 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { case 0x0f: case 0x10: /* find if this sound has an assigned name in table1 */ - for (i = 0; i < h->section_entries; i++) { + for (i = 0; i < h->sounds_entries; i++) { entry_offset = read_u16(h->table1_offset + (i * h->table1_entry_size) + h->table1_suboffset + 0x00, sf); /* rarely (ex. Polara sfx) one name applies to multiple materials, @@ -637,11 +705,11 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { h->bank_name_offset = h->table4_offset; table4_entries_offset = h->table4_offset + read_u32(h->table4_offset + 0x08, sf); - table4_names_offset = table4_entries_offset + (0x10 * h->section_entries); + table4_names_offset = table4_entries_offset + (0x10 * h->sounds_entries); //;VGM_LOG("BNK: t4_entries=%lx, t4_names=%lx\n", table4_entries_offset, table4_names_offset); /* get assigned name from table4 names */ - for (i = 0; i < h->section_entries; i++) { + for (i = 0; i < h->sounds_entries; i++) { int entry_id = read_u32(table4_entries_offset + (i * 0x10) + 0x0c, sf); if (entry_id == table4_entry_id) { h->stream_name_offset = table4_names_offset + read_u32(table4_entries_offset + (i * 0x10) + 0x00, sf); @@ -665,11 +733,14 @@ static bool process_names(STREAMFILE* sf, bnk_header_t* h) { static bool process_data(STREAMFILE* sf, bnk_header_t* h) { read_u16_t read_u16 = h->big_endian ? read_u16be : read_u16le; read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + read_s32_t read_s32 = h->big_endian ? read_s32be : read_s32le; + read_u64_t read_u64 = h->big_endian ? read_u64be : read_u64le; int subtype, loop_length; uint32_t extradata_size = 0, postdata_size = 0; h->start_offset = h->data_offset + h->stream_offset; + uint32_t info_offset = h->start_offset; switch(h->sblk_version) { case 0x01: @@ -846,6 +917,41 @@ static bool process_data(STREAMFILE* sf, bnk_header_t* h) { } break; + case 0x1a: + case 0x23: + if (h->stream_offset == 0xFFFFFFFF) { + h->channels = 1; + h->codec = DUMMY; + break; + } + + /* pre-info */ + h->stream_name_size = read_u64(info_offset+0x00,sf); + h->stream_name_offset = info_offset + 0x08; + info_offset += h->stream_name_size + 0x08; + + h->stream_size = read_u64(info_offset + 0x00,sf); /* after this offset */ + h->stream_size += 0x08 + h->stream_name_size + 0x08; + /* 0x08: max block/etc size? (0x00010000/00030000) */ + /* 0x0c: always 1? */ + extradata_size = read_u64(info_offset + 0x10,sf) + 0x08 + h->stream_name_size + 0x18; + info_offset += 0x18; + + /* actual stream info */ + /* 0x00: extradata size (without pre-info, also above) */ + h->atrac9_info = read_u32be(info_offset+0x04,sf); + h->num_samples = read_s32(info_offset+0x08,sf); + h->channels = read_u32(info_offset+0x0c,sf); + h->loop_start = read_s32(info_offset+0x10,sf); + h->loop_end = read_s32(info_offset+0x14,sf); + /* 0x18: loop flag (0=loop, -1=no) */ + /* rest: null */ + /* no sample rate (probably fixed to 48000/system's, but seen in RIFF) */ + h->sample_rate = 48000; + + h->codec = RIFF_ATRAC9; /* unsure how other codecs would work */ + break; + default: vgm_logi("BNK: unknown data version %x (report)\n", h->sblk_version); goto fail; @@ -854,7 +960,42 @@ static bool process_data(STREAMFILE* sf, bnk_header_t* h) { h->start_offset += extradata_size; h->stream_size -= extradata_size; h->stream_size -= postdata_size; - //;VGM_LOG("BNK: offset=%lx, size=%x\n", h->start_offset, h->stream_size); + //;VGM_LOG("BNK: offset=%x, size=%x\n", h->start_offset, h->stream_size); + + return true; +fail: + return false; +} + + +/* zlsd part: parse extra footer (vox?) data */ +static bool process_zlsd(STREAMFILE* sf, bnk_header_t* h) { + if (!h->zlsd_offset) + return true; + + read_u32_t read_u32 = h->big_endian ? read_u32be : read_u32le; + + if (read_u32(h->zlsd_offset+0x00,sf) != get_id32be("DSLZ")) + return false; + + /* 0x04: version? (1) */ + int zlsd_count = read_u32(h->zlsd_offset+0x08,sf); + /* 0x0c: start */ + /* rest: null */ + + if (zlsd_count) { + vgm_logi("BNK: unsupported ZLSD subsongs found\n"); + goto fail; + } + + /* per entry (for v23) + * 00: crc (not referenced elsewhere) + * 04: stream offset (from this offset) + * 08: null (part of offset?) + * 0c: stream size + * 10: offset/size? + * 14: null */ + /* known streams are standard XVAG (no subsongs) */ return true; fail: @@ -888,11 +1029,11 @@ static bool parse_bnk_v3(STREAMFILE* sf, bnk_header_t* h) { //h->sblk_size = read_u32(0x0c,sf); h->data_offset = read_u32(0x10,sf); h->data_size = read_u32(0x14,sf); - /* ZLSD small empty footer, rare in earlier versions and common later [Yakuza 6's Puyo Puyo (PS4)] */ - //if (h->sblk_offset >= 0x20) { - // zlsd_offset = read_u32(0x18,sf); - // zlsd_size = read_u32(0x1c,sf); - //} + /* ZLSD footer, rare in earlier versions and common later (often empty) [Yakuza 6's Puyo Puyo (PS4)] */ + if (sections >= 3) { + h->zlsd_offset = read_u32(0x18,sf); + h->zlsd_size = read_u32(0x1c,sf); + } if (h->sblk_offset > 0x20) return false; @@ -923,6 +1064,7 @@ static bool parse_bnk_v3(STREAMFILE* sf, bnk_header_t* h) { * - 0x20: filename (0x100?) */ //;VGM_LOG("BNK: h->sblk_offset=%lx, h->data_offset=%lx, h->sblk_version %x\n", h->sblk_offset, h->data_offset, h->sblk_version); + //TODO handle, in rare cases may contain subsongs (unsure how are referenced but has its own number) if (!process_tables(sf, h)) goto fail; @@ -932,6 +1074,8 @@ static bool parse_bnk_v3(STREAMFILE* sf, bnk_header_t* h) { goto fail; if (!process_data(sf, h)) goto fail; + if (!process_zlsd(sf, h)) + goto fail; h->loop_flag = (h->loop_start >= 0) && (h->loop_end > 0); From fad6020b86507f62934030929cf940e3d532c0b6 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 17:24:51 +0200 Subject: [PATCH 139/141] doc --- doc/BUILD-LIB.md | 2 +- doc/BUILD.md | 4 ++-- doc/FORMATS.md | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/BUILD-LIB.md b/doc/BUILD-LIB.md index 5b54d7f3c..746c0c5b9 100644 --- a/doc/BUILD-LIB.md +++ b/doc/BUILD-LIB.md @@ -239,7 +239,7 @@ Some `libatrac9.vcxproj` x64 config may be outdated. In MSBuild +15 (VS +2017) y ``` -### libvorbis +### libvorbis/libogg Should be buildable with *autotools* (Git releases need to use `autogen.sh` first) or MSVC (projects in `./win32/`, may not be up to date). *CMake* may work as well. Methods below create 3 DLL: `libogg.dll`, `libvorbis.dll` and `libvorbisfile.dll` (also `libvorbisenc.dll`, unneeded), plus static libs (`.a`). However Vorbis/Ogg DLL support in vgmstream was originally added using a combined DLL from *RareWares* (https://www.rarewares.org/ogg-libraries.php) simply called `libvorbis.dll`, so separate DLLs can't be used at the moment and we'll need to fix that. diff --git a/doc/BUILD.md b/doc/BUILD.md index 26bf9fe34..1fdae4f81 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -487,7 +487,7 @@ They are compiled in their own sources, and the resulting binary is linked by vg Currently vgmstream's repository contains pre-compiled external DLL libraries for **Windows**, while other systems link to system libraries or include static copies using CMake. -### libvorbis +### libvorbis/libogg Adds support for Vorbis, inside Ogg as `.ogg` (plain or encrypted) or custom variations like `.wem`, `.fsb`, `.ogl`, etc. - Sources: - http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.7.zip (for base vorbis decoding) @@ -495,7 +495,7 @@ Adds support for Vorbis, inside Ogg as `.ogg` (plain or encrypted) or custom var - Official Windows binaries: none - Commonly used compilations: https://www.rarewares.org/ogg-libraries.php (32-bit only, fusing libogg+libvorbis+libvorbisfile) - Version: 1.3.7 -- DLL: `libvorbis.dll` +- DLL: `libvorbis.dll` (includes `libogg` + `libvorbis` + `libvorbisfile` for historical reasons) - lib: `-lvorbis -lvorbisfile` - licensed under the 3-clause BSD license diff --git a/doc/FORMATS.md b/doc/FORMATS.md index ab20740b1..9b8f79756 100644 --- a/doc/FORMATS.md +++ b/doc/FORMATS.md @@ -167,7 +167,7 @@ different internally (encrypted, different versions, etc) and not always can be - Codecs: PSX - **xa.c** - Sony XA header [*XA*] - - *xa*: `.xa .str .pxa .grn .an2 .(extensionless)` + - *xa*: `.xa .str .pxa .grn .an2 .(extensionless) .xai` - Codecs: XA8 XA - **rxws.c** - Sony RXWS header [*RXWS*] @@ -1301,6 +1301,7 @@ different internally (encrypted, different versions, etc) and not always can be - **bnk_sony.c** - Sony BNK header [*BNK_SONY*] - *bnk_sony*: `.bnk` + - Subfiles: *riff* - Codecs: ATRAC9 PCM16BE PCM16LE PSX HEVAG - **nus3bank.c** - (container) From 344d459d964305c288413bd8c72da50c43aab7c3 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 17:39:30 +0200 Subject: [PATCH 140/141] txth: extra debug info --- src/meta/txth.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/meta/txth.c b/src/meta/txth.c index b3e0aff9e..c7b3052c3 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -313,6 +313,10 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) { (int32_t*)&txth.loop_start_sample, (int32_t*)&txth.loop_end_sample); } + if (txth.debug) { + vgm_logi("TXTH: offset=%x, size=%x, coefs=%x + %x\n", txth.start_offset, txth.data_size, txth.coef_offset, txth.coef_spacing); + } + /* build the VGMSTREAM */ vgmstream = allocate_vgmstream(txth.channels,txth.loop_flag); From 378430775b35528d03be4226ce1adf7d7eead6f7 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sat, 26 Aug 2023 17:39:52 +0200 Subject: [PATCH 141/141] Add .gmd extension [High Voltage games] --- src/formats.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/formats.c b/src/formats.c index 533b834e4..daaa0c434 100644 --- a/src/formats.c +++ b/src/formats.c @@ -204,6 +204,7 @@ static const char* extension_list[] = { "gcw", "genh", "gin", + "gmd", //txth/semi [High Voltage games: Charlie and the Chocolate Factory (GC), Zathura (GC)] "gms", "grn", "gsf",