diff --git a/src/base/info.c b/src/base/info.c
index 5ee86a47..3f6d90a6 100644
--- a/src/base/info.c
+++ b/src/base/info.c
@@ -3,7 +3,7 @@
#include "../coding/coding.h"
#include "mixing.h"
#include "../util/channel_mappings.h"
-
+#include "../util/sf_utils.h"
/*******************************************************************************/
/* TEXT */
diff --git a/src/base/render.c b/src/base/render.c
index f5480efa..a7cc29de 100644
--- a/src/base/render.c
+++ b/src/base/render.c
@@ -285,7 +285,6 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
case layout_blocked_ivaud:
case layout_blocked_ea_swvr:
case layout_blocked_adm:
- case layout_blocked_bdsp:
case layout_blocked_ps2_iab:
case layout_blocked_vs_str:
case layout_blocked_rws:
diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj
index 3cbec036..8484a505 100644
--- a/src/libvgmstream.vcxproj
+++ b/src/libvgmstream.vcxproj
@@ -185,6 +185,7 @@
+
@@ -745,6 +746,7 @@
+
diff --git a/src/libvgmstream.vcxproj.filters b/src/libvgmstream.vcxproj.filters
index 7984edc6..7bfe3e72 100644
--- a/src/libvgmstream.vcxproj.filters
+++ b/src/libvgmstream.vcxproj.filters
@@ -380,6 +380,9 @@
util\Header Files
+
+ util\Header Files
+
util\Header Files
@@ -2056,6 +2059,9 @@
util\Source Files
+
+ util\Source Files
+
util\Source Files
diff --git a/src/meta/meta.h b/src/meta/meta.h
index ba3bbb40..18cae8af 100644
--- a/src/meta/meta.h
+++ b/src/meta/meta.h
@@ -4,6 +4,7 @@
#include "../vgmstream.h"
#include "../util/reader_sf.h"
#include "../util/reader_text.h"
+#include "../util/sf_utils.h"
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);
diff --git a/src/streamfile.c b/src/streamfile.c
index ef1c5e70..8566febf 100644
--- a/src/streamfile.c
+++ b/src/streamfile.c
@@ -1,8 +1,8 @@
#include "streamfile.h"
#include "util.h"
#include "vgmstream.h"
-#include "util/reader_sf.h"
#include "util/paths.h"
+#include "util/sf_utils.h"
#include
/* for dup/fdopen in some systems */
@@ -985,92 +985,10 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size) {
/* **************************************************** */
-/* change pathname's extension to another (or add it if extensionless) */
-static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) {
- char* extension = (char*)filename_extension(pathname);
- //todo safeops
- if (extension[0] == '\0') {
- strcat(pathname, ".");
- strcat(pathname, swap);
- }
- else {
- strcpy(extension, swap);
- }
-}
-
STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname) {
return sf->open(sf, pathname, STREAMFILE_DEFAULT_BUFFER_SIZE);
}
-STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) {
- char filename[PATH_LIMIT];
-
- get_streamfile_name(sf, filename, sizeof(filename));
-
- swap_extension(filename, sizeof(filename), ext);
-
- return open_streamfile(sf, filename);
-}
-
-STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) {
- char fullname[PATH_LIMIT];
- char partname[PATH_LIMIT];
- char *path, *name, *otherpath;
-
- if (!sf || !filename || !filename[0]) return NULL;
-
- get_streamfile_name(sf, fullname, sizeof(fullname));
-
- //todo normalize separators in a better way, safeops, improve copying
-
- /* check for non-normalized paths first (ex. txth) */
- path = strrchr(fullname, '/');
- otherpath = strrchr(fullname, '\\');
- if (otherpath > path) { //todo cast to ptr?
- /* foobar makes paths like "(fake protocol)://(windows path with \)".
- * Hack to work around both separators, though probably foo_streamfile
- * should just return and handle normalized paths without protocol. */
- path = otherpath;
- }
-
- if (path) {
- path[1] = '\0'; /* remove name after separator */
-
- strcpy(partname, filename);
- fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */
-
- /* normalize relative paths as don't work ok in some plugins */
- if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */
- name = partname + 2; /* ignore './' */
- }
- else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */
- char* pathprev;
-
- path[0] = '\0'; /* remove last separator so next call works */
- pathprev = strrchr(fullname,DIR_SEPARATOR);
- if (pathprev) {
- pathprev[1] = '\0'; /* remove prev dir after separator */
- name = partname + 3; /* ignore '../' */
- }
- else { /* let plugin handle? */
- path[0] = DIR_SEPARATOR;
- name = partname;
- }
- /* could work with more relative paths but whatevs */
- }
- else {
- name = partname;
- }
-
- strcat(fullname, name);
- }
- else {
- strcpy(fullname, filename);
- }
-
- return open_streamfile(sf, fullname);
-}
-
STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) {
char pathname[PATH_LIMIT];
@@ -1084,111 +1002,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) {
/* ************************************************************************* */
-int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
- char filename[PATH_LIMIT];
- const char* ext = NULL;
- const char* cmp_ext = NULL;
- const char* ststr_res = NULL;
- size_t ext_len, cmp_len;
-
- sf->get_name(sf, filename, sizeof(filename));
- ext = filename_extension(filename);
- ext_len = strlen(ext);
-
- cmp_ext = cmp_exts;
- do {
- ststr_res = strstr(cmp_ext, ",");
- cmp_len = ststr_res == NULL
- ? strlen(cmp_ext) /* total length if more not found */
- : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */
-
- if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0)
- return 1;
-
- cmp_ext = ststr_res;
- if (cmp_ext != NULL)
- cmp_ext = cmp_ext + 1; /* skip comma */
-
- } while (cmp_ext != NULL);
-
- return 0;
-}
-
-/* ************************************************************************* */
-
-/* copies name as-is (may include full path included) */
-void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) {
- sf->get_name(sf, buffer, size);
-}
-
-/* copies the filename without path */
-void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) {
- char foldername[PATH_LIMIT];
- const char* path;
-
-
- get_streamfile_name(sf, foldername, sizeof(foldername));
-
- //todo Windows CMD accepts both \\ and /, better way to handle this?
- path = strrchr(foldername,'\\');
- if (!path)
- path = strrchr(foldername,'/');
- if (path != NULL)
- path = path+1;
-
- //todo validate sizes and copy sensible max
- if (path) {
- strcpy(buffer, path);
- } else {
- strcpy(buffer, foldername);
- }
-}
-
-/* copies the filename without path or extension */
-void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) {
- char* ext;
-
- get_streamfile_filename(sf, buffer, size);
-
- ext = strrchr(buffer,'.');
- if (ext) {
- ext[0] = '\0'; /* remove .ext from buffer */
- }
-}
-
-/* copies path removing name (NULL when if filename has no path) */
-void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) {
- const char* path;
-
- get_streamfile_name(sf, buffer, size);
-
- path = strrchr(buffer,DIR_SEPARATOR);
- if (path!=NULL) path = path+1; /* includes "/" */
-
- if (path) {
- buffer[path - buffer] = '\0';
- } else {
- buffer[0] = '\0';
- }
-}
-
-/* copies extension only */
-void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) {
- char filename[PATH_LIMIT];
- const char* extension = NULL;
-
- get_streamfile_name(sf, filename, sizeof(filename));
- extension = filename_extension(filename);
- if (!extension) {
- buffer[0] = '\n';
- }
- else {
- strncpy(buffer, extension, size); //todo use something better
- }
-}
-
-/* ************************************************************************* */
-
/* debug util, mainly for custom IO testing */
void dump_streamfile(STREAMFILE* sf, int num) {
#ifdef VGM_DEBUG_OUTPUT
diff --git a/src/streamfile.h b/src/streamfile.h
index 476372c3..d3e89091 100644
--- a/src/streamfile.h
+++ b/src/streamfile.h
@@ -130,15 +130,6 @@ STREAMFILE* open_multifile_streamfile_f(STREAMFILE** sfs, size_t sfs_size);
* Just a wrapper, to avoid having to access the STREAMFILE's callbacks directly. */
STREAMFILE* open_streamfile(STREAMFILE* sf, const char* pathname);
-/* Opens a STREAMFILE from a base pathname + new extension
- * Can be used to get companion headers. */
-STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext);
-
-/* Opens a STREAMFILE from a base path + new filename.
- * Can be used to get companion files. Relative paths like
- * './filename', '../filename', 'dir/filename' also work. */
-STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename);
-
/* Reopen a STREAMFILE with a different buffer size, for fine-tuned bigfile parsing.
* Uses default buffer size when buffer_size is 0 */
STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size);
@@ -161,18 +152,6 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) {
}
-/* various STREAMFILE helpers functions */
-
-/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix").
- * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */
-int check_extensions(STREAMFILE* sf, const char* cmp_exts);
-
-/* filename helpers */
-void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size);
-void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size);
-void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size);
-void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size);
-void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size);
-
void dump_streamfile(STREAMFILE* sf, int num);
+
#endif
diff --git a/src/util/companion_files.c b/src/util/companion_files.c
index 253b18e3..b126a49e 100644
--- a/src/util/companion_files.c
+++ b/src/util/companion_files.c
@@ -1,7 +1,8 @@
#include "companion_files.h"
#include "paths.h"
#include "../vgmstream.h"
-#include "../util/reader_text.h"
+#include "reader_text.h"
+#include "sf_utils.h"
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
diff --git a/src/util/sf_utils.c b/src/util/sf_utils.c
new file mode 100644
index 00000000..d0cd061e
--- /dev/null
+++ b/src/util/sf_utils.c
@@ -0,0 +1,192 @@
+#include "sf_utils.h"
+#include "../vgmstream.h"
+#include "reader_sf.h"
+#include "paths.h"
+
+
+/* change pathname's extension to another (or add it if extensionless) */
+static void swap_extension(char* pathname, /*size_t*/ int pathname_len, const char* swap) {
+ char* extension = (char*)filename_extension(pathname);
+ //todo safeops
+ if (extension[0] == '\0') {
+ strcat(pathname, ".");
+ strcat(pathname, swap);
+ }
+ else {
+ strcpy(extension, swap);
+ }
+}
+
+STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext) {
+ char filename[PATH_LIMIT];
+
+ get_streamfile_name(sf, filename, sizeof(filename));
+
+ swap_extension(filename, sizeof(filename), ext);
+
+ return open_streamfile(sf, filename);
+}
+
+STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename) {
+ char fullname[PATH_LIMIT];
+ char partname[PATH_LIMIT];
+ char *path, *name, *otherpath;
+
+ if (!sf || !filename || !filename[0]) return NULL;
+
+ get_streamfile_name(sf, fullname, sizeof(fullname));
+
+ //todo normalize separators in a better way, safeops, improve copying
+
+ /* check for non-normalized paths first (ex. txth) */
+ path = strrchr(fullname, '/');
+ otherpath = strrchr(fullname, '\\');
+ if (otherpath > path) { //todo cast to ptr?
+ /* foobar makes paths like "(fake protocol)://(windows path with \)".
+ * Hack to work around both separators, though probably foo_streamfile
+ * should just return and handle normalized paths without protocol. */
+ path = otherpath;
+ }
+
+ if (path) {
+ path[1] = '\0'; /* remove name after separator */
+
+ strcpy(partname, filename);
+ fix_dir_separators(partname); /* normalize to DIR_SEPARATOR */
+
+ /* normalize relative paths as don't work ok in some plugins */
+ if (partname[0] == '.' && partname[1] == DIR_SEPARATOR) { /* './name' */
+ name = partname + 2; /* ignore './' */
+ }
+ else if (partname[0] == '.' && partname[1] == '.' && partname[2] == DIR_SEPARATOR) { /* '../name' */
+ char* pathprev;
+
+ path[0] = '\0'; /* remove last separator so next call works */
+ pathprev = strrchr(fullname,DIR_SEPARATOR);
+ if (pathprev) {
+ pathprev[1] = '\0'; /* remove prev dir after separator */
+ name = partname + 3; /* ignore '../' */
+ }
+ else { /* let plugin handle? */
+ path[0] = DIR_SEPARATOR;
+ name = partname;
+ }
+ /* could work with more relative paths but whatevs */
+ }
+ else {
+ name = partname;
+ }
+
+ strcat(fullname, name);
+ }
+ else {
+ strcpy(fullname, filename);
+ }
+
+ return open_streamfile(sf, fullname);
+}
+
+/* ************************************************************************* */
+
+int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
+ char filename[PATH_LIMIT];
+ const char* ext = NULL;
+ const char* cmp_ext = NULL;
+ const char* ststr_res = NULL;
+ size_t ext_len, cmp_len;
+
+ sf->get_name(sf, filename, sizeof(filename));
+ ext = filename_extension(filename);
+ ext_len = strlen(ext);
+
+ cmp_ext = cmp_exts;
+ do {
+ ststr_res = strstr(cmp_ext, ",");
+ cmp_len = ststr_res == NULL
+ ? strlen(cmp_ext) /* total length if more not found */
+ : (intptr_t)ststr_res - (intptr_t)cmp_ext; /* find next ext; ststr_res should always be greater than cmp_ext, resulting in a positive cmp_len */
+
+ if (ext_len == cmp_len && strncasecmp(ext,cmp_ext, ext_len) == 0)
+ return 1;
+
+ cmp_ext = ststr_res;
+ if (cmp_ext != NULL)
+ cmp_ext = cmp_ext + 1; /* skip comma */
+
+ } while (cmp_ext != NULL);
+
+ return 0;
+}
+
+/* ************************************************************************* */
+
+/* copies name as-is (may include full path included) */
+void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) {
+ sf->get_name(sf, buffer, size);
+}
+
+/* copies the filename without path */
+void get_streamfile_filename(STREAMFILE* sf, char* buffer, size_t size) {
+ char foldername[PATH_LIMIT];
+ const char* path;
+
+
+ get_streamfile_name(sf, foldername, sizeof(foldername));
+
+ //todo Windows CMD accepts both \\ and /, better way to handle this?
+ path = strrchr(foldername,'\\');
+ if (!path)
+ path = strrchr(foldername,'/');
+ if (path != NULL)
+ path = path+1;
+
+ //todo validate sizes and copy sensible max
+ if (path) {
+ strcpy(buffer, path);
+ } else {
+ strcpy(buffer, foldername);
+ }
+}
+
+/* copies the filename without path or extension */
+void get_streamfile_basename(STREAMFILE* sf, char* buffer, size_t size) {
+ char* ext;
+
+ get_streamfile_filename(sf, buffer, size);
+
+ ext = strrchr(buffer,'.');
+ if (ext) {
+ ext[0] = '\0'; /* remove .ext from buffer */
+ }
+}
+
+/* copies path removing name (NULL when if filename has no path) */
+void get_streamfile_path(STREAMFILE* sf, char* buffer, size_t size) {
+ const char* path;
+
+ get_streamfile_name(sf, buffer, size);
+
+ path = strrchr(buffer,DIR_SEPARATOR);
+ if (path!=NULL) path = path+1; /* includes "/" */
+
+ if (path) {
+ buffer[path - buffer] = '\0';
+ } else {
+ buffer[0] = '\0';
+ }
+}
+
+/* copies extension only */
+void get_streamfile_ext(STREAMFILE* sf, char* buffer, size_t size) {
+ char filename[PATH_LIMIT];
+ const char* extension = NULL;
+
+ get_streamfile_name(sf, filename, sizeof(filename));
+ extension = filename_extension(filename);
+ if (!extension) {
+ buffer[0] = '\n';
+ }
+ else {
+ strncpy(buffer, extension, size); //todo use something better
+ }
+}
diff --git a/src/util/sf_utils.h b/src/util/sf_utils.h
new file mode 100644
index 00000000..c1260bfe
--- /dev/null
+++ b/src/util/sf_utils.h
@@ -0,0 +1,29 @@
+#ifndef _SF_UTILS_H
+#define _SF_UTILS_H
+#include "../streamfile.h"
+
+
+
+/* Opens a STREAMFILE from a base pathname + new extension
+ * Can be used to get companion headers. */
+STREAMFILE* open_streamfile_by_ext(STREAMFILE* sf, const char* ext);
+
+/* Opens a STREAMFILE from a base path + new filename.
+ * Can be used to get companion files. Relative paths like
+ * './filename', '../filename', 'dir/filename' also work. */
+STREAMFILE* open_streamfile_by_filename(STREAMFILE* sf, const char* filename);
+
+/* various STREAMFILE helpers functions */
+
+/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix").
+ * Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */
+int check_extensions(STREAMFILE* sf, const char* cmp_exts);
+
+/* filename helpers */
+void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size);
+void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size);
+void get_streamfile_basename(STREAMFILE* sf, char* buf, size_t size);
+void get_streamfile_path(STREAMFILE* sf, char* buf, size_t size);
+void get_streamfile_ext(STREAMFILE* sf, char* buf, size_t size);
+
+#endif
diff --git a/src/vgmstream.c b/src/vgmstream.c
index c2b61e78..68deec24 100644
--- a/src/vgmstream.c
+++ b/src/vgmstream.c
@@ -12,6 +12,7 @@
#include "base/decode.h"
#include "base/render.h"
#include "base/mixing.h"
+#include "util/sf_utils.h"
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);