From f3a9c3bdd3d4a88114aa0f6dcf96197fc010fa09 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:12:25 +0200 Subject: [PATCH 01/13] Fix .CSMP loops [Metroid Prime Trilogy (Wii)] --- src/meta/csmp.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/meta/csmp.c b/src/meta/csmp.c index c57cb8e9..2159879b 100644 --- a/src/meta/csmp.c +++ b/src/meta/csmp.c @@ -2,7 +2,7 @@ #include "../coding/coding.h" -/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */ +/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii)-sfx, Donkey Kong Country Returns (Wii)-sfx] */ VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; off_t start_offset, first_offset = 0x08, chunk_offset; @@ -10,21 +10,20 @@ VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) { /* checks */ - if (!check_extensions(sf, "csmp")) - goto fail; if (!is_id32be(0x00, sf, "CSMP")) goto fail; - if (read_u32be(0x04, sf) != 1) + if (!check_extensions(sf, "csmp")) + goto fail; + if (read_u32be(0x04, sf) != 1) /* version? */ goto fail; - if (!find_chunk(sf, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/ + /* INFO > PAD > DATA */ + if (!find_chunk(sf, get_id32be("DATA"),first_offset,0, &chunk_offset,NULL, 1, 0)) goto fail; - /* contains standard DSP header, but somehow some validations (start/loop ps) - * don't seem to work, so no point to handle as standard DSP */ - - channels = 1; - loop_flag = read_s16be(chunk_offset+0x0c,sf); + /* contains a not quite standard DSP header */ + channels = 1; /* also at INFO + 0x00? (in practice uses dual stereo in separate files) */ + loop_flag = read_s16be(chunk_offset+0x0c,sf); /* also at INFO + 0x01 */ start_offset = chunk_offset + 0x60; @@ -35,10 +34,8 @@ VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) { vgmstream->meta_type = meta_CSMP; vgmstream->sample_rate = read_s32be(chunk_offset+0x08,sf); vgmstream->num_samples = read_s32be(chunk_offset+0x00,sf); - vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x10,sf)); - vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x14,sf)) + 1; - if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */ - vgmstream->loop_end_sample = vgmstream->num_samples; + vgmstream->loop_start_sample = read_s32be(chunk_offset+0x10,sf); /* unlike regular DSP's nibbles */ + vgmstream->loop_end_sample = read_s32be(chunk_offset+0x14,sf) + 1; vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_none; From 5890ab324f030bc80963b5908f7a79e6fb9cf07c Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:13:33 +0200 Subject: [PATCH 02/13] Add .opu extension [Ys: Oath in Felghana (Switch)] --- src/formats.c | 1 + src/meta/opus.c | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/formats.c b/src/formats.c index c6a27e73..f01e762d 100644 --- a/src/formats.c +++ b/src/formats.c @@ -393,6 +393,7 @@ static const char* extension_list[] = { "ogv", "oma", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "omu", + "opu", //"opus", //common "opusx", "otm", diff --git a/src/meta/opus.c b/src/meta/opus.c index f8e1832e..cf8497b8 100644 --- a/src/meta/opus.c +++ b/src/meta/opus.c @@ -133,9 +133,10 @@ VGMSTREAM* init_vgmstream_opus_std(STREAMFILE* sf) { if (read_u32le(0x00,sf) != 0x80000001) /* 'basic info' chunk */ goto fail; - /* .opus: standard - * .bgm: Cotton Reboot (Switch) */ - if (!check_extensions(sf,"opus,lopus,bgm")) + /* .opus: standard / .lopus: for plugins + * .bgm: Cotton Reboot (Switch) + * .opu: Ys Memoire: The Oath in Felghana (Switch) */ + if (!check_extensions(sf,"opus,lopus,bgm,opu")) goto fail; offset = 0x00; From b00518669e2435d307389facd716070af1611176 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:13:47 +0200 Subject: [PATCH 03/13] vrts: add report-diffs option --- cli/tools/vrts.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/cli/tools/vrts.py b/cli/tools/vrts.py index 53a543f1..b280eebc 100644 --- a/cli/tools/vrts.py +++ b/cli/tools/vrts.py @@ -52,8 +52,7 @@ def parse_args(): ap.add_argument("-r","--recursive", help="search files in subfolders", action='store_true') ap.add_argument("-z","--fuzzy", help="fuzzy threshold of +-N PCM16LE", type=int, default=1) ap.add_argument("-nd","--no-delete", help="don't delete output", action='store_true') - ap.add_argument("-rd","--result-diffs", help="only report full diffs", action='store_true') - ap.add_argument("-rz","--result-fuzzy", help="only report full and fuzzy diffs", action='store_true') + ap.add_argument("-rd","--report-diffs", help="only report full diffs", action='store_true') ap.add_argument("-p","--performance-both", help="compare decode performance", action='store_true') ap.add_argument("-pn","--performance-new", help="test performance of new CLI", action='store_true') ap.add_argument("-po","--performance-old", help="test performance of old CLI", action='store_true') @@ -335,7 +334,15 @@ class VrtsPrinter: RESULT_MISSING_OLD: 'missing old', } - def __init__(self): + REPORTS_DIFFS = [ + #RESULT_NONE, + RESULT_SIZES, + RESULT_MISSING_NEW, + RESULT_MISSING_OLD + ] + + def __init__(self, args): + self._args = args try: os.system('color') #win only? except: @@ -347,7 +354,7 @@ class VrtsPrinter: else: print(msg) - + def result(self, msg, code, fuzzy_diff=0, fuzzy_offset=0): text = self.TEXT_RESULT.get(code) color = self.COLOR_RESULT.get(code) @@ -356,7 +363,13 @@ class VrtsPrinter: msg = "%s: %s" % (msg, text) if fuzzy_diff != 0: msg += " (%s @0x%x)" % (fuzzy_diff, fuzzy_offset) - self._print(msg, color) + + report = True + if self._args.report_diffs and code not in self.REPORTS_DIFFS: + report = False + + if report: + self._print(msg, color) def info(self, msg): @@ -471,7 +484,7 @@ class VrtsApp: self._args = args self._files = VrtsFiles(args) self._prc = VrtsProcess() - self._p = VrtsPrinter() + self._p = VrtsPrinter(args) self._cli_new = None self._cli_old = None self._temp_files = [] From 2e3205ad41d12fac6f05ac29638c4282b0ba3687 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:14:40 +0200 Subject: [PATCH 04/13] Fix some MUSX loops --- src/coding/ima_decoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/coding/ima_decoder.c b/src/coding/ima_decoder.c index 76c6f49f..f5533581 100644 --- a/src/coding/ima_decoder.c +++ b/src/coding/ima_decoder.c @@ -1317,9 +1317,11 @@ size_t xbox_ima_bytes_to_samples(size_t bytes, int channels) { size_t dat4_ima_bytes_to_samples(size_t bytes, int channels) { int block_align = 0x20 * channels; if (channels <= 0) return 0; + + int mod = bytes % block_align; /* DAT4 IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */ return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels - + ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); /* unlikely (encoder aligns) */ + + ((mod > 0 && mod > 0x04*channels) ? (mod - 0x04*channels) * 2 / channels : 0); /* unlikely (encoder aligns) */ } size_t apple_ima4_bytes_to_samples(size_t bytes, int channels) { From eadaf21bde9e383ae94123d41c3e27d0bb507043 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:17:51 +0200 Subject: [PATCH 05/13] internal cleanup (move files) --- audacious/plugin.cc | 2 +- cli/vgmstream123.c | 2 +- cli/vgmstream_cli.c | 2 +- doc/BUILD.md | 2 +- fb2k/foo_vgmstream.cpp | 2 +- src/api.h | 6 +++- src/{ => base}/decode.c | 6 ++-- src/{ => base}/decode.h | 2 +- src/base/info.c | 2 +- src/{ => base}/mixing.c | 4 +-- src/{ => base}/mixing.h | 2 +- src/{ => base}/plugins.c | 4 +-- src/{ => base}/plugins.h | 4 +-- src/{ => base}/render.c | 4 +-- src/{ => base}/render.h | 2 +- src/{ => base}/seek.c | 4 +-- src/layout/blocked.c | 2 +- src/layout/flat.c | 2 +- src/layout/interleave.c | 2 +- src/layout/layered.c | 6 ++-- src/layout/segmented.c | 6 ++-- src/libvgmstream.vcxproj | 18 +++++------ src/libvgmstream.vcxproj.filters | 54 ++++++++++++++++---------------- src/meta/txtp.c | 4 +-- src/vgmstream.c | 6 ++-- winamp/in_vgmstream.h | 2 +- xmplay/xmp_vgmstream.c | 2 +- 27 files changed, 79 insertions(+), 75 deletions(-) rename src/{ => base}/decode.c (99%) rename src/{ => base}/decode.h (98%) rename src/{ => base}/mixing.c (99%) rename src/{ => base}/mixing.h (98%) rename src/{ => base}/plugins.c (99%) rename src/{ => base}/plugins.h (98%) rename src/{ => base}/render.c (99%) rename src/{ => base}/render.h (88%) rename src/{ => base}/seek.c (99%) diff --git a/audacious/plugin.cc b/audacious/plugin.cc index a773f937..95383583 100644 --- a/audacious/plugin.cc +++ b/audacious/plugin.cc @@ -16,7 +16,7 @@ extern "C" { #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" } #include "plugin.h" #include "vfs.h" diff --git a/cli/vgmstream123.c b/cli/vgmstream123.c index 8992419b..191a7bb2 100644 --- a/cli/vgmstream123.c +++ b/cli/vgmstream123.c @@ -38,7 +38,7 @@ #endif #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" #include "../src/util/samples_ops.h" #include "../version.h" diff --git a/cli/vgmstream_cli.c b/cli/vgmstream_cli.c index a76964a8..5f47c71d 100644 --- a/cli/vgmstream_cli.c +++ b/cli/vgmstream_cli.c @@ -5,7 +5,7 @@ #include #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" #include "../src/util.h" #include "../src/util/samples_ops.h" //todo use <>? diff --git a/doc/BUILD.md b/doc/BUILD.md index 225a8aaa..26bf9fe3 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -10,7 +10,7 @@ vgmstream can be compiled using one of several build scripts that are available Because each module has different quirks one can't use a single tool for everything. You should be able to build most using a standard *compiler* (GCC/MSVC/Clang) using common *build systems* (scripts/CMake/autotools) in any typical *OS* (Windows/Linux/macOS). -64-bit support should work but hasn't been throughly tested (may have subtle decoding bugs in some codecs), since most used components are plugins for 32-bit players. Windows libraries for extra codecs are included for 32-bit only at the moment. +64-bit support should work but hasn't been as throughly tested, since most used components are plugins for 32-bit players. Windows libraries for extra codecs are included for 32-bit only at the moment. Though it's rather flexible (like using Windows with GCC and autotools), some combos may be a bit more complex to get working depending on your system and other factors. diff --git a/fb2k/foo_vgmstream.cpp b/fb2k/foo_vgmstream.cpp index 421ae85c..928e483f 100644 --- a/fb2k/foo_vgmstream.cpp +++ b/fb2k/foo_vgmstream.cpp @@ -12,7 +12,7 @@ extern "C" { #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" } #include "foo_vgmstream.h" #include "foo_filetypes.h" diff --git a/src/api.h b/src/api.h index b9a9f69d..c96d705d 100644 --- a/src/api.h +++ b/src/api.h @@ -1,6 +1,10 @@ -//possible future public/opaque API #ifndef _API_H_ #define _API_H_ + +#include "base/plugins.h" + + +//possible future public/opaque API #if 0 #include diff --git a/src/decode.c b/src/base/decode.c similarity index 99% rename from src/decode.c rename to src/base/decode.c index 0aefcf9b..3f95c96a 100644 --- a/src/decode.c +++ b/src/base/decode.c @@ -1,7 +1,7 @@ -#include "vgmstream.h" +#include "../vgmstream.h" +#include "../layout/layout.h" +#include "../coding/coding.h" #include "decode.h" -#include "layout/layout.h" -#include "coding/coding.h" #include "mixing.h" #include "plugins.h" diff --git a/src/decode.h b/src/base/decode.h similarity index 98% rename from src/decode.h rename to src/base/decode.h index 01adf358..14e6e859 100644 --- a/src/decode.h +++ b/src/base/decode.h @@ -1,7 +1,7 @@ #ifndef _DECODE_H #define _DECODE_H -#include "vgmstream.h" +#include "../vgmstream.h" void free_codec(VGMSTREAM* vgmstream); void seek_codec(VGMSTREAM* vgmstream); diff --git a/src/base/info.c b/src/base/info.c index 5d7f5ede..5ee86a47 100644 --- a/src/base/info.c +++ b/src/base/info.c @@ -1,7 +1,7 @@ #include #include "../vgmstream.h" #include "../coding/coding.h" -#include "../mixing.h" +#include "mixing.h" #include "../util/channel_mappings.h" diff --git a/src/mixing.c b/src/base/mixing.c similarity index 99% rename from src/mixing.c rename to src/base/mixing.c index 896197f6..17ae4397 100644 --- a/src/mixing.c +++ b/src/base/mixing.c @@ -1,7 +1,7 @@ -#include "vgmstream.h" +#include "../vgmstream.h" +#include "../util/channel_mappings.h" #include "mixing.h" #include "plugins.h" -#include "util/channel_mappings.h" #include #include diff --git a/src/mixing.h b/src/base/mixing.h similarity index 98% rename from src/mixing.h rename to src/base/mixing.h index e563c5b4..d63d7645 100644 --- a/src/mixing.h +++ b/src/base/mixing.h @@ -1,7 +1,7 @@ #ifndef _MIXING_H_ #define _MIXING_H_ -#include "vgmstream.h" +#include "../vgmstream.h" /* Applies mixing commands to the sample buffer. Mixing must be externally enabled and * outbuf must big enough to hold output_channels*samples_to_do */ diff --git a/src/plugins.c b/src/base/plugins.c similarity index 99% rename from src/plugins.c rename to src/base/plugins.c index a30412f7..c78ad6cc 100644 --- a/src/plugins.c +++ b/src/base/plugins.c @@ -1,7 +1,7 @@ -#include "vgmstream.h" +#include "../vgmstream.h" +#include "../util/log.h" #include "plugins.h" #include "mixing.h" -#include "util/log.h" /* ****************************************** */ diff --git a/src/plugins.h b/src/base/plugins.h similarity index 98% rename from src/plugins.h rename to src/base/plugins.h index b160e8d5..dbc25c79 100644 --- a/src/plugins.h +++ b/src/base/plugins.h @@ -4,8 +4,8 @@ #ifndef _PLUGINS_H_ #define _PLUGINS_H_ -#include "streamfile.h" -#include "vgmstream.h" +#include "../streamfile.h" +#include "../vgmstream.h" /* ****************************************** */ diff --git a/src/render.c b/src/base/render.c similarity index 99% rename from src/render.c rename to src/base/render.c index 06e9af44..94afd5bf 100644 --- a/src/render.c +++ b/src/base/render.c @@ -1,5 +1,5 @@ -#include "vgmstream.h" -#include "layout/layout.h" +#include "../vgmstream.h" +#include "../layout/layout.h" #include "render.h" #include "decode.h" #include "mixing.h" diff --git a/src/render.h b/src/base/render.h similarity index 88% rename from src/render.h rename to src/base/render.h index 4a3b1de3..93fb388a 100644 --- a/src/render.h +++ b/src/base/render.h @@ -1,7 +1,7 @@ #ifndef _RENDER_H #define _RENDER_H -#include "vgmstream.h" +#include "../vgmstream.h" void free_layout(VGMSTREAM* vgmstream); void reset_layout(VGMSTREAM* vgmstream); diff --git a/src/seek.c b/src/base/seek.c similarity index 99% rename from src/seek.c rename to src/base/seek.c index 46ef3abc..9a271eb4 100644 --- a/src/seek.c +++ b/src/base/seek.c @@ -1,5 +1,5 @@ -#include "vgmstream.h" -#include "layout/layout.h" +#include "../vgmstream.h" +#include "../layout/layout.h" #include "render.h" #include "decode.h" #include "mixing.h" diff --git a/src/layout/blocked.c b/src/layout/blocked.c index 395af40e..bac084ec 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -1,6 +1,6 @@ #include "layout.h" #include "../vgmstream.h" -#include "../decode.h" +#include "../base/decode.h" #include "../coding/coding.h" diff --git a/src/layout/flat.c b/src/layout/flat.c index ff3001b7..603281c1 100644 --- a/src/layout/flat.c +++ b/src/layout/flat.c @@ -1,6 +1,6 @@ #include "layout.h" #include "../vgmstream.h" -#include "../decode.h" +#include "../base/decode.h" /* Decodes samples for flat streams. diff --git a/src/layout/interleave.c b/src/layout/interleave.c index 0714d6d9..1c8ba0ae 100644 --- a/src/layout/interleave.c +++ b/src/layout/interleave.c @@ -1,6 +1,6 @@ #include "layout.h" #include "../vgmstream.h" -#include "../decode.h" +#include "../base/decode.h" /* Decodes samples for interleaved streams. diff --git a/src/layout/layered.c b/src/layout/layered.c index 5e057045..e6221b74 100644 --- a/src/layout/layered.c +++ b/src/layout/layered.c @@ -1,8 +1,8 @@ #include "layout.h" #include "../vgmstream.h" -#include "../decode.h" -#include "../mixing.h" -#include "../plugins.h" +#include "../base/decode.h" +#include "../base/mixing.h" +#include "../base/plugins.h" #define VGMSTREAM_MAX_LAYERS 255 #define VGMSTREAM_LAYER_SAMPLE_BUFFER 8192 diff --git a/src/layout/segmented.c b/src/layout/segmented.c index 97d32add..85a61740 100644 --- a/src/layout/segmented.c +++ b/src/layout/segmented.c @@ -1,8 +1,8 @@ #include "layout.h" #include "../vgmstream.h" -#include "../decode.h" -#include "../mixing.h" -#include "../plugins.h" +#include "../base/decode.h" +#include "../base/mixing.h" +#include "../base/plugins.h" #define VGMSTREAM_MAX_SEGMENTS 1024 #define VGMSTREAM_SEGMENT_SAMPLE_BUFFER 8192 diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 19bf7900..31cf0f61 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -81,15 +81,15 @@ - - - - + + + + @@ -184,16 +184,16 @@ - - - - - + + + + + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index c89f2c33..aee5e93d 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -68,18 +68,6 @@ Header Files - - Header Files - - - Header Files - - - Header Files - - - Header Files - Header Files @@ -95,6 +83,18 @@ Header Files + + base\Header Files + + + base\Header Files + + + base\Header Files + + + base\Header Files + coding\Header Files @@ -373,24 +373,9 @@ - - Source Files - Source Files - - Source Files - - - Source Files - - - Source Files - - - Source Files - Source Files @@ -400,9 +385,24 @@ Source Files + + base\Source Files + base\Source Files + + base\Source Files + + + base\Source Files + + + base\Source Files + + + base\Source Files + coding\Source Files diff --git a/src/meta/txtp.c b/src/meta/txtp.c index 69f5e50f..e6d382b1 100644 --- a/src/meta/txtp.c +++ b/src/meta/txtp.c @@ -1,8 +1,8 @@ #include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" -#include "../mixing.h" -#include "../plugins.h" +#include "../base/mixing.h" +#include "../base/plugins.h" #include "../util/text_reader.h" #include diff --git a/src/vgmstream.c b/src/vgmstream.c index a2f6a6c4..bf1573b8 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -9,9 +9,9 @@ #include "meta/meta.h" #include "layout/layout.h" #include "coding/coding.h" -#include "decode.h" -#include "render.h" -#include "mixing.h" +#include "base/decode.h" +#include "base/render.h" +#include "base/mixing.h" static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM* (*init_vgmstream_function)(STREAMFILE*)); diff --git a/winamp/in_vgmstream.h b/winamp/in_vgmstream.h index da6e388f..c30663f2 100644 --- a/winamp/in_vgmstream.h +++ b/winamp/in_vgmstream.h @@ -22,7 +22,7 @@ #include #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" #include "sdk/in2.h" #include "sdk/wa_ipc.h" #include "sdk/ipc_pe.h" diff --git a/xmplay/xmp_vgmstream.c b/xmplay/xmp_vgmstream.c index 1e35e93c..ddc5e0fb 100644 --- a/xmplay/xmp_vgmstream.c +++ b/xmplay/xmp_vgmstream.c @@ -13,7 +13,7 @@ #include "xmpin.h" #include "../src/vgmstream.h" -#include "../src/plugins.h" +#include "../src/api.h" #include "../version.h" From ff34edfa9176539bf3da730b45bda4189787f880 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 20:18:27 +0200 Subject: [PATCH 06/13] cleanup: minor tweaks --- src/meta/xnb_streamfile.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/meta/xnb_streamfile.h b/src/meta/xnb_streamfile.h index 949f2716..a5c40704 100644 --- a/src/meta/xnb_streamfile.h +++ b/src/meta/xnb_streamfile.h @@ -2,17 +2,20 @@ #define _XNB_STREAMFILE_H_ //#define XNB_ENABLE_LZX 1 +#include "../streamfile.h" +#include "../util/log.h" + +#include "xnb_lz4mg.h" #ifdef XNB_ENABLE_LZX -/* lib from https://github.com/sumatrapdfreader/chmlib +/* can be safely enabled but useless since LZX isn't used for audio assets + * lib from https://github.com/sumatrapdfreader/chmlib * which is a cleaned-up version of https://github.com/jedwing/CHMLib */ -#include "lzx.h" +#include "../utils/lzx.h" #define LZX_XNB_WINDOW_BITS 16 #endif -#include "xnb_lz4mg.h" - #define XNB_TYPE_LZX 1 #define XNB_TYPE_LZ4 2 From bf218c08b465a0a61b42f7564e97c711a025f8b6 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 21:20:29 +0200 Subject: [PATCH 07/13] cleanup: separate functions move common functions to its own .h so it's clearer where are they used and don't get copied in all headers --- src/base/plugins.c | 1 + src/coding/coding.h | 1 + src/coding/nwa_decoder.c | 2 +- src/layout/layout.h | 1 + src/meta/baf.c | 6 +- src/meta/bkhd.c | 9 ++- src/meta/ea_eaac.c | 5 +- src/meta/ea_schl.c | 7 +- src/meta/ea_wve_ad10.c | 3 +- src/meta/kwb.c | 3 +- src/meta/meta.h | 1 + src/meta/mul.c | 2 +- src/meta/nub.c | 9 ++- src/meta/seg.c | 4 +- src/meta/sps_n1.c | 3 +- src/meta/sspr.c | 3 +- src/meta/ubi_bao.c | 5 +- src/meta/ubi_ckd.c | 4 +- src/streamfile.c | 1 + src/streamfile.h | 163 --------------------------------------- src/util.c | 9 +++ src/util.h | 2 + src/util/chunks.c | 2 +- src/util/cri_utf.c | 1 + src/util/endianness.h | 16 +++- src/util/reader_sf.h | 149 +++++++++++++++++++++++++++++++++++ 26 files changed, 219 insertions(+), 193 deletions(-) create mode 100644 src/util/reader_sf.h diff --git a/src/base/plugins.c b/src/base/plugins.c index c78ad6cc..27d9193d 100644 --- a/src/base/plugins.c +++ b/src/base/plugins.c @@ -1,5 +1,6 @@ #include "../vgmstream.h" #include "../util/log.h" +#include "../util/reader_sf.h" #include "plugins.h" #include "mixing.h" diff --git a/src/coding/coding.h b/src/coding/coding.h index f67d8a02..aa52ce7d 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -2,6 +2,7 @@ #define _CODING_H #include "../vgmstream.h" +#include "../util/reader_sf.h" #include "../util/reader_get_nibbles.h" //todo remove #include "hca_decoder_clhca.h" diff --git a/src/coding/nwa_decoder.c b/src/coding/nwa_decoder.c index 0e7beabf..859f2f8c 100644 --- a/src/coding/nwa_decoder.c +++ b/src/coding/nwa_decoder.c @@ -61,7 +61,7 @@ #include #include "nwa_decoder.h" - +#include "../util/reader_sf.h" //NWAInfo::UseRunLength static int is_use_runlength(NWAData* nwa) { diff --git a/src/layout/layout.h b/src/layout/layout.h index 971143eb..1eeda70b 100644 --- a/src/layout/layout.h +++ b/src/layout/layout.h @@ -3,6 +3,7 @@ #include "../streamtypes.h" #include "../vgmstream.h" +#include "../util/reader_sf.h" /* blocked layouts */ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream); diff --git a/src/meta/baf.c b/src/meta/baf.c index 303db7e3..eb38bce0 100644 --- a/src/meta/baf.c +++ b/src/meta/baf.c @@ -1,5 +1,7 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" + /* .BAF - Bizarre Creations bank file [Blur (PS3), Project Gotham Racing 4 (X360), Geometry Wars (PC)] */ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) { @@ -8,7 +10,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) { size_t stream_size; uint32_t channel_count, sample_rate, num_samples, version, codec, tracks; int loop_flag, total_subsongs, target_subsong = sf->stream_index; - uint32_t (*read_u32)(off_t,STREAMFILE*); + read_u32_t read_u32; /* checks */ if (!is_id32be(0x00, sf, "BANK")) @@ -18,7 +20,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) { goto fail; /* use BANK size to check endianness */ - if (guess_endianness32bit(0x04,sf)) { + if (guess_endian32(0x04,sf)) { read_u32 = read_u32be; } else { read_u32 = read_u32le; diff --git a/src/meta/bkhd.c b/src/meta/bkhd.c index 8a3c7505..f18debac 100644 --- a/src/meta/bkhd.c +++ b/src/meta/bkhd.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../util/chunks.h" +#include "../util/endianness.h" /* BKHD - Wwise soundbank container */ @@ -10,8 +11,8 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) { uint32_t subfile_offset, subfile_size, base_offset = 0; uint32_t subfile_id, version; int big_endian, is_dummy = 0, is_wmid = 0; - uint32_t (*read_u32)(off_t,STREAMFILE*); - float (*read_f32)(off_t,STREAMFILE*); + read_u32_t read_u32; + read_f32_t read_f32; int total_subsongs, target_subsong = sf->stream_index; int prefetch = 0; @@ -24,7 +25,7 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) { base_offset = 0x0c; if (!is_id32be(base_offset + 0x00, sf, "BKHD")) goto fail; - big_endian = guess_endianness32bit(base_offset + 0x04, sf); + big_endian = guess_endian32(base_offset + 0x04, sf); read_u32 = big_endian ? read_u32be : read_u32le; read_f32 = big_endian ? read_f32be : read_f32le; @@ -200,7 +201,7 @@ VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf) { /* .wem: used when (rarely) external */ if (!check_extensions(sf,"wem,bnk")) goto fail; - big_endian = guess_endianness32bit(0x00, sf); + big_endian = guess_endian32(0x00, sf); read_u32 = big_endian ? read_u32be : read_u32le; /* Not an actual stream but typically convolution reverb models and other FX plugin helpers. diff --git a/src/meta/ea_eaac.c b/src/meta/ea_eaac.c index ce8e7dd5..314f1565 100644 --- a/src/meta/ea_eaac.c +++ b/src/meta/ea_eaac.c @@ -2,6 +2,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" #include "ea_eaac_streamfile.h" /* EAAudioCore (aka SND10) formats, EA's current audio middleware */ @@ -85,7 +86,7 @@ VGMSTREAM* init_vgmstream_ea_snu(STREAMFILE* sf) { * 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */ /* use start_offset as endianness flag */ - if (guess_endianness32bit(0x08,sf)) { + if (guess_endian32(0x08,sf)) { read_32bit = read_32bitBE; } else { read_32bit = read_32bitLE; @@ -125,7 +126,7 @@ VGMSTREAM* init_vgmstream_ea_abk_eaac(STREAMFILE* sf) { goto fail; /* use table offset to check endianness */ - if (guess_endianness32bit(0x1C, sf)) { + if (guess_endian32(0x1C, sf)) { read_32bit = read_32bitBE; read_16bit = read_16bitBE; } else { diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index e7031783..a4b23b24 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" #include "ea_schl_streamfile.h" /* header version */ @@ -222,7 +223,7 @@ VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf) { } /* use block size to check endianness */ - if (guess_endianness32bit(0x04, sf)) { + if (guess_endian32(0x04, sf)) { read_32bit = read_32bitBE; } else { read_32bit = read_32bitLE; @@ -329,7 +330,7 @@ VGMSTREAM* init_vgmstream_ea_abk(STREAMFILE* sf) { goto fail; /* use table offset to check endianness */ - if (guess_endianness32bit(0x1C, sf)) { + if (guess_endian32(0x1C, sf)) { read_32bit = read_32bitBE; read_16bit = read_16bitBE; } else { @@ -1142,7 +1143,7 @@ static VGMSTREAM* parse_schl_block(STREAMFILE* sf, off_t offset) { ea.codec_config |= (header_id & 0xFFFF) << 16; } - if (guess_endianness32bit(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */ + if (guess_endian32(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */ header_size = read_32bitBE(offset + 0x04, sf); ea.codec_config |= 0x02; } diff --git a/src/meta/ea_wve_ad10.c b/src/meta/ea_wve_ad10.c index 110af317..a720265e 100644 --- a/src/meta/ea_wve_ad10.c +++ b/src/meta/ea_wve_ad10.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../layout/layout.h" +#include "../util/endianness.h" /* EA WVE (Ad10) - from early Electronic Arts movies [Wing Commander 3/4 (PS1), Madden NHL 97 (PC)-w95] */ VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) { @@ -22,7 +23,7 @@ VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) { !is_id32be(0x00, sf, "Ad11")) /* last audio block, but could be first */ goto fail; - big_endian = guess_endianness32bit(0x04, sf); + big_endian = guess_endian32(0x04, sf); if (is_id32be(0x00, sf, "AABB")) start_offset += big_endian ? read_u32be(0x04, sf) : read_u32le(0x04, sf); diff --git a/src/meta/kwb.c b/src/meta/kwb.c index b7a1474e..3dd45663 100644 --- a/src/meta/kwb.c +++ b/src/meta/kwb.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF_APEX, XMA2 } kwb_codec; @@ -594,7 +595,7 @@ static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) { head_offset = 0x00; body_offset = 0x00; - kwb->big_endian = guess_endianness32bit(head_offset + 0x08, sf_h); + kwb->big_endian = guess_endian32(head_offset + 0x08, sf_h); read_u32 = kwb->big_endian ? read_u32be : read_u32le; } diff --git a/src/meta/meta.h b/src/meta/meta.h index 3e1c7c4d..2df93035 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -2,6 +2,7 @@ #define _META_H #include "../vgmstream.h" +#include "../util/reader_sf.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf); diff --git a/src/meta/mul.c b/src/meta/mul.c index 4eb042a1..613f7562 100644 --- a/src/meta/mul.c +++ b/src/meta/mul.c @@ -33,7 +33,7 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) { read_u32be(0x1c,sf) != 0) goto fail; - big_endian = guess_endianness32bit(0x00, sf); + big_endian = guess_endian32(0x00, sf); read_u32 = big_endian ? read_u32be : read_u32le; read_f32 = big_endian ? read_f32be : read_f32le; diff --git a/src/meta/nub.c b/src/meta/nub.c index 5e69a658..3499cc30 100644 --- a/src/meta/nub.c +++ b/src/meta/nub.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" static void load_name(char* name, size_t name_size, STREAMFILE* sf, int big_endian, int total_subsongs, int target_subsong); @@ -33,7 +34,7 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) { goto fail; /* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */ - big_endian = guess_endianness32bit(0x18, sf); + big_endian = guess_endian32(0x18, sf); if (big_endian) { read_32bit = read_32bitBE; } else{ @@ -249,7 +250,7 @@ VGMSTREAM* init_vgmstream_nub_wav(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x77617600) /* "wav\0" "*/ goto fail; - if (guess_endianness32bit(0x1c, sf)) { + if (guess_endian32(0x1c, sf)) { read_32bit = read_32bitBE; read_16bit = read_16bitBE; } else { @@ -313,7 +314,7 @@ VGMSTREAM* init_vgmstream_nub_vag(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x76616700) /* "vag\0" */ goto fail; - if (guess_endianness32bit(0x1c, sf)) { + if (guess_endian32(0x1c, sf)) { read_32bit = read_32bitBE; } else { read_32bit = read_32bitLE; @@ -598,7 +599,7 @@ VGMSTREAM* init_vgmstream_nub_is14(STREAMFILE* sf) { if (read_32bitBE(0x00,sf) != 0x69733134) /* "is14" */ goto fail; - if (guess_endianness32bit(0x1c, sf)) { + if (guess_endian32(0x1c, sf)) { read_32bit = read_32bitBE; } else{ read_32bit = read_32bitLE; diff --git a/src/meta/seg.c b/src/meta/seg.c index 27bed92f..756c9283 100644 --- a/src/meta/seg.c +++ b/src/meta/seg.c @@ -1,5 +1,7 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" + /* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { @@ -19,7 +21,7 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) { codec = read_32bitBE(0x04,sf); /* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */ - if (guess_endianness32bit(0x08,sf)) { + if (guess_endian32(0x08,sf)) { read_32bit = read_32bitBE; } else { read_32bit = read_32bitLE; diff --git a/src/meta/sps_n1.c b/src/meta/sps_n1.c index eed3d11c..0637cac6 100644 --- a/src/meta/sps_n1.c +++ b/src/meta/sps_n1.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" /* also see init_vgmstream_dsp_sps_n1 and init_vgmstream_opus_sps_n1 */ @@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) { if (!check_extensions(sf,"sps")) goto fail; - if (guess_endianness32bit(0x00, sf)) { /* PS3 */ + if (guess_endian32(0x00, sf)) { /* PS3 */ read_u32 = read_u32be; read_u16 = read_u16be; } diff --git a/src/meta/sspr.c b/src/meta/sspr.c index f24e1623..c877be76 100644 --- a/src/meta/sspr.c +++ b/src/meta/sspr.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/endianness.h" /* SSPR - Capcom container [Sengoku Basara 4 (PS3/PS4), Mega Man Zero ZX Legacy Collection (PS4)] */ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) { @@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) { /* Simple (audio only) container used some Capcom games (common engine?). * Some files come with a .stqr with unknown data (cues?). */ - big_endian = guess_endianness32bit(0x04, sf); /* 0x01 (version?) */ + big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */ read_u32 = big_endian ? read_u32be : read_u32le; total_subsongs = read_u32(0x08,sf); diff --git a/src/meta/ubi_bao.c b/src/meta/ubi_bao.c index 9093e442..e05370e2 100644 --- a/src/meta/ubi_bao.c +++ b/src/meta/ubi_bao.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#include "../util/endianness.h" #include "ubi_bao_streamfile.h" #define BAO_MIN_VERSION 0x1B @@ -1570,7 +1571,7 @@ static void config_bao_endian(ubi_bao_header* bao, off_t offset, STREAMFILE* sf) * This could be done once as all BAOs share endianness */ /* negate as fields looks like LE (0xN0000000) */ - bao->big_endian = !guess_endianness32bit(offset+bao->cfg.bao_class, sf); + bao->big_endian = !guess_endian32(offset+bao->cfg.bao_class, sf); } @@ -1714,7 +1715,7 @@ static int config_bao_version(ubi_bao_header* bao, STREAMFILE* sf) { /* next BAO uses machine endianness, entry should always exist * (maybe should use project BAO to detect?) */ - if (guess_endianness32bit(header_size + 0x04, sf)) { + if (guess_endian32(header_size + 0x04, sf)) { version |= 0xFF00; /* signal Wii=BE, but don't modify original */ } } diff --git a/src/meta/ubi_ckd.c b/src/meta/ubi_ckd.c index 47cf74d5..945f8416 100644 --- a/src/meta/ubi_ckd.c +++ b/src/meta/ubi_ckd.c @@ -1,6 +1,6 @@ #include "meta.h" #include "../coding/coding.h" -#include "../coding/coding.h" +#include "../util/endianness.h" typedef enum { MSADPCM, DSP, MP3, XMA2 } ckd_codec; @@ -30,7 +30,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) { if (!is_id32be(0x0c,sf, "fmt ")) goto fail; - big_endian = guess_endianness32bit(0x04, sf); + big_endian = guess_endian32(0x04, sf); read_u32 = big_endian ? read_u32be : read_u32le; read_u16 = big_endian ? read_u16be : read_u16le; diff --git a/src/streamfile.c b/src/streamfile.c index ec4d7df8..bfdabcbb 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1,6 +1,7 @@ #include "streamfile.h" #include "util.h" #include "vgmstream.h" +#include "util/reader_sf.h" #include /* for dup/fdopen in some systems */ diff --git a/src/streamfile.h b/src/streamfile.h index 5ca8f4cf..cd2402fb 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -161,169 +161,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) { } -/* Sometimes you just need an int, and we're doing the buffering. -* Note, however, that if these fail to read they'll return -1, -* so that should not be a valid value or there should be some backup. */ -static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) { - uint8_t buf[2]; - - if (read_streamfile(buf,offset,2,sf)!=2) return -1; - return get_16bitLE(buf); -} -static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) { - uint8_t buf[2]; - - if (read_streamfile(buf,offset,2,sf)!=2) return -1; - return get_16bitBE(buf); -} -static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) { - uint8_t buf[4]; - - if (read_streamfile(buf,offset,4,sf)!=4) return -1; - return get_32bitLE(buf); -} -static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) { - uint8_t buf[4]; - - if (read_streamfile(buf,offset,4,sf)!=4) return -1; - return get_32bitBE(buf); -} -static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) { - uint8_t buf[8]; - - if (read_streamfile(buf,offset,8,sf)!=8) return -1; - return get_64bitLE(buf); -} -static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) { - uint8_t buf[8]; - - if (read_streamfile(buf,offset,8,sf)!=8) return -1; - return get_64bitBE(buf); -} -static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) { - uint8_t buf[1]; - - if (read_streamfile(buf,offset,1,sf)!=1) return -1; - return buf[0]; -} - -/* alias of the above */ -static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); } -static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); } -static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); } -static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); } -static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); } -static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); } -static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); } -static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); } -static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); } -static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); } -static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); } -static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); } -static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); } -static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); } - -static inline float read_f32be(off_t offset, STREAMFILE* sf) { - uint8_t buf[4]; - - if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) - return -1; - return get_f32be(buf); -} -static inline float read_f32le(off_t offset, STREAMFILE* sf) { - uint8_t buf[4]; - - if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) - return -1; - return get_f32le(buf); -} - -#if 0 -// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring: -// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle; -// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant). -// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants -// so may result on bloatness? -// (from godbolt tests, test more real cases) - -/* collection of callbacks for quick access */ -typedef struct sf_reader { - int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32 - float (*read_f32)(off_t,STREAMFILE*); - /* ... */ -} sf_reader; - -static inline void sf_reader_init(sf_reader* r, int big_endian) { - memset(r, 0, sizeof(sf_reader)); - if (big_endian) { - r->read_s32 = read_s32be; - r->read_f32 = read_f32be; - } - else { - r->read_s32 = read_s32le; - r->read_f32 = read_f32le; - } -} - -/* sf_reader r; - * ... - * sf_reader_init(&r, big_endian); - * val = r.read_s32; //maybe r.s32? - */ -#endif -#if 0 //todo improve + test + simplify code (maybe not inline?) -static inline int read_s4h(off_t offset, STREAMFILE* sf) { - uint8_t byte = read_u8(offset, streamfile); - return get_nibble_signed(byte, 1); -} -static inline int read_u4h(off_t offset, STREAMFILE* sf) { - uint8_t byte = read_u8(offset, streamfile); - return (byte >> 4) & 0x0f; -} -static inline int read_s4l(off_t offset, STREAMFILE* sf) { - ... -} -static inline int read_u4l(off_t offset, STREAMFILE* sf) { - ... -} -static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; } -static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; } -//align32, align16, clamp16, etc -#endif - -/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */ -static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) { - return read_u32be(offset, sf) == get_id32be(s); -} - -static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) { - return read_u32le(offset, sf) == get_id32be(s); -} - -static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) { - return read_u64be(offset, sf) == get_id64be(s); -} - - -//TODO: maybe move to streamfile.c -/* guess byte endianness from a given value, return true if big endian and false if little endian */ -static inline int guess_endianness16bit(off_t offset, STREAMFILE* sf) { - uint8_t buf[0x02]; - if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */ - return get_u16le(buf) > get_u16be(buf) ? 1 : 0; -} -static inline int guess_endianness32bit(off_t offset, STREAMFILE* sf) { - uint8_t buf[0x04]; - if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */ - return get_u32le(buf) > get_u32be(buf) ? 1 : 0; -} - -static inline size_t align_size_to_block(size_t value, size_t block_align) { - size_t extra_size = value % block_align; - if (extra_size == 0) return value; - return (value + block_align - extra_size); -} - /* various STREAMFILE helpers functions */ /* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated diff --git a/src/util.c b/src/util.c index d35e239b..06aa6e85 100644 --- a/src/util.c +++ b/src/util.c @@ -42,3 +42,12 @@ void concatn(int length, char * dst, const char * src) { dst[i]=src[j]; dst[i]='\0'; } + +size_t align_size_to_block(size_t value, size_t block_align) { + if (!block_align) + return 0; + + size_t extra_size = value % block_align; + if (extra_size == 0) return value; + return (value + block_align - extra_size); +} diff --git a/src/util.h b/src/util.h index 9a83e9c6..4b6c551e 100644 --- a/src/util.h +++ b/src/util.h @@ -51,4 +51,6 @@ const char* filename_extension(const char* pathname); void concatn(int length, char * dst, const char * src); +size_t align_size_to_block(size_t value, size_t block_align); + #endif diff --git a/src/util/chunks.c b/src/util/chunks.c index 0898dfd1..7bdb2ad0 100644 --- a/src/util/chunks.c +++ b/src/util/chunks.c @@ -1,5 +1,5 @@ #include "chunks.h" -//#include "log.h" +#include "reader_sf.h" int next_chunk(chunk_t* chunk, STREAMFILE* sf) { diff --git a/src/util/cri_utf.c b/src/util/cri_utf.c index e3174ca0..36fb74da 100644 --- a/src/util/cri_utf.c +++ b/src/util/cri_utf.c @@ -1,5 +1,6 @@ #include "cri_utf.h" #include "log.h" +#include "reader_sf.h" #define UTF_MAX_SCHEMA_SIZE 0x8000 /* arbitrary max */ #define COLUMN_BITMASK_FLAG 0xf0 diff --git a/src/util/endianness.h b/src/util/endianness.h index 84723b88..762d63e1 100644 --- a/src/util/endianness.h +++ b/src/util/endianness.h @@ -2,6 +2,7 @@ #define _UTIL_ENDIAN_H #include "../streamfile.h" +#include "reader_get.h" typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*); typedef int32_t (*read_s32_t)(off_t, STREAMFILE*); @@ -11,8 +12,17 @@ typedef float (*read_f32_t)(off_t, STREAMFILE*); typedef int16_t (*get_s16_t)(const uint8_t*); -//todo move here -#define guess_endian32 guess_endianness32bit -#define guess_endian16 guess_endianness16bit +/* guess byte endianness from a given value, return true if big endian and false if little endian */ +static inline int guess_endian16(off_t offset, STREAMFILE* sf) { + uint8_t buf[0x02]; + if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */ + return get_u16le(buf) > get_u16be(buf) ? 1 : 0; +} + +static inline int guess_endian32(off_t offset, STREAMFILE* sf) { + uint8_t buf[0x04]; + if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */ + return get_u32le(buf) > get_u32be(buf) ? 1 : 0; +} #endif diff --git a/src/util/reader_sf.h b/src/util/reader_sf.h new file mode 100644 index 00000000..ef8f36fb --- /dev/null +++ b/src/util/reader_sf.h @@ -0,0 +1,149 @@ +#ifndef _READER_SF_H +#define _READER_SF_H +#include "../streamfile.h" + + +/* Sometimes you just need an int, and we're doing the buffering. +* Note, however, that if these fail to read they'll return -1, +* so that should not be a valid value or there should be some backup. */ +static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) { + uint8_t buf[2]; + + if (read_streamfile(buf,offset,2,sf)!=2) return -1; + return get_16bitLE(buf); +} +static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) { + uint8_t buf[2]; + + if (read_streamfile(buf,offset,2,sf)!=2) return -1; + return get_16bitBE(buf); +} +static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) { + uint8_t buf[4]; + + if (read_streamfile(buf,offset,4,sf)!=4) return -1; + return get_32bitLE(buf); +} +static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) { + uint8_t buf[4]; + + if (read_streamfile(buf,offset,4,sf)!=4) return -1; + return get_32bitBE(buf); +} +static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) { + uint8_t buf[8]; + + if (read_streamfile(buf,offset,8,sf)!=8) return -1; + return get_64bitLE(buf); +} +static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) { + uint8_t buf[8]; + + if (read_streamfile(buf,offset,8,sf)!=8) return -1; + return get_64bitBE(buf); +} +static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) { + uint8_t buf[1]; + + if (read_streamfile(buf,offset,1,sf)!=1) return -1; + return buf[0]; +} + +/* alias of the above */ +static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); } +static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); } +static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); } +static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); } +static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); } +static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); } +static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); } +static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); } +static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); } +static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); } +static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); } +static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); } +static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); } +static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); } + +static inline float read_f32be(off_t offset, STREAMFILE* sf) { + uint8_t buf[4]; + + if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) + return -1; + return get_f32be(buf); +} +static inline float read_f32le(off_t offset, STREAMFILE* sf) { + uint8_t buf[4]; + + if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf)) + return -1; + return get_f32le(buf); +} + +#if 0 +// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring: +// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle; +// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant). +// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants +// so may result on bloatness? +// (from godbolt tests, test more real cases) + +/* collection of callbacks for quick access */ +typedef struct sf_reader { + int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32 + float (*read_f32)(off_t,STREAMFILE*); + /* ... */ +} sf_reader; + +static inline void sf_reader_init(sf_reader* r, int big_endian) { + memset(r, 0, sizeof(sf_reader)); + if (big_endian) { + r->read_s32 = read_s32be; + r->read_f32 = read_f32be; + } + else { + r->read_s32 = read_s32le; + r->read_f32 = read_f32le; + } +} + +/* sf_reader r; + * ... + * sf_reader_init(&r, big_endian); + * val = r.read_s32; //maybe r.s32? + */ +#endif +#if 0 //todo improve + test + simplify code (maybe not inline?) +static inline int read_s4h(off_t offset, STREAMFILE* sf) { + uint8_t byte = read_u8(offset, streamfile); + return get_nibble_signed(byte, 1); +} +static inline int read_u4h(off_t offset, STREAMFILE* sf) { + uint8_t byte = read_u8(offset, streamfile); + return (byte >> 4) & 0x0f; +} +static inline int read_s4l(off_t offset, STREAMFILE* sf) { + ... +} +static inline int read_u4l(off_t offset, STREAMFILE* sf) { + ... +} +static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; } +static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; } +//align32, align16, clamp16, etc +#endif + +/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */ +static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) { + return read_u32be(offset, sf) == get_id32be(s); +} + +static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) { + return read_u32le(offset, sf) == get_id32be(s); +} + +static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) { + return read_u64be(offset, sf) == get_id64be(s); +} + +#endif From 4b0387fb7a50252a699c9b4047450ec1742714a3 Mon Sep 17 00:00:00 2001 From: bnnm Date: Sun, 14 May 2023 23:20:20 +0200 Subject: [PATCH 08/13] cleanup: separate functions --- src/coding/ffmpeg_decoder_utils.c | 1 + src/libvgmstream.vcxproj | 5 + src/libvgmstream.vcxproj.filters | 15 ++ src/meta/adx.c | 1 + src/meta/ahx.c | 1 + src/meta/awb.c | 1 + src/meta/bnsf.c | 1 + src/meta/cpk.c | 1 + src/meta/csmp.c | 1 + src/meta/ea_eaac.c | 1 + src/meta/ea_schl.c | 1 + src/meta/encrypted.c | 2 + src/meta/fsb5_fev.c | 10 +- src/meta/fsb_encrypted.c | 1 + src/meta/gsp_gsb.c | 1 + src/meta/hca.c | 1 + src/meta/imuse.c | 1 + src/meta/nub.c | 15 +- src/meta/sbk.c | 11 +- src/meta/sgxd.c | 1 + src/meta/sxd.c | 1 + src/meta/txth.c | 1 + src/meta/txtp.c | 1 + src/meta/ubi_ckd.c | 1 + src/meta/ubi_hx.c | 1 + src/meta/vxn.c | 6 +- src/meta/wbk.c | 1 + src/meta/xau.c | 79 +++++----- src/meta/xvag.c | 6 +- src/meta/xwb_xsb.h | 1 + src/streamfile.c | 233 +----------------------------- src/streamfile.h | 23 --- src/util/chunks.c | 68 +++++++++ src/util/chunks.h | 12 ++ src/util/companion_files.c | 148 +++++++++++++++++++ src/util/companion_files.h | 16 ++ src/util/paths.c | 11 ++ src/util/paths.h | 17 +++ 38 files changed, 384 insertions(+), 314 deletions(-) create mode 100644 src/util/companion_files.c create mode 100644 src/util/companion_files.h create mode 100644 src/util/paths.c create mode 100644 src/util/paths.h diff --git a/src/coding/ffmpeg_decoder_utils.c b/src/coding/ffmpeg_decoder_utils.c index da8699e0..57113494 100644 --- a/src/coding/ffmpeg_decoder_utils.c +++ b/src/coding/ffmpeg_decoder_utils.c @@ -1,5 +1,6 @@ #include "coding.h" #include "../util/channel_mappings.h" +#include "../util/chunks.h" #ifdef VGM_USE_FFMPEG diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 31cf0f61..2a977e14 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -171,15 +171,18 @@ + + + @@ -736,11 +739,13 @@ + + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index aee5e93d..e9aa66ba 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -338,6 +338,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -356,6 +359,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -365,6 +371,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2029,6 +2038,9 @@ util\Source Files + + util\Source Files + util\Source Files @@ -2044,6 +2056,9 @@ util\Source Files + + util\Source Files + util\Source Files diff --git a/src/meta/adx.c b/src/meta/adx.c index 51fe4c14..2e709104 100644 --- a/src/meta/adx.c +++ b/src/meta/adx.c @@ -7,6 +7,7 @@ #include "adx_keys.h" #include "../coding/coding.h" #include "../util/cri_keys.h" +#include "../util/companion_files.h" #ifdef VGM_DEBUG_OUTPUT diff --git a/src/meta/ahx.c b/src/meta/ahx.c index e5c98fe7..cf3ebc7a 100644 --- a/src/meta/ahx.c +++ b/src/meta/ahx.c @@ -2,6 +2,7 @@ #include "../coding/coding.h" #include "ahx_keys.h" #include "../util/cri_keys.h" +#include "../util/companion_files.h" #ifdef VGM_USE_MPEG static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey); diff --git a/src/meta/awb.c b/src/meta/awb.c index 0210ae56..d21fd6a9 100644 --- a/src/meta/awb.c +++ b/src/meta/awb.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/companion_files.h" //typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type_t; diff --git a/src/meta/bnsf.c b/src/meta/bnsf.c index f12eb7c7..d07cfdb2 100644 --- a/src/meta/bnsf.c +++ b/src/meta/bnsf.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../util/chunks.h" +#include "../util/companion_files.h" #include "bnsf_keys.h" diff --git a/src/meta/cpk.c b/src/meta/cpk.c index 8ebe4a26..3d748734 100644 --- a/src/meta/cpk.c +++ b/src/meta/cpk.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../util/cri_utf.h" +#include "../util/companion_files.h" typedef enum { HCA, CWAV, ADX } cpk_type_t; diff --git a/src/meta/csmp.c b/src/meta/csmp.c index 2159879b..e60c2bb8 100644 --- a/src/meta/csmp.c +++ b/src/meta/csmp.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* CSMP - Retro Studios sample [Metroid Prime 3 (Wii)-sfx, Donkey Kong Country Returns (Wii)-sfx] */ diff --git a/src/meta/ea_eaac.c b/src/meta/ea_eaac.c index 314f1565..bee76931 100644 --- a/src/meta/ea_eaac.c +++ b/src/meta/ea_eaac.c @@ -3,6 +3,7 @@ #include "../layout/layout.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/companion_files.h" #include "ea_eaac_streamfile.h" /* EAAudioCore (aka SND10) formats, EA's current audio middleware */ diff --git a/src/meta/ea_schl.c b/src/meta/ea_schl.c index a4b23b24..eddd9abb 100644 --- a/src/meta/ea_schl.c +++ b/src/meta/ea_schl.c @@ -2,6 +2,7 @@ #include "../layout/layout.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/companion_files.h" #include "ea_schl_streamfile.h" /* header version */ diff --git a/src/meta/encrypted.c b/src/meta/encrypted.c index 62d06d8b..120fcb1c 100644 --- a/src/meta/encrypted.c +++ b/src/meta/encrypted.c @@ -1,5 +1,7 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/companion_files.h" +#include "../util/chunks.h" #include "ogg_vorbis_streamfile.h" #include "encrypted_bgm_streamfile.h" #include "encrypted_mc161_streamfile.h" diff --git a/src/meta/fsb5_fev.c b/src/meta/fsb5_fev.c index 80432a8f..6a59ae3d 100644 --- a/src/meta/fsb5_fev.c +++ b/src/meta/fsb5_fev.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" static int get_subsongs(STREAMFILE* sf, off_t fsb5_offset, size_t fsb5_size); @@ -16,13 +17,14 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) { /* checks */ + if (!is_id32be(0x00,sf, "RIFF")) + goto fail; + if (!is_id32be(0x08,sf, "FEV ")) + goto fail; + if (!check_extensions(sf, "bank")) goto fail; - if (read_u32be(0x00,sf) != 0x52494646) /* "RIFF" */ - goto fail; - if (read_u32be(0x08,sf) != 0x46455620) /* "FEV " */ - goto fail; version = read_u32le(0x14,sf); /* newer FEV have some kind of sub-version at 0x18 */ /* .fev is an event format referencing various external .fsb, but FMOD can bake .fev and .fsb to diff --git a/src/meta/fsb_encrypted.c b/src/meta/fsb_encrypted.c index 3c974ae7..9bcd1940 100644 --- a/src/meta/fsb_encrypted.c +++ b/src/meta/fsb_encrypted.c @@ -1,4 +1,5 @@ #include "meta.h" +#include "../util/companion_files.h" #include "fsb_keys.h" #include "fsb_encrypted_streamfile.h" diff --git a/src/meta/gsp_gsb.c b/src/meta/gsp_gsb.c index d0d2174e..15ec2bcb 100644 --- a/src/meta/gsp_gsb.c +++ b/src/meta/gsp_gsb.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../layout/layout.h" #include "../coding/coding.h" +#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) { diff --git a/src/meta/hca.c b/src/meta/hca.c index 92b5158c..294d71f9 100644 --- a/src/meta/hca.c +++ b/src/meta/hca.c @@ -3,6 +3,7 @@ #include "../coding/coding.h" #include "../coding/hca_decoder_clhca.h" #include "../util/channel_mappings.h" +#include "../util/companion_files.h" #ifdef VGM_DEBUG_OUTPUT //#define HCA_BRUTEFORCE diff --git a/src/meta/imuse.c b/src/meta/imuse.c index 112e0a46..c974a717 100644 --- a/src/meta/imuse.c +++ b/src/meta/imuse.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* LucasArts iMUSE (Interactive Music Streaming Engine) formats */ diff --git a/src/meta/nub.c b/src/meta/nub.c index 3499cc30..cec97abc 100644 --- a/src/meta/nub.c +++ b/src/meta/nub.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/chunks.h" static void load_name(char* name, size_t name_size, STREAMFILE* sf, int big_endian, int total_subsongs, int target_subsong); @@ -20,17 +21,17 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) { /* checks */ - /* .nub: standard - * .nub2: rare [iDOLM@STER - Gravure For You (PS3)] */ - if (!check_extensions(sf, "nub,nub2")) - goto fail; - - version = read_32bitBE(0x00,sf); + version = read_u32be(0x00,sf); if (version != 0x00020000 && /* v2.0 (rare, ex. Ridge Race 6 (X360)) */ version != 0x00020100 && /* v2.1 (common) */ version != 0x01020100) /* same but LE (seen in PSP/PC games, except PS4) */ goto fail; - if (read_32bitBE(0x04,sf) != 0x00000000) /* null */ + if (read_u32be(0x04,sf) != 0x00000000) /* null */ + goto fail; + + /* .nub: standard + * .nub2: rare [iDOLM@STER - Gravure For You (PS3)] */ + if (!check_extensions(sf, "nub,nub2")) goto fail; /* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */ diff --git a/src/meta/sbk.c b/src/meta/sbk.c index 99531388..41c1483c 100644 --- a/src/meta/sbk.c +++ b/src/meta/sbk.c @@ -1,5 +1,7 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" + /* .SBK - from Addiction Pinball (PC) */ VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) { @@ -11,13 +13,12 @@ VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) { int target_subsong = sf->stream_index, total_subsongs, loop_flag, is_streamed; /* checks */ - if (!check_extensions(sf, "sbk")) + if (!is_id32be(0x00,sf, "RIFF")) + goto fail; + if (!is_id32be(0x08,sf, "SBNK")) goto fail; - /* check header */ - if (read_u32be(0x00, sf) != 0x52494646) /* "RIFF" */ - goto fail; - if (read_u32be(0x08, sf) != 0x53424E4B) /* "SBNK" */ + if (!check_extensions(sf, "sbk")) goto fail; if (!find_chunk_le(sf, 0x57415649, 0x0c, 0, &table_offset, &table_size)) /* "WAVI" */ diff --git a/src/meta/sgxd.c b/src/meta/sgxd.c index 8b6c8fd5..c16c53a2 100644 --- a/src/meta/sgxd.c +++ b/src/meta/sgxd.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */ diff --git a/src/meta/sxd.c b/src/meta/sxd.c index 841a695d..4cbd97fc 100644 --- a/src/meta/sxd.c +++ b/src/meta/sxd.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ diff --git a/src/meta/txth.c b/src/meta/txth.c index e261a3f9..1627c050 100644 --- a/src/meta/txth.c +++ b/src/meta/txth.c @@ -4,6 +4,7 @@ #include "txth_streamfile.h" #include "../util/text_reader.h" #include "../util/endianness.h" +#include "../util/paths.h" #define TXT_LINE_MAX 2048 /* probably ~1000 would be ok */ #define TXT_LINE_KEY_MAX 128 diff --git a/src/meta/txtp.c b/src/meta/txtp.c index e6d382b1..9db9a49a 100644 --- a/src/meta/txtp.c +++ b/src/meta/txtp.c @@ -4,6 +4,7 @@ #include "../base/mixing.h" #include "../base/plugins.h" #include "../util/text_reader.h" +#include "../util/paths.h" #include diff --git a/src/meta/ubi_ckd.c b/src/meta/ubi_ckd.c index 945f8416..dabcde55 100644 --- a/src/meta/ubi_ckd.c +++ b/src/meta/ubi_ckd.c @@ -1,6 +1,7 @@ #include "meta.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/chunks.h" typedef enum { MSADPCM, DSP, MP3, XMA2 } ckd_codec; diff --git a/src/meta/ubi_hx.c b/src/meta/ubi_hx.c index 1600c10a..76abcca4 100644 --- a/src/meta/ubi_hx.c +++ b/src/meta/ubi_hx.c @@ -2,6 +2,7 @@ #include "../layout/layout.h" #include "../coding/coding.h" #include "../util/endianness.h" +#include "../util/chunks.h" typedef enum { PCM, UBI, PSX, DSP, XIMA, ATRAC3, XMA2, MP3, SILENCE } ubi_hx_codec; diff --git a/src/meta/vxn.c b/src/meta/vxn.c index a41d541b..929081cd 100644 --- a/src/meta/vxn.c +++ b/src/meta/vxn.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" /* VXN - from Gameloft mobile games */ @@ -11,11 +12,12 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) { int total_subsongs, target_subsong = sf->stream_index; /* checks */ + if (!is_id32be(0x00,sf, "VoxN")) + goto fail; + if (!check_extensions(sf,"vxn")) goto fail; - if (!is_id32be(0x00,sf, "VoxN")) - goto fail; /* 0x04: chunk size */ /* 0x08: ASCII version? ("0.0.1") */ if (read_u32le(0x10,sf) != get_streamfile_size(sf)) diff --git a/src/meta/wbk.c b/src/meta/wbk.c index 884c2925..44a8dcfa 100644 --- a/src/meta/wbk.c +++ b/src/meta/wbk.c @@ -1,5 +1,6 @@ #include "meta.h" #include "../coding/coding.h" +#include "../util/chunks.h" //#include /* .WBK - seen in some Treyarch games [Spider-Man 2, Ultimate Spider-Man, Call of Duty 2: Big Red One] */ diff --git a/src/meta/xau.c b/src/meta/xau.c index ab663dc8..3b758bbf 100644 --- a/src/meta/xau.c +++ b/src/meta/xau.c @@ -1,64 +1,65 @@ #include "meta.h" #include "../util.h" #include "../coding/coding.h" +#include "../util/chunks.h" -/* XAU - XPEC Entertainment sound format (Beat Down PS2/Xbox, Spectral Force Chronicle [SLPM-65967]) */ -VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) { - VGMSTREAM * vgmstream = NULL; +/* XAU - XPEC Entertainment sound format [Beat Down (PS2/Xbox), Spectral Force Chronicle (PS2)] */ +VGMSTREAM* init_vgmstream_xau(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; off_t start_offset; - int loop_flag, channel_count, type, loop_start, loop_end; + int loop_flag, channels, type, loop_start, loop_end; /* check extension */ - if (!check_extensions(streamFile, "xau")) - goto fail; - - /* check header */ - if (read_32bitBE(0x00,streamFile) != 0x58415500) /* "XAU\0" "*/ + if (!is_id32be(0x00,sf, "XAU\0")) goto fail; - if (read_32bitLE(0x08,streamFile) != 0x40) /* header start */ + + if (!check_extensions(sf, "xau")) + goto fail; + + if (read_32bitLE(0x08,sf) != 0x40) /* header start */ goto fail; /* 0x04: version? (0x100) */ - type = read_32bitBE(0x0c, streamFile); - loop_start = read_32bitLE(0x10, streamFile); - loop_end = read_32bitLE(0x14, streamFile); - loop_flag = (loop_end > 0); + type = read_32bitBE(0x0c, sf); + loop_start = read_32bitLE(0x10, sf); + loop_end = read_32bitLE(0x14, sf); + loop_flag = (loop_end > 0); - channel_count = read_8bit(0x18,streamFile); + channels = read_8bit(0x18,sf); - /* build the VGMSTREAM */ - vgmstream = allocate_vgmstream(channel_count, loop_flag); + /* build the VGMSTREAM */ + vgmstream = allocate_vgmstream(channels, loop_flag); if (!vgmstream) goto fail; - vgmstream->channels = channel_count; + vgmstream->channels = channels; vgmstream->meta_type = meta_XAU; - /* miniheader over a common header with some tweaks, so we'll simplify parsing */ - switch(type) { - case 0x50533200: /* "PS2\0" */ - if (read_32bitBE(0x40,streamFile) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */ + /* miniheader over a common header with some tweaks, so we'll simplify parsing */ + switch(type) { + case 0x50533200: /* "PS2\0" */ + if (read_32bitBE(0x40,sf) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */ - start_offset = 0x800; - vgmstream->sample_rate = read_32bitBE(0x50, streamFile); - vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,streamFile) * channel_count, channel_count); + start_offset = 0x800; + vgmstream->sample_rate = read_32bitBE(0x50, sf); + vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,sf) * channels, channels); vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; vgmstream->coding_type = coding_PSX; vgmstream->layout_type = layout_interleave; - vgmstream->interleave_block_size = 0x8000; - break; + vgmstream->interleave_block_size = 0x8000; + break; - case 0x58420000: /* "XB\0\0" */ - if (read_32bitBE(0x40,streamFile) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */ + case 0x58420000: /* "XB\0\0" */ + if (read_32bitBE(0x40,sf) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */ - /* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */ - if (!find_chunk_le(streamFile, 0x64617461, 0x4c, 0, &start_offset, NULL) ) - goto fail; + /* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */ + if (!find_chunk_le(sf, 0x64617461, 0x4c, 0, &start_offset, NULL) ) + goto fail; - vgmstream->sample_rate = read_32bitLE(0x58, streamFile); - vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count); + vgmstream->sample_rate = read_32bitLE(0x58, sf); + vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, sf), channels); vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; @@ -66,13 +67,13 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) { vgmstream->layout_type = layout_none; break; - default: - goto fail; - } + default: + goto fail; + } - if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) - goto fail; + if (!vgmstream_open_stream(vgmstream,sf,start_offset)) + goto fail; return vgmstream; diff --git a/src/meta/xvag.c b/src/meta/xvag.c index c7a36505..205579b2 100644 --- a/src/meta/xvag.c +++ b/src/meta/xvag.c @@ -2,6 +2,7 @@ #include "../coding/coding.h" #include "../layout/layout.h" #include "xvag_streamfile.h" +#include "../util/chunks.h" typedef struct { @@ -41,12 +42,13 @@ VGMSTREAM* init_vgmstream_xvag(STREAMFILE* sf) { /* checks */ + if (!is_id32be(0x00,sf, "XVAG")) + goto fail; + /* .xvag: standard * (extensionless): The Last of Us (PS3) speech files */ if (!check_extensions(sf,"xvag,")) goto fail; - if (!is_id32be(0x00,sf, "XVAG")) - goto fail; /* endian flag (XVAGs of the same game can use BE or LE, usually when reusing from other platforms) */ xvag.big_endian = read_8bit(0x08,sf) & 0x01; diff --git a/src/meta/xwb_xsb.h b/src/meta/xwb_xsb.h index e2b8b5f1..ab00b067 100644 --- a/src/meta/xwb_xsb.h +++ b/src/meta/xwb_xsb.h @@ -1,6 +1,7 @@ #ifndef _XWB_XSB_H_ #define _XWB_XSB_H_ #include "meta.h" +#include "../util/companion_files.h" #define XSB_XACT1_0_MAX 5 /* Unreal Championship (Xbox) */ #define XSB_XACT1_1_MAX 8 /* Die Hard: Vendetta (Xbox) */ diff --git a/src/streamfile.c b/src/streamfile.c index bfdabcbb..7fb25eff 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -2,6 +2,7 @@ #include "util.h" #include "vgmstream.h" #include "util/reader_sf.h" +#include "util/paths.h" #include /* for dup/fdopen in some systems */ @@ -9,15 +10,6 @@ #include #endif -//TODO: move -#ifndef DIR_SEPARATOR - #if defined (_WIN32) || defined (WIN32) - #define DIR_SEPARATOR '\\' - #else - #define DIR_SEPARATOR '/' - #endif -#endif - /* For (rarely needed) +2GB file support we use fseek64/ftell64. Those are usually available * but may depend on compiler. * - MSVC: +VS2008 should work @@ -1205,162 +1197,6 @@ size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* /* ************************************************************************* */ -size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { - char keyname[PATH_LIMIT]; - char filename[PATH_LIMIT]; - const char *path, *ext; - STREAMFILE* sf_key = NULL; - size_t keysize; - - get_streamfile_name(sf, filename, sizeof(filename)); - - if (strlen(filename)+4 > sizeof(keyname)) goto fail; - - /* try to open a keyfile using variations */ - { - ext = strrchr(filename,'.'); - if (ext!=NULL) ext = ext+1; - - path = strrchr(filename, DIR_SEPARATOR); - if (path!=NULL) path = path+1; - - /* "(name.ext)key" */ - strcpy(keyname, filename); - strcat(keyname, "key"); - sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); - if (sf_key) goto found; - - /* "(name.ext)KEY" */ - /* - strcpy(keyname+strlen(keyname)-3,"KEY"); - sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); - if (sf_key) goto found; - */ - - - /* "(.ext)key" */ - if (path) { - strcpy(keyname, filename); - keyname[path-filename] = '\0'; - strcat(keyname, "."); - } else { - strcpy(keyname, "."); - } - if (ext) strcat(keyname, ext); - strcat(keyname, "key"); - sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); - if (sf_key) goto found; - - /* "(.ext)KEY" */ - /* - strcpy(keyname+strlen(keyname)-3,"KEY"); - sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); - if (sf_key) goto found; - */ - - goto fail; - } - -found: - keysize = get_streamfile_size(sf_key); - if (keysize > buf_size) goto fail; - - if (read_streamfile(buf, 0, keysize, sf_key) != keysize) - goto fail; - - close_streamfile(sf_key); - return keysize; - -fail: - close_streamfile(sf_key); - return 0; -} - -STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { - return read_filemap_file_pos(sf, file_num, NULL); -} - -STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) { - char filename[PATH_LIMIT]; - off_t txt_offset, file_size; - STREAMFILE* sf_map = NULL; - int file_pos = 0; - - sf_map = open_streamfile_by_filename(sf, ".txtm"); - if (!sf_map) goto fail; - - get_streamfile_filename(sf, filename, sizeof(filename)); - - txt_offset = read_bom(sf_map); - file_size = get_streamfile_size(sf_map); - - /* read lines and find target filename, format is (filename): value1, ... valueN */ - while (txt_offset < file_size) { - char line[0x2000]; - char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 }; - int ok, bytes_read, line_ok; - - bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok); - if (!line_ok) goto fail; - - txt_offset += bytes_read; - - /* get key/val (ignores lead/trailing spaces, stops at comment/separator) */ - ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val); - if (ok != 2) { /* ignore line if no key=val (comment or garbage) */ - /* better way? */ - if (strcmp(line, "#@reset-pos") == 0) { - file_pos = 0; - } - continue; - } - - if (strcmp(key, filename) == 0) { - int n; - char subval[PATH_LIMIT]; - const char* current = val; - int i; - - for (i = 0; i <= file_num; i++) { - if (current[0] == '\0') - goto fail; - - ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n); - if (ok != 1) - goto fail; - - if (i == file_num) { - if (p_pos) *p_pos = file_pos; - - close_streamfile(sf_map); - return open_streamfile_by_filename(sf, subval); - } - - current += n; - if (current[0] == ',') - current++; - } - } - file_pos++; - } - -fail: - close_streamfile(sf_map); - return NULL; -} - -void fix_dir_separators(char* filename) { - char c; - int i = 0; - while ((c = filename[i]) != '\0') { - if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\')) - filename[i] = DIR_SEPARATOR; - i++; - } -} - -/* ************************************************************************* */ - int check_extensions(STREAMFILE* sf, const char* cmp_exts) { char filename[PATH_LIMIT]; const char* ext = NULL; @@ -1393,73 +1229,6 @@ int check_extensions(STREAMFILE* sf, const char* cmp_exts) { /* ************************************************************************* */ -/** - * Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size. - * Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF). - * The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt "). - * "full_chunk_size" signals chunk_size includes 4+4+data. - * - * returns 0 on failure - */ -static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) { - int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE; - int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE; - off_t offset, max_offset; - size_t file_size = get_streamfile_size(sf); - - if (max_size == 0) - max_size = file_size; - - offset = start_offset; - max_offset = offset + max_size; - if (max_offset > file_size) - max_offset = file_size; - - - /* read chunks */ - while (offset < max_offset) { - uint32_t chunk_type = read_32bit_type(offset + 0x00,sf); - uint32_t chunk_size = read_32bit_size(offset + 0x04,sf); - - if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF) - return 0; - - if (chunk_type == chunk_id) { - if (out_chunk_offset) *out_chunk_offset = offset + 0x08; - if (out_chunk_size) *out_chunk_size = chunk_size; - return 1; - } - - /* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */ - if (chunk_size == 0 && zero_size_end) - return 0; - - offset += full_chunk_size ? chunk_size : 0x08 + chunk_size; - } - - return 0; -} -int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { - return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0); -} -int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { - return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0); -} -int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) { - return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end); -} -int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) { - return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0); -} -int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) { - return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0); -} -int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) { - return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 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); diff --git a/src/streamfile.h b/src/streamfile.h index cd2402fb..119bea94 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -178,34 +178,11 @@ size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* s size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); -/* Opens a file containing decryption keys and copies to buffer. - * Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames. - * returns size of key if found and copied */ -size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf); - -/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match - * then loads the associated companion file if one is found */ -STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num); -STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos); - - -/* hack to allow relative paths in various OSs */ -void fix_dir_separators(char* filename); /* 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); -/* chunk-style file helpers */ -int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size); -int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size); -int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end); -/* find a RIFF-style chunk (with chunk_size not including id and size) */ -int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size); -int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size); -/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */ -int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian); - /* filename helpers */ void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size); void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size); diff --git a/src/util/chunks.c b/src/util/chunks.c index 7bdb2ad0..bfdd4984 100644 --- a/src/util/chunks.c +++ b/src/util/chunks.c @@ -33,3 +33,71 @@ int next_chunk(chunk_t* chunk, STREAMFILE* sf) { /* more chunks remain */ return 1; } + + +/* ************************************************************************* */ + +/** + * Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size. + * Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF). + * The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt "). + * "full_chunk_size" signals chunk_size includes 4+4+data. + * + * returns 0 on failure + */ +static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) { + int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE; + int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE; + off_t offset, max_offset; + size_t file_size = get_streamfile_size(sf); + + if (max_size == 0) + max_size = file_size; + + offset = start_offset; + max_offset = offset + max_size; + if (max_offset > file_size) + max_offset = file_size; + + + /* read chunks */ + while (offset < max_offset) { + uint32_t chunk_type = read_32bit_type(offset + 0x00,sf); + uint32_t chunk_size = read_32bit_size(offset + 0x04,sf); + + if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF) + return 0; + + if (chunk_type == chunk_id) { + if (out_chunk_offset) *out_chunk_offset = offset + 0x08; + if (out_chunk_size) *out_chunk_size = chunk_size; + return 1; + } + + /* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */ + if (chunk_size == 0 && zero_size_end) + return 0; + + offset += full_chunk_size ? chunk_size : 0x08 + chunk_size; + } + + return 0; +} +int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0); +} +int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0); +} +int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) { + return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end); +} +int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0); +} +int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) { + return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0); +} +int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) { + return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 0); +} diff --git a/src/util/chunks.h b/src/util/chunks.h index f091cecb..7373d33d 100644 --- a/src/util/chunks.h +++ b/src/util/chunks.h @@ -26,4 +26,16 @@ enum { }; #endif + +/* chunk-style file helpers (the above is more performant, this is mainly for quick checks) */ +int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size); +int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size); +int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end); +/* find a RIFF-style chunk (with chunk_size not including id and size) */ +int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size); +int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size); +/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */ +int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian); + + #endif diff --git a/src/util/companion_files.c b/src/util/companion_files.c new file mode 100644 index 00000000..9a3d02a4 --- /dev/null +++ b/src/util/companion_files.c @@ -0,0 +1,148 @@ +#include "companion_files.h" +#include "paths.h" +#include "../vgmstream.h" + + +size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { + char keyname[PATH_LIMIT]; + char filename[PATH_LIMIT]; + const char *path, *ext; + STREAMFILE* sf_key = NULL; + size_t keysize; + + get_streamfile_name(sf, filename, sizeof(filename)); + + if (strlen(filename)+4 > sizeof(keyname)) goto fail; + + /* try to open a keyfile using variations */ + { + ext = strrchr(filename,'.'); + if (ext!=NULL) ext = ext+1; + + path = strrchr(filename, DIR_SEPARATOR); + if (path!=NULL) path = path+1; + + /* "(name.ext)key" */ + strcpy(keyname, filename); + strcat(keyname, "key"); + sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (sf_key) goto found; + + /* "(name.ext)KEY" */ + /* + strcpy(keyname+strlen(keyname)-3,"KEY"); + sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (sf_key) goto found; + */ + + + /* "(.ext)key" */ + if (path) { + strcpy(keyname, filename); + keyname[path-filename] = '\0'; + strcat(keyname, "."); + } else { + strcpy(keyname, "."); + } + if (ext) strcat(keyname, ext); + strcat(keyname, "key"); + sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (sf_key) goto found; + + /* "(.ext)KEY" */ + /* + strcpy(keyname+strlen(keyname)-3,"KEY"); + sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE); + if (sf_key) goto found; + */ + + goto fail; + } + +found: + keysize = get_streamfile_size(sf_key); + if (keysize > buf_size) goto fail; + + if (read_streamfile(buf, 0, keysize, sf_key) != keysize) + goto fail; + + close_streamfile(sf_key); + return keysize; + +fail: + close_streamfile(sf_key); + return 0; +} + +STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) { + return read_filemap_file_pos(sf, file_num, NULL); +} + +STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) { + char filename[PATH_LIMIT]; + off_t txt_offset, file_size; + STREAMFILE* sf_map = NULL; + int file_pos = 0; + + sf_map = open_streamfile_by_filename(sf, ".txtm"); + if (!sf_map) goto fail; + + get_streamfile_filename(sf, filename, sizeof(filename)); + + txt_offset = read_bom(sf_map); + file_size = get_streamfile_size(sf_map); + + /* read lines and find target filename, format is (filename): value1, ... valueN */ + while (txt_offset < file_size) { + char line[0x2000]; + char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 }; + int ok, bytes_read, line_ok; + + bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok); + if (!line_ok) goto fail; + + txt_offset += bytes_read; + + /* get key/val (ignores lead/trailing spaces, stops at comment/separator) */ + ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val); + if (ok != 2) { /* ignore line if no key=val (comment or garbage) */ + /* better way? */ + if (strcmp(line, "#@reset-pos") == 0) { + file_pos = 0; + } + continue; + } + + if (strcmp(key, filename) == 0) { + int n; + char subval[PATH_LIMIT]; + const char* current = val; + int i; + + for (i = 0; i <= file_num; i++) { + if (current[0] == '\0') + goto fail; + + ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n); + if (ok != 1) + goto fail; + + if (i == file_num) { + if (p_pos) *p_pos = file_pos; + + close_streamfile(sf_map); + return open_streamfile_by_filename(sf, subval); + } + + current += n; + if (current[0] == ',') + current++; + } + } + file_pos++; + } + +fail: + close_streamfile(sf_map); + return NULL; +} diff --git a/src/util/companion_files.h b/src/util/companion_files.h new file mode 100644 index 00000000..c07a7a86 --- /dev/null +++ b/src/util/companion_files.h @@ -0,0 +1,16 @@ +#ifndef _COMPANION_FILES_H +#define _COMPANION_FILES_H + +#include "../streamfile.h" + +/* Opens a file containing decryption keys and copies to buffer. + * Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames. + * returns size of key if found and copied */ +size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf); + +/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match + * then loads the associated companion file if one is found */ +STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num); +STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos); + +#endif diff --git a/src/util/paths.c b/src/util/paths.c new file mode 100644 index 00000000..8c1140c7 --- /dev/null +++ b/src/util/paths.c @@ -0,0 +1,11 @@ +#include "paths.h" + +void fix_dir_separators(char* filename) { + char c; + int i = 0; + while ((c = filename[i]) != '\0') { + if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\')) + filename[i] = DIR_SEPARATOR; + i++; + } +} diff --git a/src/util/paths.h b/src/util/paths.h new file mode 100644 index 00000000..72af5712 --- /dev/null +++ b/src/util/paths.h @@ -0,0 +1,17 @@ +#ifndef _PATHS_H +#define _PATHS_H + +#ifndef DIR_SEPARATOR + #if defined (_WIN32) || defined (WIN32) + #define DIR_SEPARATOR '\\' + #else + #define DIR_SEPARATOR '/' + #endif +#endif + +/* hack to allow relative paths in various OSs */ +void fix_dir_separators(char* filename); + +//const char* filename_extension(const char* pathname); + +#endif From 6d1a0e28950c2cb7a3232049e1fc61fa13ae7f3f Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 15 May 2023 12:04:12 +0200 Subject: [PATCH 09/13] cleanup: separate functions --- src/base/plugins.c | 1 + src/libvgmstream.vcxproj | 3 +- src/libvgmstream.vcxproj.filters | 5 +- src/meta/meta.h | 1 + src/streamfile.c | 117 ------------------------ src/streamfile.h | 16 ---- src/util/companion_files.c | 1 + src/util/reader.c | 149 +++++++++++++++++++++++++++++++ src/util/reader_put.c | 29 ------ src/util/reader_text.h | 21 +++++ 10 files changed, 179 insertions(+), 164 deletions(-) create mode 100644 src/util/reader.c delete mode 100644 src/util/reader_put.c create mode 100644 src/util/reader_text.h diff --git a/src/base/plugins.c b/src/base/plugins.c index 27d9193d..22b62a4f 100644 --- a/src/base/plugins.c +++ b/src/base/plugins.c @@ -1,6 +1,7 @@ #include "../vgmstream.h" #include "../util/log.h" #include "../util/reader_sf.h" +#include "../util/reader_text.h" #include "plugins.h" #include "mixing.h" diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 2a977e14..ff8be911 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -183,6 +183,7 @@ + @@ -746,7 +747,7 @@ - + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index e9aa66ba..493d257a 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -374,6 +374,9 @@ util\Header Files + + util\Header Files + util\Header Files @@ -2059,7 +2062,7 @@ util\Source Files - + util\Source Files diff --git a/src/meta/meta.h b/src/meta/meta.h index 2df93035..c0d9c08c 100644 --- a/src/meta/meta.h +++ b/src/meta/meta.h @@ -3,6 +3,7 @@ #include "../vgmstream.h" #include "../util/reader_sf.h" +#include "../util/reader_text.h" typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf); diff --git a/src/streamfile.c b/src/streamfile.c index 7fb25eff..77ec2bf8 100644 --- a/src/streamfile.c +++ b/src/streamfile.c @@ -1078,123 +1078,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) { return sf->open(sf, pathname, buffer_size); } -/* **************************************************** */ - -size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) { - int i; - off_t file_size = get_streamfile_size(sf); - int extra_bytes = 0; /* how many bytes over those put in the buffer were read */ - - if (p_line_ok) *p_line_ok = 0; - - for (i = 0; i < buf_size-1 && offset+i < file_size; i++) { - char in_char = read_8bit(offset+i, sf); - /* check for end of line */ - if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ - extra_bytes = 2; - if (p_line_ok) *p_line_ok = 1; - break; - } - else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ - extra_bytes = 1; - if (p_line_ok) *p_line_ok = 1; - break; - } - - buf[i] = in_char; - } - - buf[i] = '\0'; - - /* did we fill the buffer? */ - if (i == buf_size) { - char in_char = read_8bit(offset+i, sf); - /* did the bytes we missed just happen to be the end of the line? */ - if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ - extra_bytes = 2; - if (p_line_ok) *p_line_ok = 1; - } - else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ - extra_bytes = 1; - if (p_line_ok) *p_line_ok = 1; - } - } - - /* did we hit the file end? */ - if (offset+i == file_size) { - /* then we did in fact finish reading the last line */ - if (p_line_ok) *p_line_ok = 1; - } - - return i + extra_bytes; -} - -size_t read_bom(STREAMFILE* sf) { - if (read_u16le(0x00, sf) == 0xFFFE || - read_u16le(0x00, sf) == 0xFEFF) { - return 0x02; - } - - if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) { - return 0x03; - } - - return 0x00; -} - -size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - size_t pos; - - for (pos = 0; pos < buf_size; pos++) { - uint8_t byte = read_u8(offset + pos, sf); - char c = (char)byte; - if (buf) buf[pos] = c; - if (c == '\0') - return pos; - if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ - if (buf) buf[pos] = '\0'; - return buf_size; - } - /* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */ - if (byte < 0x20 || byte > 0xF0) - goto fail; - } - -fail: - if (buf) buf[0] = '\0'; - return 0; -} - -size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) { - size_t pos, offpos; - uint16_t (*read_u16)(off_t,STREAMFILE*) = big_endian ? read_u16be : read_u16le; - - - for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) { - char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */ - if (buf) buf[pos] = c; - if (c == '\0') - return pos; - if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ - if (buf) buf[pos] = '\0'; - return buf_size; - } - if (c < 0x20 || (uint8_t)c > 0xA5) - goto fail; - } - -fail: - if (buf) buf[0] = '\0'; - return 0; -} - -size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - return read_string_utf16(buf, buf_size, offset, sf, 0); -} -size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { - return read_string_utf16(buf, buf_size, offset, sf, 1); -} - /* ************************************************************************* */ int check_extensions(STREAMFILE* sf, const char* cmp_exts) { diff --git a/src/streamfile.h b/src/streamfile.h index 119bea94..476372c3 100644 --- a/src/streamfile.h +++ b/src/streamfile.h @@ -163,22 +163,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) { /* various STREAMFILE helpers functions */ -/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated - * and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length. - * p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */ -size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok); - -/* skip BOM if needed */ -size_t read_bom(STREAMFILE* sf); - -/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */ -size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); -/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */ -size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian); -size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); -size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); - - /* 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); diff --git a/src/util/companion_files.c b/src/util/companion_files.c index 9a3d02a4..253b18e3 100644 --- a/src/util/companion_files.c +++ b/src/util/companion_files.c @@ -1,6 +1,7 @@ #include "companion_files.h" #include "paths.h" #include "../vgmstream.h" +#include "../util/reader_text.h" size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) { diff --git a/src/util/reader.c b/src/util/reader.c new file mode 100644 index 00000000..8b4a2fe8 --- /dev/null +++ b/src/util/reader.c @@ -0,0 +1,149 @@ +#include "reader_put.h" +#include "reader_text.h" +#include "reader_sf.h" +#include "endianness.h" + +void put_8bit(uint8_t* buf, int8_t i) { + buf[0] = i; +} + +void put_16bitLE(uint8_t* buf, int16_t i) { + buf[0] = (i & 0xFF); + buf[1] = i >> 8; +} + +void put_32bitLE(uint8_t* buf, int32_t i) { + buf[0] = (uint8_t)(i & 0xFF); + buf[1] = (uint8_t)((i >> 8) & 0xFF); + buf[2] = (uint8_t)((i >> 16) & 0xFF); + buf[3] = (uint8_t)((i >> 24) & 0xFF); +} + +void put_16bitBE(uint8_t* buf, int16_t i) { + buf[0] = i >> 8; + buf[1] = (i & 0xFF); +} + +void put_32bitBE(uint8_t* buf, int32_t i) { + buf[0] = (uint8_t)((i >> 24) & 0xFF); + buf[1] = (uint8_t)((i >> 16) & 0xFF); + buf[2] = (uint8_t)((i >> 8) & 0xFF); + buf[3] = (uint8_t)(i & 0xFF); +} + +/* **************************************************** */ + +size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) { + int i; + off_t file_size = get_streamfile_size(sf); + int extra_bytes = 0; /* how many bytes over those put in the buffer were read */ + + if (p_line_ok) *p_line_ok = 0; + + for (i = 0; i < buf_size-1 && offset+i < file_size; i++) { + char in_char = read_8bit(offset+i, sf); + /* check for end of line */ + if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ + extra_bytes = 2; + if (p_line_ok) *p_line_ok = 1; + break; + } + else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ + extra_bytes = 1; + if (p_line_ok) *p_line_ok = 1; + break; + } + + buf[i] = in_char; + } + + buf[i] = '\0'; + + /* did we fill the buffer? */ + if (i == buf_size) { + char in_char = read_8bit(offset+i, sf); + /* did the bytes we missed just happen to be the end of the line? */ + if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */ + extra_bytes = 2; + if (p_line_ok) *p_line_ok = 1; + } + else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */ + extra_bytes = 1; + if (p_line_ok) *p_line_ok = 1; + } + } + + /* did we hit the file end? */ + if (offset+i == file_size) { + /* then we did in fact finish reading the last line */ + if (p_line_ok) *p_line_ok = 1; + } + + return i + extra_bytes; +} + +size_t read_bom(STREAMFILE* sf) { + if (read_u16le(0x00, sf) == 0xFFFE || + read_u16le(0x00, sf) == 0xFEFF) { + return 0x02; + } + + if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) { + return 0x03; + } + + return 0x00; +} + +size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + size_t pos; + + for (pos = 0; pos < buf_size; pos++) { + uint8_t byte = read_u8(offset + pos, sf); + char c = (char)byte; + if (buf) buf[pos] = c; + if (c == '\0') + return pos; + if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ + if (buf) buf[pos] = '\0'; + return buf_size; + } + /* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */ + if (byte < 0x20 || byte > 0xF0) + goto fail; + } + +fail: + if (buf) buf[0] = '\0'; + return 0; +} + +size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) { + size_t pos, offpos; + read_u16_t read_u16 = big_endian ? read_u16be : read_u16le; + + + for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) { + char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */ + if (buf) buf[pos] = c; + if (c == '\0') + return pos; + if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */ + if (buf) buf[pos] = '\0'; + return buf_size; + } + if (c < 0x20 || (uint8_t)c > 0xA5) + goto fail; + } + +fail: + if (buf) buf[0] = '\0'; + return 0; +} + +size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + return read_string_utf16(buf, buf_size, offset, sf, 0); +} +size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) { + return read_string_utf16(buf, buf_size, offset, sf, 1); +} diff --git a/src/util/reader_put.c b/src/util/reader_put.c deleted file mode 100644 index ed04f154..00000000 --- a/src/util/reader_put.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "reader_put.h" - -void put_8bit(uint8_t * buf, int8_t i) { - buf[0] = i; -} - -void put_16bitLE(uint8_t * buf, int16_t i) { - buf[0] = (i & 0xFF); - buf[1] = i >> 8; -} - -void put_32bitLE(uint8_t * buf, int32_t i) { - buf[0] = (uint8_t)(i & 0xFF); - buf[1] = (uint8_t)((i >> 8) & 0xFF); - buf[2] = (uint8_t)((i >> 16) & 0xFF); - buf[3] = (uint8_t)((i >> 24) & 0xFF); -} - -void put_16bitBE(uint8_t * buf, int16_t i) { - buf[0] = i >> 8; - buf[1] = (i & 0xFF); -} - -void put_32bitBE(uint8_t * buf, int32_t i) { - buf[0] = (uint8_t)((i >> 24) & 0xFF); - buf[1] = (uint8_t)((i >> 16) & 0xFF); - buf[2] = (uint8_t)((i >> 8) & 0xFF); - buf[3] = (uint8_t)(i & 0xFF); -} diff --git a/src/util/reader_text.h b/src/util/reader_text.h new file mode 100644 index 00000000..f18b2092 --- /dev/null +++ b/src/util/reader_text.h @@ -0,0 +1,21 @@ +#ifndef _READER_TEXT_H +#define _READER_TEXT_H +#include "../streamfile.h" + + +/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated + * and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length. + * p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */ +size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok); + +/* skip BOM if needed */ +size_t read_bom(STREAMFILE* sf); + +/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */ +size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); +/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */ +size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian); +size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); +size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf); + +#endif From 4e5631e6308091a3e38571c28a5c24fa0d88fd05 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 15 May 2023 15:30:21 +0200 Subject: [PATCH 10/13] cleanup: move bitreader and tweaks --- src/coding/vorbis_custom_utils_vid1.c | 21 +- src/coding/vorbis_custom_utils_wwise.c | 378 +++++++++--------- src/libvgmstream.vcxproj | 2 +- src/libvgmstream.vcxproj.filters | 6 +- .../bitstream_lsb.h} | 23 +- src/util/bitstream_msb.h | 37 +- 6 files changed, 249 insertions(+), 218 deletions(-) rename src/{coding/vorbis_bitreader.h => util/bitstream_lsb.h} (84%) diff --git a/src/coding/vorbis_custom_utils_vid1.c b/src/coding/vorbis_custom_utils_vid1.c index 327a1f20..c902d37b 100644 --- a/src/coding/vorbis_custom_utils_vid1.c +++ b/src/coding/vorbis_custom_utils_vid1.c @@ -1,8 +1,7 @@ #include "vorbis_custom_decoder.h" #ifdef VGM_USE_VORBIS -#define BITSTREAM_READ_ONLY /* config */ -#include "vorbis_bitreader.h" +#include "../util/bitstream_lsb.h" #include @@ -108,12 +107,12 @@ static int build_header_comment(uint8_t* buf, size_t bufsize) { if (bytes > bufsize) return 0; - put_8bit (buf+0x00, 0x03); /* packet_type (comments) */ - memcpy (buf+0x01, "vorbis", 6); /* id */ - put_32bitLE(buf+0x07, 0x09); /* vendor_length */ - memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */ - put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */ - put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */ + put_u8 (buf+0x00, 0x03); /* packet_type (comments) */ + memcpy (buf+0x01, "vorbis", 6); /* id */ + put_u32le(buf+0x07, 0x09); /* vendor_length */ + memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */ + put_u32le(buf+0x14, 0x00); /* user_comment_list_length */ + put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */ return bytes; } @@ -129,11 +128,11 @@ static int get_packet_header(STREAMFILE* sf, off_t* offset, size_t* size) { if (read_streamfile(ibuf,(*offset),ibufsize, sf) != ibufsize) goto fail; - init_bitstream(&ib, ibuf, ibufsize); + bl_setup(&ib, ibuf, ibufsize); /* read using Vorbis weird LSF */ - rv_bits(&ib, 4,&size_bits); - rv_bits(&ib, (size_bits+1),(uint32_t*)size); + bl_get(&ib, 4,&size_bits); + bl_get(&ib, (size_bits+1),(uint32_t*)size); /* special meaning, seen in silent frames */ if (size_bits == 0 && *size == 0 && (uint8_t)read_8bit(*offset, sf) == 0x80) { diff --git a/src/coding/vorbis_custom_utils_wwise.c b/src/coding/vorbis_custom_utils_wwise.c index 3ffe00a7..bc47cb1a 100644 --- a/src/coding/vorbis_custom_utils_wwise.c +++ b/src/coding/vorbis_custom_utils_wwise.c @@ -1,8 +1,8 @@ #include "vorbis_custom_decoder.h" #ifdef VGM_USE_VORBIS -#include "vorbis_bitreader.h" #include +#include "../util/bitstream_lsb.h" #define WWISE_VORBIS_USE_PRECOMPILED_WVC 1 /* if enabled vgmstream weights ~150kb more but doesn't need external .wvc packets */ #if WWISE_VORBIS_USE_PRECOMPILED_WVC @@ -212,8 +212,8 @@ static size_t rebuild_packet(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STRE ok = read_packet(wp, ibuf, ibufsize, sf, offset, data, 0); if (!ok) goto fail; - init_bitstream(&ow, obuf, obufsize); - init_bitstream(&iw, ibuf, ibufsize); + bl_setup(&ow, obuf, obufsize); + bl_setup(&iw, ibuf, ibufsize); ok = ww2ogg_generate_vorbis_packet(&ow, &iw, wp, data); if (!ok) goto fail; @@ -242,8 +242,8 @@ static size_t rebuild_setup(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STREA ok = read_packet(wp, ibuf, ibufsize, sf, offset, data, 1); if (!ok) goto fail; - init_bitstream(&ow, obuf, obufsize); - init_bitstream(&iw, ibuf, ibufsize); + bl_setup(&ow, obuf, obufsize); + bl_setup(&iw, ibuf, ibufsize); ok = ww2ogg_generate_vorbis_setup(&ow,&iw, data, wp->packet_size, sf); if (!ok) goto fail; @@ -267,16 +267,16 @@ static size_t build_header_identification(uint8_t* buf, size_t bufsize, vorbis_c blocksizes = (cfg->blocksize_0_exp << 4) | (cfg->blocksize_1_exp); - put_8bit (buf+0x00, 0x01); /* packet_type (id) */ - memcpy (buf+0x01, "vorbis", 6); /* id */ - put_32bitLE(buf+0x07, 0x00); /* vorbis_version (fixed) */ - put_8bit (buf+0x0b, cfg->channels); /* audio_channels */ - put_32bitLE(buf+0x0c, cfg->sample_rate);/* audio_sample_rate */ - put_32bitLE(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */ - put_32bitLE(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */ - put_32bitLE(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */ - put_8bit (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */ - put_8bit (buf+0x1d, 0x01); /* framing_flag (fixed) */ + put_u8 (buf+0x00, 0x01); /* packet_type (id) */ + memcpy (buf+0x01, "vorbis", 6); /* id */ + put_u32le(buf+0x07, 0x00); /* vorbis_version (fixed) */ + put_u8 (buf+0x0b, cfg->channels); /* audio_channels */ + put_u32le(buf+0x0c, cfg->sample_rate);/* audio_sample_rate */ + put_u32le(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */ + put_u32le(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */ + put_u32le(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */ + put_u8 (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */ + put_u8 (buf+0x1d, 0x01); /* framing_flag (fixed) */ return bytes; } @@ -286,12 +286,12 @@ static size_t build_header_comment(uint8_t* buf, size_t bufsize) { if (bytes > bufsize) return 0; - put_8bit (buf+0x00, 0x03); /* packet_type (comments) */ - memcpy (buf+0x01, "vorbis", 6); /* id */ - put_32bitLE(buf+0x07, 0x09); /* vendor_length */ - memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */ - put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */ - put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */ + put_u8 (buf+0x00, 0x03); /* packet_type (comments) */ + memcpy (buf+0x01, "vorbis", 6); /* id */ + put_u32le(buf+0x07, 0x09); /* vendor_length */ + memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */ + put_u32le(buf+0x14, 0x00); /* user_comment_list_length */ + put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */ return bytes; } @@ -306,14 +306,14 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) { for (i = 0; i < bytes / 4; i++) { uint32_t c = 0; - rv_bits(ib, 32, &c); - wv_bits(ob, 32, c); + bl_get(ib, 32, &c); + bl_put(ob, 32, c); } for (i = 0; i < bytes % 4; i++) { uint32_t c = 0; - rv_bits(ib, 8, &c); - wv_bits(ob, 8, c); + bl_get(ib, 8, &c); + bl_put(ob, 8, c); } #endif @@ -325,8 +325,8 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) { for (i = 0; i < bytes; i++, iw_pos++) { uint32_t c = ib->buf[iw_pos]; - //rv_bits(ib, 8, &c); - wv_bits(ob, 8, c); + //bl_get(ib, 8, &c); + bl_put(ob, 8, c); } ib->b_off += bytes * 8; @@ -337,8 +337,8 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) { for (i = 0; i < bytes; i++) { uint32_t c = 0; - rv_bits(ib, 8, &c); - wv_bits(ob, 8, c); + bl_get(ib, 8, &c); + bl_put(ob, 8, c); } return 1; @@ -369,13 +369,13 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack /* audio packet type */ packet_type = 0; - wv_bits(ow, 1, packet_type); + bl_put(ow, 1, packet_type); /* collect this packet mode from the first byte */ - rv_bits(iw, data->mode_bits,&mode_number); /* max 6b */ - wv_bits(ow, data->mode_bits, mode_number); + bl_get(iw, data->mode_bits,&mode_number); /* max 6b */ + bl_put(ow, data->mode_bits, mode_number); - rv_bits(iw, 8-data->mode_bits,&remainder); + bl_get(iw, 8-data->mode_bits,&remainder); /* adjust window info */ if (data->mode_blockflag[mode_number]) { @@ -387,9 +387,9 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack uint32_t next_mode_number; bitstream_t nw; - init_bitstream(&nw, wp->inxt, sizeof(wp->inxt)); + bl_setup(&nw, wp->inxt, sizeof(wp->inxt)); - rv_bits(&nw, data->mode_bits,&next_mode_number); /* max 6b */ + bl_get(&nw, data->mode_bits,&next_mode_number); /* max 6b */ next_blockflag = data->mode_blockflag[next_mode_number]; } @@ -399,15 +399,15 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack } prev_window_type = data->prev_blockflag; - wv_bits(ow, 1, prev_window_type); + bl_put(ow, 1, prev_window_type); next_window_type = next_blockflag; - wv_bits(ow, 1, next_window_type); + bl_put(ow, 1, next_window_type); } data->prev_blockflag = data->mode_blockflag[mode_number]; /* save for next packet */ - wv_bits(ow, 8-data->mode_bits, remainder); + bl_put(ow, 8-data->mode_bits, remainder); /* rest of the packet (input/output bytes aren't byte aligned here, so no memcpy) */ copy_bytes(ow, iw, wp->packet_size - 1); @@ -417,7 +417,7 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack uint32_t padding = 0; int padding_bits = 8 - (ow->b_off % 8); - wv_bits(ow, padding_bits, padding); + bl_put(ow, padding_bits, padding); } } else { @@ -480,12 +480,12 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { uint32_t id = 0, dimensions = 0, entries = 0; uint32_t ordered = 0, lookup_type = 0; - rv_bits(iw, 24,&id); - wv_bits(ow, 24, id); - rv_bits(iw, 16,&dimensions); - wv_bits(ow, 16, dimensions); - rv_bits(iw, 24,&entries); - wv_bits(ow, 24, entries); + bl_get(iw, 24,&id); + bl_put(ow, 24, id); + bl_get(iw, 16,&dimensions); + bl_put(ow, 16, dimensions); + bl_get(iw, 24,&entries); + bl_put(ow, 24, entries); if (0x564342 != id) { /* "VCB" */ VGM_LOG("Wwise Vorbis: invalid codebook identifier\n"); @@ -493,21 +493,21 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { } /* codeword lengths */ - rv_bits(iw, 1,&ordered); - wv_bits(ow, 1, ordered); + bl_get(iw, 1,&ordered); + bl_put(ow, 1, ordered); if (ordered) { uint32_t initial_length = 0, current_entry = 0; - rv_bits(iw, 5,&initial_length); - wv_bits(ow, 5, initial_length); + bl_get(iw, 5,&initial_length); + bl_put(ow, 5, initial_length); current_entry = 0; while (current_entry < entries) { uint32_t number = 0; - int numberv_bits = ww2ogg_tremor_ilog(entries-current_entry); + int numbebl_get = ww2ogg_tremor_ilog(entries-current_entry); - rv_bits(iw, numberv_bits,&number); - wv_bits(ow, numberv_bits, number); + bl_get(iw, numbebl_get,&number); + bl_put(ow, numbebl_get, number); current_entry += number; } if (current_entry > entries) { @@ -518,8 +518,8 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { else { uint32_t sparse = 0; - rv_bits(iw, 1,&sparse); - wv_bits(ow, 1, sparse); + bl_get(iw, 1,&sparse); + bl_put(ow, 1, sparse); for (i = 0; i < entries; i++) { uint32_t present_bool = 0; @@ -528,8 +528,8 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { if (sparse) { uint32_t present = 0; - rv_bits(iw, 1,&present); - wv_bits(ow, 1, present); + bl_get(iw, 1,&present); + bl_put(ow, 1, present); present_bool = (0 != present); } @@ -537,16 +537,16 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { if (present_bool) { uint32_t codeword_length = 0; - rv_bits(iw, 5,&codeword_length); - wv_bits(ow, 5, codeword_length); + bl_get(iw, 5,&codeword_length); + bl_put(ow, 5, codeword_length); } } } /* lookup table */ - rv_bits(iw, 4,&lookup_type); - wv_bits(ow, 4, lookup_type); + bl_get(iw, 4,&lookup_type); + bl_put(ow, 4, lookup_type); if (0 == lookup_type) { //VGM_LOG("Wwise Vorbis: no lookup table\n"); @@ -556,22 +556,22 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) { uint32_t quantvals = 0, min = 0, max = 0; uint32_t value_length = 0, sequence_flag = 0; - rv_bits(iw, 32,&min); - wv_bits(ow, 32, min); - rv_bits(iw, 32,&max); - wv_bits(ow, 32, max); - rv_bits(iw, 4,&value_length); - wv_bits(ow, 4, value_length); - rv_bits(iw, 1,&sequence_flag); - wv_bits(ow, 1, sequence_flag); + bl_get(iw, 32,&min); + bl_put(ow, 32, min); + bl_get(iw, 32,&max); + bl_put(ow, 32, max); + bl_get(iw, 4,&value_length); + bl_put(ow, 4, value_length); + bl_get(iw, 1,&sequence_flag); + bl_put(ow, 1, sequence_flag); quantvals = ww2ogg_tremor_book_maptype1_quantvals(entries, dimensions); for (i = 0; i < quantvals; i++) { uint32_t val = 0, val_bits = 0; val_bits = value_length+1; - rv_bits(iw, val_bits,&val); - wv_bits(ow, val_bits, val); + bl_get(iw, val_bits,&val); + bl_put(ow, val_bits, val); } } else if (2 == lookup_type) { @@ -596,28 +596,28 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz id = 0x564342; /* "VCB" */ - wv_bits(ow, 24, id); - rv_bits(iw, 4,&dimensions); - wv_bits(ow, 16, dimensions); /* 4 to 16 */ - rv_bits(iw, 14,&entries); - wv_bits(ow, 24, entries); /* 14 to 24*/ + bl_put(ow, 24, id); + bl_get(iw, 4,&dimensions); + bl_put(ow, 16, dimensions); /* 4 to 16 */ + bl_get(iw, 14,&entries); + bl_put(ow, 24, entries); /* 14 to 24*/ /* codeword lengths */ - rv_bits(iw, 1,&ordered); - wv_bits(ow, 1, ordered); + bl_get(iw, 1,&ordered); + bl_put(ow, 1, ordered); if (ordered) { uint32_t initial_length = 0, current_entry = 0; - rv_bits(iw, 5,&initial_length); - wv_bits(ow, 5, initial_length); + bl_get(iw, 5,&initial_length); + bl_put(ow, 5, initial_length); current_entry = 0; while (current_entry < entries) { uint32_t number = 0; - int numberv_bits = ww2ogg_tremor_ilog(entries-current_entry); + int numbebl_get = ww2ogg_tremor_ilog(entries-current_entry); - rv_bits(iw, numberv_bits,&number); - wv_bits(ow, numberv_bits, number); + bl_get(iw, numbebl_get,&number); + bl_put(ow, numbebl_get, number); current_entry += number; } if (current_entry > entries) { @@ -628,9 +628,9 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz else { uint32_t codeword_length_length = 0, sparse = 0; - rv_bits(iw, 3,&codeword_length_length); - rv_bits(iw, 1,&sparse); - wv_bits(ow, 1, sparse); + bl_get(iw, 3,&codeword_length_length); + bl_get(iw, 1,&sparse); + bl_put(ow, 1, sparse); if (0 == codeword_length_length || 5 < codeword_length_length) { VGM_LOG("Wwise Vorbis: nonsense codeword length\n"); @@ -644,8 +644,8 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz if (sparse) { uint32_t present = 0; - rv_bits(iw, 1,&present); - wv_bits(ow, 1, present); + bl_get(iw, 1,&present); + bl_put(ow, 1, present); present_bool = (0 != present); } @@ -653,16 +653,16 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz if (present_bool) { uint32_t codeword_length = 0; - rv_bits(iw, codeword_length_length,&codeword_length); - wv_bits(ow, 5, codeword_length); /* max 7 (3b) to 5 */ + bl_get(iw, codeword_length_length,&codeword_length); + bl_put(ow, 5, codeword_length); /* max 7 (3b) to 5 */ } } } /* lookup table */ - rv_bits(iw, 1,&lookup_type); - wv_bits(ow, 4, lookup_type); /* 1 to 4 */ + bl_get(iw, 1,&lookup_type); + bl_put(ow, 4, lookup_type); /* 1 to 4 */ if (0 == lookup_type) { //VGM_LOG("Wwise Vorbis: no lookup table\n"); @@ -672,22 +672,22 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz uint32_t quantvals = 0, min = 0, max = 0; uint32_t value_length = 0, sequence_flag = 0; - rv_bits(iw, 32,&min); - wv_bits(ow, 32, min); - rv_bits(iw, 32,&max); - wv_bits(ow, 32, max); - rv_bits(iw, 4,&value_length); - wv_bits(ow, 4, value_length); - rv_bits(iw, 1,&sequence_flag); - wv_bits(ow, 1, sequence_flag); + bl_get(iw, 32,&min); + bl_put(ow, 32, min); + bl_get(iw, 32,&max); + bl_put(ow, 32, max); + bl_get(iw, 4,&value_length); + bl_put(ow, 4, value_length); + bl_get(iw, 1,&sequence_flag); + bl_put(ow, 1, sequence_flag); quantvals = ww2ogg_tremor_book_maptype1_quantvals(entries, dimensions); for (i = 0; i < quantvals; i++) { uint32_t val = 0, val_bits = 0; val_bits = value_length+1; - rv_bits(iw, val_bits,&val); - wv_bits(ow, val_bits, val); + bl_get(iw, val_bits,&val); + bl_put(ow, val_bits, val); } } else if (2 == lookup_type) { @@ -722,7 +722,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(bitstream_t* ow, uint32_t codeb cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, sf); if (cb_size == 0) goto fail; - init_bitstream(&iw, ibuf, ibufsize); + bl_setup(&iw, ibuf, ibufsize); return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, sf); fail: @@ -746,8 +746,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis /* Codebooks */ - rv_bits(iw, 8,&codebook_count_less1); - wv_bits(ow, 8, codebook_count_less1); + bl_get(iw, 8,&codebook_count_less1); + bl_put(ow, 8, codebook_count_less1); codebook_count = codebook_count_less1 + 1; if (data->config.setup_type == WWV_FULL_SETUP) { @@ -770,7 +770,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis int rc; uint32_t codebook_id = 0; - rv_bits(iw, 10,&codebook_id); + bl_get(iw, 10,&codebook_id); rc = ww2ogg_codebook_library_rebuild_by_id(ow, codebook_id, data->config.setup_type, sf); if (!rc) goto fail; @@ -780,9 +780,9 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis /* Time domain transforms */ time_count_less1 = 0; - wv_bits(ow, 6, time_count_less1); + bl_put(ow, 6, time_count_less1); dummy_time_value = 0; - wv_bits(ow, 16, dummy_time_value); + bl_put(ow, 16, dummy_time_value); if (data->config.setup_type == WWV_FULL_SETUP) { @@ -792,8 +792,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t setup_packet_size_bits = packet_size * 8; while (total_bits_read < setup_packet_size_bits) { - rv_bits(iw, 1,&bitly); - wv_bits(ow, 1, bitly); + bl_get(iw, 1,&bitly); + bl_put(ow, 1, bitly); total_bits_read = iw->b_off; } } @@ -806,8 +806,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis /* Floors */ - rv_bits(iw, 6,&floor_count_less1); - wv_bits(ow, 6, floor_count_less1); + bl_get(iw, 6,&floor_count_less1); + bl_put(ow, 6, floor_count_less1); floor_count = floor_count_less1 + 1; for (i = 0; i < floor_count; i++) { @@ -818,10 +818,10 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis // Always floor type 1 floor_type = 1; - wv_bits(ow, 16, floor_type); + bl_put(ow, 16, floor_type); - rv_bits(iw, 5,&floor1_partitions); - wv_bits(ow, 5, floor1_partitions); + bl_get(iw, 5,&floor1_partitions); + bl_put(ow, 5, floor1_partitions); memset(floor1_partition_class_list, 0, sizeof(uint32_t)*32); @@ -829,8 +829,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis for (j = 0; j < floor1_partitions; j++) { uint32_t floor1_partition_class = 0; - rv_bits(iw, 4,&floor1_partition_class); - wv_bits(ow, 4, floor1_partition_class); + bl_get(iw, 4,&floor1_partition_class); + bl_put(ow, 4, floor1_partition_class); floor1_partition_class_list[j] = floor1_partition_class; @@ -843,19 +843,19 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis for (j = 0; j <= maximum_class; j++) { uint32_t class_dimensions_less1 = 0, class_subclasses = 0; - rv_bits(iw, 3,&class_dimensions_less1); - wv_bits(ow, 3, class_dimensions_less1); + bl_get(iw, 3,&class_dimensions_less1); + bl_put(ow, 3, class_dimensions_less1); floor1_class_dimensions_list[j] = class_dimensions_less1 + 1; - rv_bits(iw, 2,&class_subclasses); - wv_bits(ow, 2, class_subclasses); + bl_get(iw, 2,&class_subclasses); + bl_put(ow, 2, class_subclasses); if (0 != class_subclasses) { uint32_t masterbook = 0; - rv_bits(iw, 8,&masterbook); - wv_bits(ow, 8, masterbook); + bl_get(iw, 8,&masterbook); + bl_put(ow, 8, masterbook); if (masterbook >= codebook_count) { VGM_LOG("Wwise Vorbis: invalid floor1 masterbook\n"); @@ -867,8 +867,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t subclass_book_plus1 = 0; int subclass_book = 0; /* this MUST be int */ - rv_bits(iw, 8,&subclass_book_plus1); - wv_bits(ow, 8, subclass_book_plus1); + bl_get(iw, 8,&subclass_book_plus1); + bl_put(ow, 8, subclass_book_plus1); subclass_book = subclass_book_plus1 - 1; if (subclass_book >= 0 && subclass_book >= codebook_count) { @@ -878,11 +878,11 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis } } - rv_bits(iw, 2,&floor1_multiplier_less1); - wv_bits(ow, 2, floor1_multiplier_less1); + bl_get(iw, 2,&floor1_multiplier_less1); + bl_put(ow, 2, floor1_multiplier_less1); - rv_bits(iw, 4,&rangebits); - wv_bits(ow, 4, rangebits); + bl_get(iw, 4,&rangebits); + bl_put(ow, 4, rangebits); for (j = 0; j < floor1_partitions; j++) { uint32_t current_class_number = 0; @@ -891,16 +891,16 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis for (k = 0; k < floor1_class_dimensions_list[current_class_number]; k++) { uint32_t X = 0; /* max 4b (15) */ - rv_bits(iw, rangebits,&X); - wv_bits(ow, rangebits, X); + bl_get(iw, rangebits,&X); + bl_put(ow, rangebits, X); } } } /* Residues */ - rv_bits(iw, 6,&residue_count_less1); - wv_bits(ow, 6, residue_count_less1); + bl_get(iw, 6,&residue_count_less1); + bl_put(ow, 6, residue_count_less1); residue_count = residue_count_less1 + 1; for (i = 0; i < residue_count; i++) { @@ -908,24 +908,24 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t residue_begin = 0, residue_end = 0, residue_partition_size_less1 = 0, residue_classifications_less1 = 0, residue_classbook = 0; uint32_t residue_cascade[64+1]; /* 6b +1 */ - rv_bits(iw, 2,&residue_type); - wv_bits(ow, 16, residue_type); /* 2b to 16b */ + bl_get(iw, 2,&residue_type); + bl_put(ow, 16, residue_type); /* 2b to 16b */ if (residue_type > 2) { VGM_LOG("Wwise Vorbis: invalid residue type\n"); goto fail; } - rv_bits(iw, 24,&residue_begin); - wv_bits(ow, 24, residue_begin); - rv_bits(iw, 24,&residue_end); - wv_bits(ow, 24, residue_end); - rv_bits(iw, 24,&residue_partition_size_less1); - wv_bits(ow, 24, residue_partition_size_less1); - rv_bits(iw, 6,&residue_classifications_less1); - wv_bits(ow, 6, residue_classifications_less1); - rv_bits(iw, 8,&residue_classbook); - wv_bits(ow, 8, residue_classbook); + bl_get(iw, 24,&residue_begin); + bl_put(ow, 24, residue_begin); + bl_get(iw, 24,&residue_end); + bl_put(ow, 24, residue_end); + bl_get(iw, 24,&residue_partition_size_less1); + bl_put(ow, 24, residue_partition_size_less1); + bl_get(iw, 6,&residue_classifications_less1); + bl_put(ow, 6, residue_classifications_less1); + bl_get(iw, 8,&residue_classbook); + bl_put(ow, 8, residue_classbook); residue_classifications = residue_classifications_less1 + 1; if (residue_classbook >= codebook_count) { @@ -936,21 +936,21 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis memset(residue_cascade, 0, sizeof(uint32_t)*(64+1)); for (j = 0; j < residue_classifications; j++) { - uint32_t high_bits = 0, lowv_bits = 0, bitflag = 0; + uint32_t high_bits = 0, lobl_put = 0, bitflag = 0; high_bits = 0; - rv_bits(iw, 3,&lowv_bits); - wv_bits(ow, 3, lowv_bits); + bl_get(iw, 3,&lobl_put); + bl_put(ow, 3, lobl_put); - rv_bits(iw, 1,&bitflag); - wv_bits(ow, 1, bitflag); + bl_get(iw, 1,&bitflag); + bl_put(ow, 1, bitflag); if (bitflag) { - rv_bits(iw, 5,&high_bits); - wv_bits(ow, 5, high_bits); + bl_get(iw, 5,&high_bits); + bl_put(ow, 5, high_bits); } - residue_cascade[j] = high_bits * 8 + lowv_bits; + residue_cascade[j] = high_bits * 8 + lobl_put; } for (j = 0; j < residue_classifications; j++) { @@ -958,8 +958,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis if (residue_cascade[j] & (1 << k)) { uint32_t residue_book = 0; - rv_bits(iw, 8,&residue_book); - wv_bits(ow, 8, residue_book); + bl_get(iw, 8,&residue_book); + bl_put(ow, 8, residue_book); if (residue_book >= codebook_count) { VGM_LOG("Wwise Vorbis: invalid residue book\n"); @@ -972,8 +972,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis /* Mappings */ - rv_bits(iw, 6,&mapping_count_less1); - wv_bits(ow, 6, mapping_count_less1); + bl_get(iw, 6,&mapping_count_less1); + bl_put(ow, 6, mapping_count_less1); mapping_count = mapping_count_less1 + 1; for (i = 0; i < mapping_count; i++) { @@ -982,28 +982,28 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis // always mapping type 0, the only one mapping_type = 0; - wv_bits(ow, 16, mapping_type); + bl_put(ow, 16, mapping_type); - rv_bits(iw, 1,&submaps_flag); - wv_bits(ow, 1, submaps_flag); + bl_get(iw, 1,&submaps_flag); + bl_put(ow, 1, submaps_flag); submaps = 1; if (submaps_flag) { uint32_t submaps_less1 = 0; - rv_bits(iw, 4,&submaps_less1); - wv_bits(ow, 4, submaps_less1); + bl_get(iw, 4,&submaps_less1); + bl_put(ow, 4, submaps_less1); submaps = submaps_less1 + 1; } - rv_bits(iw, 1,&square_polar_flag); - wv_bits(ow, 1, square_polar_flag); + bl_get(iw, 1,&square_polar_flag); + bl_put(ow, 1, square_polar_flag); if (square_polar_flag) { uint32_t coupling_steps_less1 = 0, coupling_steps = 0; - rv_bits(iw, 8,&coupling_steps_less1); - wv_bits(ow, 8, coupling_steps_less1); + bl_get(iw, 8,&coupling_steps_less1); + bl_put(ow, 8, coupling_steps_less1); coupling_steps = coupling_steps_less1 + 1; for (j = 0; j < coupling_steps; j++) { @@ -1011,10 +1011,10 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis int magnitude_bits = ww2ogg_tremor_ilog(channels-1); int angle_bits = ww2ogg_tremor_ilog(channels-1); - rv_bits(iw, magnitude_bits,&magnitude); - wv_bits(ow, magnitude_bits, magnitude); - rv_bits(iw, angle_bits,&angle); - wv_bits(ow, angle_bits, angle); + bl_get(iw, magnitude_bits,&magnitude); + bl_put(ow, magnitude_bits, magnitude); + bl_get(iw, angle_bits,&angle); + bl_put(ow, angle_bits, angle); if (angle == magnitude || magnitude >= channels || angle >= channels) { VGM_LOG("Wwise Vorbis: invalid coupling (angle=%i, mag=%i, ch=%i)\n", angle, magnitude,channels); @@ -1024,8 +1024,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis } // a rare reserved field not removed by Ak! - rv_bits(iw, 2,&mapping_reserved); - wv_bits(ow, 2, mapping_reserved); + bl_get(iw, 2,&mapping_reserved); + bl_put(ow, 2, mapping_reserved); if (0 != mapping_reserved) { VGM_LOG("Wwise Vorbis: mapping reserved field nonzero\n"); goto fail; @@ -1035,8 +1035,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis for (j = 0; j < channels; j++) { uint32_t mapping_mux = 0; - rv_bits(iw, 4,&mapping_mux); - wv_bits(ow, 4, mapping_mux); + bl_get(iw, 4,&mapping_mux); + bl_put(ow, 4, mapping_mux); if (mapping_mux >= submaps) { VGM_LOG("Wwise Vorbis: mapping_mux >= submaps\n"); goto fail; @@ -1048,18 +1048,18 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t time_config = 0, floor_number = 0, residue_number = 0; // Another! Unused time domain transform configuration placeholder! - rv_bits(iw, 8,&time_config); - wv_bits(ow, 8, time_config); + bl_get(iw, 8,&time_config); + bl_put(ow, 8, time_config); - rv_bits(iw, 8,&floor_number); - wv_bits(ow, 8, floor_number); + bl_get(iw, 8,&floor_number); + bl_put(ow, 8, floor_number); if (floor_number >= floor_count) { VGM_LOG("Wwise Vorbis: invalid floor mapping\n"); goto fail; } - rv_bits(iw, 8,&residue_number); - wv_bits(ow, 8, residue_number); + bl_get(iw, 8,&residue_number); + bl_put(ow, 8, residue_number); if (residue_number >= residue_count) { VGM_LOG("Wwise Vorbis: invalid residue mapping\n"); goto fail; @@ -1069,8 +1069,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis /* Modes */ - rv_bits(iw, 6,&mode_count_less1); - wv_bits(ow, 6, mode_count_less1); + bl_get(iw, 6,&mode_count_less1); + bl_put(ow, 6, mode_count_less1); mode_count = mode_count_less1 + 1; memset(data->mode_blockflag, 0, sizeof(uint8_t)*(64+1)); /* up to max mode_count */ @@ -1079,18 +1079,18 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis for (i = 0; i < mode_count; i++) { uint32_t block_flag = 0, windowtype = 0, transformtype = 0, mapping = 0; - rv_bits(iw, 1,&block_flag); - wv_bits(ow, 1, block_flag); + bl_get(iw, 1,&block_flag); + bl_put(ow, 1, block_flag); data->mode_blockflag[i] = (block_flag != 0); /* for mod_packets */ windowtype = 0; transformtype = 0; - wv_bits(ow, 16, windowtype); - wv_bits(ow, 16, transformtype); + bl_put(ow, 16, windowtype); + bl_put(ow, 16, transformtype); - rv_bits(iw, 8,&mapping); - wv_bits(ow, 8, mapping); + bl_get(iw, 8,&mapping); + bl_put(ow, 8, mapping); if (mapping >= mapping_count) { VGM_LOG("Wwise Vorbis: invalid mode mapping\n"); goto fail; @@ -1104,7 +1104,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t framing = 0; framing = 1; - wv_bits(ow, 1, framing); + bl_put(ow, 1, framing); } /* remove trailing garbage bits */ @@ -1112,7 +1112,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis uint32_t padding = 0; int padding_bits = 8 - (ow->b_off % 8); - wv_bits(ow, padding_bits, padding); + bl_put(ow, padding_bits, padding); } diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index ff8be911..90ce90da 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -110,7 +110,6 @@ - @@ -168,6 +167,7 @@ + diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters index 493d257a..bbe5335e 100644 --- a/src/libvgmstream.vcxproj.filters +++ b/src/libvgmstream.vcxproj.filters @@ -155,9 +155,6 @@ coding\Header Files - - coding\Header Files - coding\Header Files @@ -329,6 +326,9 @@ meta\Header Files + + util\Header Files + util\Header Files diff --git a/src/coding/vorbis_bitreader.h b/src/util/bitstream_lsb.h similarity index 84% rename from src/coding/vorbis_bitreader.h rename to src/util/bitstream_lsb.h index 89ac0817..275cfba1 100644 --- a/src/coding/vorbis_bitreader.h +++ b/src/util/bitstream_lsb.h @@ -1,8 +1,11 @@ -#ifndef _VORBIS_BITREADER_H -#define _VORBIS_BITREADER_H +#ifndef _BITSTREAM_LSB_H +#define _BITSTREAM_LSB_H -/* Simple bitreader for Vorbis' bit format. - * Kept in .h since it's slightly faster (compiler can optimize statics better) */ +#include "../streamtypes.h" + +/* Simple bitreader for Vorbis' bit style, in 'least significant byte' (LSB) format. + * Example: 0x12345678 is read as 12,34,56,78 (continuous). + * Kept in .h since it's slightly faster (compiler can optimize statics better using default compile flags). */ typedef struct { @@ -12,7 +15,7 @@ typedef struct { } bitstream_t; /* convenience util */ -static void init_bitstream(bitstream_t* b, uint8_t* buf, size_t bufsize) { +static inline void bl_setup(bitstream_t* b, uint8_t* buf, size_t bufsize) { b->buf = buf; b->bufsize = bufsize; b->b_off = 0; @@ -29,7 +32,7 @@ static const uint32_t MASK_TABLE[33] = { /* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. * (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */ -static int rv_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) { +static inline int bl_get(bitstream_t* ib, uint32_t bits, uint32_t* value) { uint32_t shift, mask, pos, val; if (bits > 32 || ib->b_off + bits > ib->bufsize * 8) @@ -59,15 +62,14 @@ static int rv_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) { return 1; fail: - VGM_LOG_ONCE("BITREADER: read fail\n"); + //VGM_LOG_ONCE("BITREADER: read fail\n"); *value = 0; return 0; } -#ifndef BITSTREAM_READ_ONLY /* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte. * (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/ -static int wv_bits(bitstream_t* ob, uint32_t bits, uint32_t value) { +static inline int bl_put(bitstream_t* ob, uint32_t bits, uint32_t value) { uint32_t shift, mask, pos; if (bits > 32 || ob->b_off + bits > ob->bufsize*8) @@ -95,9 +97,8 @@ static int wv_bits(bitstream_t* ob, uint32_t bits, uint32_t value) { ob->b_off += bits; return 1; fail: - VGM_LOG_ONCE("BITREADER: write fail\n"); + //VGM_LOG_ONCE("BITREADER: write fail\n"); return 0; } -#endif #endif diff --git a/src/util/bitstream_msb.h b/src/util/bitstream_msb.h index 77fd0f07..42bd9b29 100644 --- a/src/util/bitstream_msb.h +++ b/src/util/bitstream_msb.h @@ -1,10 +1,11 @@ #ifndef _BITSTREAM_MSB_H #define _BITSTREAM_MSB_H -#include +#include "../streamtypes.h" -/* Simple bitreader for MPEG/standard bit format. - * Kept in .h since it's slightly faster (compiler can optimize better) */ +/* Simple bitreader for MPEG/standard bit style, in 'most significant byte' (MSB) format. + * Example: 0x12345678 is read as 78,56,34,12 then each byte's bits. + * Kept in .h since it's slightly faster (compiler can optimize statics better using default compile flags). */ typedef struct { uint8_t* buf; /* buffer to read/write */ @@ -70,6 +71,7 @@ static inline int bm_get(bitstream_t* ib, uint32_t bits, uint32_t* value) { pos = ib->b_off / 8; /* byte offset */ shift = ib->b_off % 8; /* bit sub-offset */ +#if 1 //naive approach val = 0; for (i = 0; i < bits; i++) { bit_buf = (1U << (8-1-shift)) & 0xFF; /* bit check for buf */ @@ -84,6 +86,35 @@ static inline int bm_get(bitstream_t* ib, uint32_t bits, uint32_t* value) { pos++; } } +#else //has bugs + pos = ib->b_off / 8; /* byte offset */ + shift = ib->b_off % 8; /* bit sub-offset */ + uint32_t mask = MASK_TABLE[bits]; /* to remove upper in highest byte */ + + int left = 0; + if (bits == 0) + val = 0; + else + val = ib->buf[pos+0]; + left = 8 - (bits + shift); + if (bits + shift > 8) { + val = (val << 8u) | ib->buf[pos+1]; + left = 16 - (bits + shift); + if (bits + shift > 16) { + val = (val << 8u) | ib->buf[pos+2]; + left = 32 - (bits + shift); + if (bits + shift > 24) { + val = (val << 8u) | ib->buf[pos+3]; + left = 32 - (bits + shift); + if (bits + shift > 32) { + val = (val << 8u) | ib->buf[pos+4]; /* upper bits are lost (shifting over 32) */ TO-DO + left = 40 - (bits + shift); + } + } + } + } + val = ((val >> left) & mask); +#endif *value = val; ib->b_off += bits; From 0746a892107ef79d9706362fa288958937ba7c45 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 15 May 2023 16:14:29 +0200 Subject: [PATCH 11/13] cleanup: misc renames --- doc/DEV.md | 8 ++++---- src/base/decode.c | 24 ++++++++++++------------ src/base/decode.h | 18 +++++++++--------- src/base/render.c | 4 ++-- src/base/render.h | 4 ++-- src/base/seek.c | 2 +- src/formats.c | 2 +- src/layout/blocked.c | 18 +++++++++--------- src/layout/flat.c | 6 +++--- src/layout/interleave.c | 16 ++++++++-------- src/layout/layered.c | 6 +++--- src/layout/segmented.c | 4 ++-- src/vgmstream.c | 33 +++++++++++++++++---------------- 13 files changed, 73 insertions(+), 72 deletions(-) diff --git a/doc/DEV.md b/doc/DEV.md index f0aa669d..f330ff3e 100644 --- a/doc/DEV.md +++ b/doc/DEV.md @@ -122,7 +122,7 @@ Very simplified it goes like this: - layout prepares samples and offsets to read from the stream *[render_vgmstream_(layout)]* - decoder reads and decodes bytes into PCM samples *[decode_vgmstream_(coding)]* - player plays those samples, asks to fill sample buffer again, repeats (until total_samples) -- layout moves offsets back to loop_start when loop_end is reached *[vgmstream_do_loop]* +- layout moves offsets back to loop_start when loop_end is reached *[decode_do_loop]* - player closes the VGMSTREAM once the stream is finished vgsmtream's main code (located in src) may be considered "libvgmstream", and plugins interface it through vgmstream.h, mainly the part commented as "vgmstream public API". There isn't a clean external API at the moment, this may be improved later. @@ -201,10 +201,10 @@ If the decoder needs to keep state between calls it may use the VGMSTREAM for co Adding a new decoder involves: - *src/coding/(decoder-name).c*: create `decode_x` function that decodes stream data into the passed sample buffer. If the codec requires custom internals it may need `init/reset/seek/free_x`, or other helper functions. - *src/coding/coding.h*: define decoder's functions and type -- *src/decode.c: get_vgmstream_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples) -- *src/decode.c: get_vgmstream_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way. +- *src/decode.c: decode_get_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples) +- *src/decode.c: decode_get_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way. - *src/decode.c: decode_vgmstream*: call `decode_x`, possibly once per channel if the decoder works with a channel at a time. -- *src/decode.c: add handling in `reset/seek/free_codec` if needed +- *src/decode.c: add handling in `reset/seek/decode_free` if needed - *src/formats.c*: add coding type description - *src/libvgmstream.vcproj/vcxproj/filters*: add to compile new (decoder-name).c parser in VS - if the codec depends on a external library don't forget to mark parts with: *#ifdef VGM_USE_X ... #endif* diff --git a/src/base/decode.c b/src/base/decode.c index 3f95c96a..f5feaa3d 100644 --- a/src/base/decode.c +++ b/src/base/decode.c @@ -8,7 +8,7 @@ /* custom codec handling, not exactly "decode" stuff but here to simplify adding new codecs */ -void free_codec(VGMSTREAM* vgmstream) { +void decode_free(VGMSTREAM* vgmstream) { #ifdef VGM_USE_VORBIS if (vgmstream->coding_type == coding_OGG_VORBIS) { @@ -119,7 +119,7 @@ void free_codec(VGMSTREAM* vgmstream) { } -void seek_codec(VGMSTREAM* vgmstream) { +void decode_seek(VGMSTREAM* vgmstream) { if (vgmstream->coding_type == coding_CIRCUS_VQ) { seek_circus_vq(vgmstream->codec_data, vgmstream->loop_current_sample); } @@ -213,7 +213,7 @@ void seek_codec(VGMSTREAM* vgmstream) { } -void reset_codec(VGMSTREAM* vgmstream) { +void decode_reset(VGMSTREAM* vgmstream) { #ifdef VGM_USE_VORBIS if (vgmstream->coding_type == coding_OGG_VORBIS) { @@ -325,7 +325,7 @@ void reset_codec(VGMSTREAM* vgmstream) { /* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */ -int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) { +int decode_get_samples_per_frame(VGMSTREAM* vgmstream) { /* Value returned here is the max (or less) that vgmstream will ask a decoder per * "decode_x" call. Decoders with variable samples per frame or internal discard * may return 0 here and handle arbitrary samples_to_do values internally @@ -555,7 +555,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) { } /* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */ -int get_vgmstream_frame_size(VGMSTREAM* vgmstream) { +int decode_get_frame_size(VGMSTREAM* vgmstream) { switch (vgmstream->coding_type) { case coding_SILENCE: return 0; @@ -747,21 +747,21 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) { } /* In NDS IMA the frame size is the block size, so the last one is short */ -int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream) { +int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream) { switch (vgmstream->coding_type) { case coding_NDS_IMA: return (vgmstream->interleave_last_block_size-4)*2; default: - return get_vgmstream_samples_per_frame(vgmstream); + return decode_get_samples_per_frame(vgmstream); } } -int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream) { +int decode_get_shortframe_size(VGMSTREAM* vgmstream) { switch (vgmstream->coding_type) { case coding_NDS_IMA: return vgmstream->interleave_last_block_size; default: - return get_vgmstream_frame_size(vgmstream); + return decode_get_frame_size(vgmstream); } } @@ -1488,7 +1488,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_ /* Calculate number of consecutive samples we can decode. Takes into account hitting * a loop start or end, or going past a single frame. */ -int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) { +int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) { int samples_to_do; int samples_left_this_block; @@ -1521,7 +1521,7 @@ int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, V /* Detect loop start and save values, or detect loop end and restore (loop back). * Returns 1 if loop was done. */ -int vgmstream_do_loop(VGMSTREAM* vgmstream) { +int decode_do_loop(VGMSTREAM* vgmstream) { /*if (!vgmstream->loop_flag) return 0;*/ /* is this the loop end? = new loop, continue from loop_start_sample */ @@ -1557,7 +1557,7 @@ int vgmstream_do_loop(VGMSTREAM* vgmstream) { * - loop_ch[] is copied to ch[] (with custom value) * - then codec will use ch[]'s offset * regular codecs may use copied loop_ch[] offset without issue */ - seek_codec(vgmstream); + decode_seek(vgmstream); /* restore! */ memcpy(vgmstream->ch, vgmstream->loop_ch, sizeof(VGMSTREAMCHANNEL) * vgmstream->channels); diff --git a/src/base/decode.h b/src/base/decode.h index 14e6e859..541445b6 100644 --- a/src/base/decode.h +++ b/src/base/decode.h @@ -3,30 +3,30 @@ #include "../vgmstream.h" -void free_codec(VGMSTREAM* vgmstream); -void seek_codec(VGMSTREAM* vgmstream); -void reset_codec(VGMSTREAM* vgmstream); +void decode_free(VGMSTREAM* vgmstream); +void decode_seek(VGMSTREAM* vgmstream); +void decode_reset(VGMSTREAM* vgmstream); /* Decode samples into the buffer. Assume that we have written samples_written into the * buffer already, and we have samples_to_do consecutive samples ahead of us. */ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer); /* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */ -int vgmstream_do_loop(VGMSTREAM* vgmstream); +int decode_do_loop(VGMSTREAM* vgmstream); /* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ -int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream); +int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream); /* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */ -int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream); +int decode_get_samples_per_frame(VGMSTREAM* vgmstream); /* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */ -int get_vgmstream_frame_size(VGMSTREAM* vgmstream); +int decode_get_frame_size(VGMSTREAM* vgmstream); /* In NDS IMA the frame size is the block size, but last one is shorter */ -int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream); -int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream); +int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream); +int decode_get_shortframe_size(VGMSTREAM* vgmstream); #endif diff --git a/src/base/render.c b/src/base/render.c index 94afd5bf..f5480efa 100644 --- a/src/base/render.c +++ b/src/base/render.c @@ -222,7 +222,7 @@ void setup_state_vgmstream(VGMSTREAM* vgmstream) { /*****************************************************************************/ -void free_layout(VGMSTREAM* vgmstream) { +void render_free(VGMSTREAM* vgmstream) { if (vgmstream->layout_type == layout_segmented) { free_layout_segmented(vgmstream->layout_data); @@ -233,7 +233,7 @@ void free_layout(VGMSTREAM* vgmstream) { } } -void reset_layout(VGMSTREAM* vgmstream) { +void render_reset(VGMSTREAM* vgmstream) { if (vgmstream->layout_type == layout_segmented) { reset_layout_segmented(vgmstream->layout_data); diff --git a/src/base/render.h b/src/base/render.h index 93fb388a..488546fe 100644 --- a/src/base/render.h +++ b/src/base/render.h @@ -3,8 +3,8 @@ #include "../vgmstream.h" -void free_layout(VGMSTREAM* vgmstream); -void reset_layout(VGMSTREAM* vgmstream); +void render_free(VGMSTREAM* vgmstream); +void render_reset(VGMSTREAM* vgmstream); int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream); diff --git a/src/base/seek.c b/src/base/seek.c index 9a271eb4..24e076fe 100644 --- a/src/base/seek.c +++ b/src/base/seek.c @@ -14,7 +14,7 @@ static void seek_force_loop(VGMSTREAM* vgmstream, int loop_count) { /* pretend decoder reached loop end so state is set to loop start */ vgmstream->loop_count = loop_count - 1; /* seeking to first loop must become ++ > 0 */ vgmstream->current_sample = vgmstream->loop_end_sample; - vgmstream_do_loop(vgmstream); + decode_do_loop(vgmstream); } static void seek_force_decode(VGMSTREAM* vgmstream, int samples) { diff --git a/src/formats.c b/src/formats.c index f01e762d..d1f00693 100644 --- a/src/formats.c +++ b/src/formats.c @@ -116,7 +116,7 @@ static const char* extension_list[] = { "bk2", "bkr", //txth/reserved [P.N.03 (GC), Viewtiful Joe (GC)] "blk", - "bmdx", + "bmdx", //fake extension (to be removed?) "bms", "bnk", "bnm", diff --git a/src/layout/blocked.c b/src/layout/blocked.c index bac084ec..d38a2053 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -11,13 +11,13 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* int samples_written = 0; int frame_size, samples_per_frame, samples_this_block; - frame_size = get_vgmstream_frame_size(vgmstream); - samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + frame_size = decode_get_frame_size(vgmstream); + samples_per_frame = decode_get_samples_per_frame(vgmstream); samples_this_block = 0; if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; @@ -28,11 +28,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* int samples_to_do; - if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { /* handle looping, readjust back to loop start values */ if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; @@ -54,7 +54,7 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* break; } - samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); if (samples_to_do > sample_count - samples_written) samples_to_do = sample_count - samples_written; @@ -74,11 +74,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* block_update(vgmstream->next_block_offset,vgmstream); /* update since these may change each block */ - frame_size = get_vgmstream_frame_size(vgmstream); - samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + frame_size = decode_get_frame_size(vgmstream); + samples_per_frame = decode_get_samples_per_frame(vgmstream); if (vgmstream->current_block_samples) { samples_this_block = vgmstream->current_block_samples; - } else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */ + } else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; diff --git a/src/layout/flat.c b/src/layout/flat.c index 603281c1..05ef8262 100644 --- a/src/layout/flat.c +++ b/src/layout/flat.c @@ -9,19 +9,19 @@ void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vg int samples_written = 0; int samples_per_frame, samples_this_block; - samples_per_frame = get_vgmstream_samples_per_frame(vgmstream); + samples_per_frame = decode_get_samples_per_frame(vgmstream); samples_this_block = vgmstream->num_samples; /* do all samples if possible */ while (samples_written < sample_count) { int samples_to_do; - if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { /* handle looping */ continue; } - samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); if (samples_to_do > sample_count - samples_written) samples_to_do = sample_count - samples_written; diff --git a/src/layout/interleave.c b/src/layout/interleave.c index 1c8ba0ae..678ed339 100644 --- a/src/layout/interleave.c +++ b/src/layout/interleave.c @@ -19,20 +19,20 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR /* setup */ { - int frame_size_d = get_vgmstream_frame_size(vgmstream); - samples_per_frame_d = get_vgmstream_samples_per_frame(vgmstream); + int frame_size_d = decode_get_frame_size(vgmstream); + samples_per_frame_d = decode_get_samples_per_frame(vgmstream); if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail; samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d; } if (has_interleave_first) { - int frame_size_f = get_vgmstream_frame_size(vgmstream); - samples_per_frame_f = get_vgmstream_samples_per_frame(vgmstream); //todo samples per shortframe + int frame_size_f = decode_get_frame_size(vgmstream); + samples_per_frame_f = decode_get_samples_per_frame(vgmstream); //todo samples per shortframe if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail; samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f; } if (has_interleave_last) { - int frame_size_l = get_vgmstream_shortframe_size(vgmstream); - samples_per_frame_l = get_vgmstream_samples_per_shortframe(vgmstream); + int frame_size_l = decode_get_shortframe_size(vgmstream); + samples_per_frame_l = decode_get_samples_per_shortframe(vgmstream); if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail; samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l; } @@ -62,7 +62,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR while (samples_written < sample_count) { int samples_to_do; - if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { /* handle looping, restore standard interleave sizes */ if (has_interleave_first && @@ -83,7 +83,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR continue; } - samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); if (samples_to_do > sample_count - samples_written) samples_to_do = sample_count - samples_written; diff --git a/src/layout/layered.c b/src/layout/layered.c index e6221b74..2dc853dc 100644 --- a/src/layout/layered.c +++ b/src/layout/layered.c @@ -25,12 +25,12 @@ void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM* int layer, ch; - if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { /* handle looping (loop_layout has been called below) */ continue; } - samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream); + samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); if (samples_to_do > sample_count - samples_written) samples_to_do = sample_count - samples_written; @@ -105,7 +105,7 @@ void loop_layout_layered(VGMSTREAM* vgmstream, int32_t loop_sample) { * calls to do_loop work (used in seek_vgmstream) */ if (data->layers[layer]->loop_flag) { /* mixing looping and non-looping layers is allowed */ data->layers[layer]->current_sample = data->layers[layer]->loop_end_sample; /* forces do loop */ - vgmstream_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */ + decode_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */ } else { /* needed when mixing non-looping layers and installing loop externally */ diff --git a/src/layout/segmented.c b/src/layout/segmented.c index 85a61740..bf0bd579 100644 --- a/src/layout/segmented.c +++ b/src/layout/segmented.c @@ -34,7 +34,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA while (samples_written < sample_count) { int samples_to_do; - if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) { + if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { /* handle looping (loop_layout has been called below, changes segments/state) */ samples_this_block = vgmstream_get_samples(data->segments[data->current_segment]); mixing_info(data->segments[data->current_segment], NULL, ¤t_channels); @@ -60,7 +60,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA } - samples_to_do = get_vgmstream_samples_to_do(samples_this_block, sample_count, vgmstream); + samples_to_do = decode_get_samples_to_do(samples_this_block, sample_count, vgmstream); if (samples_to_do > sample_count - samples_written) samples_to_do = sample_count - samples_written; if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */ diff --git a/src/vgmstream.c b/src/vgmstream.c index bf1573b8..c9b8a399 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -13,11 +13,12 @@ #include "base/render.h" #include "base/mixing.h" -static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM* (*init_vgmstream_function)(STREAMFILE*)); +typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*); +static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function); /* list of metadata parser functions that will recognize files, used on init */ -VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { +init_vgmstream_t init_vgmstream_functions[] = { init_vgmstream_adx, init_vgmstream_brstm, init_vgmstream_brwav, @@ -563,25 +564,25 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = { #endif }; +#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) +static const int init_vgmstream_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions); /*****************************************************************************/ /* INIT/META */ /*****************************************************************************/ -#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0])) /* internal version with all parameters */ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) { - int i, fcns_count; - if (!sf) return NULL; - fcns_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions); - /* try a series of formats, see which works */ - for (i = 0; i < fcns_count; i++) { + for (int i = 0; i < init_vgmstream_count; i++) { + init_vgmstream_t init_vgmstream_function = init_vgmstream_functions[i]; + + /* call init function and see if valid VGMSTREAM was returned */ - VGMSTREAM* vgmstream = (init_vgmstream_functions[i])(sf); + VGMSTREAM* vgmstream = init_vgmstream_function(sf); if (!vgmstream) continue; @@ -614,7 +615,7 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) { /* test if candidate for dual stereo */ if (vgmstream->channels == 1 && vgmstream->allow_dual_stereo == 1) { - try_dual_file_stereo(vgmstream, sf, init_vgmstream_functions[i]); + try_dual_file_stereo(vgmstream, sf, init_vgmstream_function); } /* clean as loops are readable metadata but loop fields may contain garbage @@ -714,9 +715,9 @@ void reset_vgmstream(VGMSTREAM* vgmstream) { * Otherwise hit_loop will be 0 and it will be copied over anyway when we * really hit the loop start. */ - reset_codec(vgmstream); + decode_reset(vgmstream); - reset_layout(vgmstream); + render_reset(vgmstream); /* note that this does not reset the constituent STREAMFILES * (vgmstream->ch[N].streamfiles' internal state, like internal offset, though shouldn't matter) */ @@ -737,7 +738,7 @@ VGMSTREAM* allocate_vgmstream(int channel_count, int loop_flag) { * - ch: config+state per channel, also modified by those * - start_vgmstream: vgmstream clone copied on init_vgmstream and restored on reset_vgmstream * - start_ch: ch clone copied on init_vgmstream and restored on reset_vgmstream - * - loop_ch: ch clone copied on loop start and restored on loop end (vgmstream_do_loop) + * - loop_ch: ch clone copied on loop start and restored on loop end (decode_do_loop) * - codec/layout_data: custom state for complex codecs or layouts, handled externally * * Here we only create the basic structs to be filled, and only after init_vgmstream it @@ -799,10 +800,10 @@ void close_vgmstream(VGMSTREAM* vgmstream) { if (!vgmstream) return; - free_codec(vgmstream); + decode_free(vgmstream); vgmstream->codec_data = NULL; - free_layout(vgmstream); + render_free(vgmstream); vgmstream->layout_data = NULL; @@ -915,7 +916,7 @@ void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target) { /* See if there is a second file which may be the second channel, given an already opened mono vgmstream. * If a suitable file is found, open it and change opened_vgmstream to a stereo vgmstream. */ -static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM*(*init_vgmstream_function)(STREAMFILE*)) { +static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function) { /* filename search pairs for dual file stereo */ static const char* const dfs_pairs[][2] = { {"L","R"}, /* most common in .dsp and .vag */ From 44925f38f5f1231bc6ccff04d616ea6c85a02b87 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 15 May 2023 16:37:59 +0200 Subject: [PATCH 12/13] build: workaround for foobar 2.0 64-bit issue --- msvc-build.ps1 | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/msvc-build.ps1 b/msvc-build.ps1 index 4c5cb293..1b9b0c10 100644 --- a/msvc-build.ps1 +++ b/msvc-build.ps1 @@ -270,8 +270,18 @@ function MakePackage Copy-Item $fb2kFiles32 bin/foobar2000/ -Recurse -Force Copy-Item $fb2kFiles64 bin/foobar2000/x64/ -Recurse -Force Remove-Item $fb2kFiles_remove -ErrorAction Ignore - Compress-Archive -Path bin/foobar2000/* bin/foo_input_vgmstream.zip -Force - Move-Item bin/foo_input_vgmstream.zip bin/foo_input_vgmstream.fb2k-component -Force + + # workaround for a foobar 2.0 64-bit bug: (earlier?) powershell creates zip paths with '\' (which seem + # non-standard), and apparently that confuses foobar when trying to unpack the zip + try { + # possibly available in github actions + & '7z' a -tzip bin/foo_input_vgmstream.fb2k-component bin/foobar2000/* + } catch { + # works for 32-bit at least + Compress-Archive -Path bin/foobar2000/* bin/foo_input_vgmstream.zip -Force + Move-Item bin/foo_input_vgmstream.zip bin/foo_input_vgmstream.fb2k-component -Force + } + Remove-Item -Path bin/foobar2000 -Recurse -ErrorAction Ignore } From a211dcf9b0747bd3fc53f028242326e986970bd0 Mon Sep 17 00:00:00 2001 From: bnnm Date: Mon, 15 May 2023 16:52:09 +0200 Subject: [PATCH 13/13] cleanup: tweaks --- src/streamtypes.h | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/streamtypes.h b/src/streamtypes.h index 1de682f0..5432756c 100644 --- a/src/streamtypes.h +++ b/src/streamtypes.h @@ -1,11 +1,12 @@ /* * streamtypes.h - widely used type definitions */ - - #ifndef _STREAMTYPES_H #define _STREAMTYPES_H +#include //size_t +#include //bool + #ifdef _MSC_VER /* Common versions: * - 1500: VS2008 @@ -15,25 +16,24 @@ * - 1900: VS2015 * - 1920: VS2019 */ -#if (_MSC_VER >= 1600) + #if (_MSC_VER >= 1600) + #include + #else + #include + #endif -#include + #if (_MSC_VER < 1800) && !defined(__cplusplus) + #define inline __inline + #endif + + #define strcasecmp _stricmp + #define strncasecmp _strnicmp + + #if (_MSC_VER < 1900) + #define snprintf _snprintf + #endif #else -#include -#endif -#if (_MSC_VER < 1800) && !defined(__cplusplus) -#define inline __inline -#endif - -#define strcasecmp _stricmp -#define strncasecmp _strnicmp - -#if (_MSC_VER < 1900) -#define snprintf _snprintf -#endif - -#else #include #endif /* _MSC_VER */