mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
Merge pull request #930 from bnnm/log-etc
- Add log functions to show errors to user - Allow TXTH codec strings in name_table - Add .wve for EA SCHl [Madden NFL 99 (PC)] - build tweaks
This commit is contained in:
commit
4cda04d025
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ ifeq ($(VGMSTREAM_VERSION),)
|
||||
else
|
||||
VGMSTREAM_VERSION=$(VGMSTREAM_VERSION)
|
||||
endif
|
||||
DEF_CFLAGS += -DVGMSTREAM_VERSION_AUTO
|
||||
DEF_CFLAGS += -DVGMSTREAM_VERSION_AUTO -DVGM_LOG_OUTPUT
|
||||
|
||||
###############################################################################
|
||||
### external defs
|
||||
|
23
README.md
23
README.md
@ -248,13 +248,13 @@ loop info, or apply subtle fixes, but is also limited in some ways (like ignorin
|
||||
standard tags). `.vgmstream` is a catch-all extension that may work as a last resort
|
||||
to make a file playable.
|
||||
|
||||
Some plugins have options that allow common extensions to be played, making any
|
||||
Some plugins have options that allow "*common extensions*" to be played, making any
|
||||
renaming unnecessary. You may need to adjust plugin priority in player's options
|
||||
first. Note that vgmstream also accepts certain extension-less files as-is too.
|
||||
|
||||
Similarly, vgmstream has a curated list of known extensions, that plugins may take
|
||||
into account and ignore unknowns. Through *TXTH* you can make unknown files playable,
|
||||
but you also need to either rename or set plugin options to allow "unknown extensions"
|
||||
but you also need to either rename or set plugin options to allow "*unknown extensions*"
|
||||
(or, preferably, report this new extension so it can be added to the known list).
|
||||
|
||||
It's also possible to make a .txtp file that opens files with those common/unknown
|
||||
@ -356,9 +356,8 @@ the only option is renaming the companion extension to lowercase.
|
||||
A particularly nasty variation of that is that some formats load files by full
|
||||
name (e.g. `STREAM.SS0`), but sometimes the actual filename is in other case
|
||||
(`Stream.ss0`), and some files could even point to that with yet another case.
|
||||
You could try adding *symlinks* in various upper/lower/mixed cases to handle this.
|
||||
Currently there isn't any way to know what exact name is needed (other than
|
||||
hex-editting), though only a few formats do this, mainly *Ubisoft* banks.
|
||||
You could try adding *symlinks* in various upper/lower/mixed cases to handle this,
|
||||
though only a few formats do this, mainly *Ubisoft* banks.
|
||||
|
||||
Regular formats without companion files should work fine in upper/lowercase.
|
||||
|
||||
@ -514,6 +513,20 @@ You can also choose which channels to play using *TXTP*. For example, create
|
||||
a file named `song.adx#C1,2.txtp` to play only channels 1 and 2 from `song.adx`.
|
||||
*TXTP* also has command to set how files are downmixed.
|
||||
|
||||
### Logged errors and unplayable supported files
|
||||
Some formats should normally play, but somehow don't. In those cases plugins
|
||||
can print vgmstream's error info to console (for example, `.fsb` with an unknown
|
||||
codec, `.hca/awb` with missing decryption key, bank has no audio, `.txth` is
|
||||
malformed, or `.wav` has an incorrectly ripped size).
|
||||
|
||||
Console location and format depends on plugin:
|
||||
- *foobar2000*: found in *View menu > Console*
|
||||
- *Winamp*: open vgmstream's config (*Preferences... > Plug-ins > vgmstream* + *Configure*
|
||||
button) then press "Open Log"
|
||||
- *Audacious*: start with `audacious -V` from terminal
|
||||
- CLI utils: printed to stdout directly
|
||||
|
||||
Only a few errors are printed ATM but may be helpful for more common cases.
|
||||
|
||||
## Tagging
|
||||
Some of vgmstream's plugins support simple read-only tagging via external files.
|
||||
|
@ -6,7 +6,7 @@ inputplugindir = $(plugindir)/$(INPUT_PLUGIN_DIR)
|
||||
inputplugin_LTLIBRARIES = libvgmstream.la
|
||||
|
||||
AM_MAKEFLAGS=-f Makefile.autotools
|
||||
AM_CXXFLAGS = -DVGMSTREAM_VERSION_AUTO -Wall -std=c++11 -fpermissive -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/ $(AUDACIOUS_CFLAGS) $(GTK_CFLAGS)
|
||||
AM_CXXFLAGS = -DVGMSTREAM_VERSION_AUTO -DVGM_LOG_OUTPUT -Wall -std=c++11 -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/ $(AUDACIOUS_CFLAGS) $(GTK_CFLAGS)
|
||||
AM_LIBS =
|
||||
|
||||
# sources/headers are updated automatically by ./bootstrap script (not all headers are needed though)
|
||||
|
@ -133,18 +133,29 @@ bool VgmstreamPlugin::is_our_file(const char * filename, VFSFile & file) {
|
||||
return vgmstream_ctx_is_valid(filename, &cfg) > 0 ? true : false;
|
||||
}
|
||||
|
||||
|
||||
/* default output in audacious is: "INFO/DEBUG plugin.cc:xxx [(fn name)]: (msg)" */
|
||||
static void vgmstream_log(int level, const char* str) {
|
||||
if (level == VGM_LOG_LEVEL_DEBUG)
|
||||
AUDDBG("%s", str);
|
||||
else
|
||||
AUDINFO("%s", str);
|
||||
}
|
||||
|
||||
// called on startup (main thread)
|
||||
bool VgmstreamPlugin::init() {
|
||||
AUDINFO("plugin start\n");
|
||||
AUDINFO("vgmstream plugin start\n");
|
||||
|
||||
vgmstream_settings_load();
|
||||
|
||||
vgmstream_set_log_callback(VGM_LOG_LEVEL_ALL, (void*)&vgmstream_log);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called on stop (main thread)
|
||||
void VgmstreamPlugin::cleanup() {
|
||||
AUDINFO("plugin end\n");
|
||||
AUDINFO("vgmstream plugin end\n");
|
||||
|
||||
vgmstream_settings_save();
|
||||
}
|
||||
|
29
bootstrap
29
bootstrap
@ -4,26 +4,19 @@
|
||||
|
||||
# gets all files and updates .am scripts to avoid having to do manually (frowned upon by automake, whatevs)
|
||||
# maybe there is a better way or place for this
|
||||
VGMSTREAM_SRCS=`(cd ./src/ && ls *.c) | tr '\n' ' '`
|
||||
VGMSTREAM_HDRS=`(cd ./src/ && ls *.h) | tr '\n' ' '`
|
||||
CODING_SRCS=`(cd ./src/coding/ && ls *.c) | tr '\n' ' '`
|
||||
CODING_HDRS=`(cd ./src/coding/ && ls *.h) | tr '\n' ' '`
|
||||
LAYOUT_SRCS=`(cd ./src/layout/ && ls *.c) | tr '\n' ' '`
|
||||
LAYOUT_HDRS=`(cd ./src/layout/ && ls *.h) | tr '\n' ' '`
|
||||
META_SRCS=`(cd ./src/meta/ && ls *.c) | tr '\n' ' '`
|
||||
META_HDRS=`(cd ./src/meta/ && ls *.h) | tr '\n' ' '`
|
||||
VGMSTREAM_SRCS=`(cd ./src/ && ls *.c coding/*.c layout/*.c meta/*.c util/*.c) | tr '\n' ' '`
|
||||
VGMSTREAM_HDRS=`(cd ./src/ && ls *.h coding/*.h layout/*.h meta/*.h util/*.h) | tr '\n' ' '`
|
||||
AUDACIOUS_SRCS=`(cd ./audacious/ && ls *.cc) | tr '\n' ' '`
|
||||
AUDACIOUS_HDRS=`(cd ./audacious/ && ls *.h) | tr '\n' ' '`
|
||||
sed -i -e "s/libvgmstream_la_SOURCES =.*/libvgmstream_la_SOURCES = $VGMSTREAM_SRCS/g" ./src/Makefile.autotools.am
|
||||
sed -i -e "s/EXTRA_DIST =.*/EXTRA_DIST = $VGMSTREAM_HDRS/g" ./src/Makefile.autotools.am
|
||||
sed -i -e "s/libcoding_la_SOURCES =.*/libcoding_la_SOURCES = $CODING_SRCS/g" ./src/coding/Makefile.autotools.am
|
||||
sed -i -e "s/EXTRA_DIST =.*/EXTRA_DIST = $CODING_HDRS/g" ./src/coding/Makefile.autotools.am
|
||||
sed -i -e "s/liblayout_la_SOURCES =.*/liblayout_la_SOURCES = $LAYOUT_SRCS/g" ./src/layout/Makefile.autotools.am
|
||||
sed -i -e "s/EXTRA_DIST =.*/EXTRA_DIST = $LAYOUT_HDRS/g" ./src/layout/Makefile.autotools.am
|
||||
sed -i -e "s/libmeta_la_SOURCES =.*/libmeta_la_SOURCES = $META_SRCS/g" ./src/meta/Makefile.autotools.am
|
||||
sed -i -e "s/EXTRA_DIST =.*/EXTRA_DIST = $META_HDRS/g" ./src/meta/Makefile.autotools.am
|
||||
sed -i -e "s/libvgmstream_la_SOURCES =.*/libvgmstream_la_SOURCES = $AUDACIOUS_SRCS/g" ./audacious/Makefile.autotools.am
|
||||
sed -i -e "s/EXTRA_DIST =.*/EXTRA_DIST = $AUDACIOUS_HDRS/g" ./audacious/Makefile.autotools.am
|
||||
|
||||
# in case some distro sed doesn't support | separator and must use /, all slashes need to be escaped first
|
||||
#VGMSTREAM_SRCS=$(echo "$VGMSTREAM_SRCS" | sed 's/\//\\\//g')
|
||||
|
||||
sed -i -e "s|libvgmstream_la_SOURCES =.*|libvgmstream_la_SOURCES = $VGMSTREAM_SRCS|g" ./src/Makefile.autotools.am
|
||||
sed -i -e "s|EXTRA_DIST =.*|EXTRA_DIST = $VGMSTREAM_HDRS|g" ./src/Makefile.autotools.am
|
||||
|
||||
sed -i -e "s|libvgmstream_la_SOURCES =.*|libvgmstream_la_SOURCES = $AUDACIOUS_SRCS|g" ./audacious/Makefile.autotools.am
|
||||
sed -i -e "s|EXTRA_DIST =.*|EXTRA_DIST = $AUDACIOUS_HDRS|g" ./audacious/Makefile.autotools.am
|
||||
|
||||
# make version to show in about dialogs
|
||||
# again, not very pretty
|
||||
|
@ -3,6 +3,16 @@
|
||||
add_executable(vgmstream_cli
|
||||
vgmstream_cli.c)
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(vgmstream_cli PROPERTIES
|
||||
PREFIX ""
|
||||
OUTPUT_NAME "test")
|
||||
else()
|
||||
set_target_properties(vgmstream_cli PROPERTIES
|
||||
PREFIX ""
|
||||
OUTPUT_NAME "vgmstream-cli")
|
||||
endif()
|
||||
|
||||
# Link to the vgmstream library
|
||||
target_link_libraries(vgmstream_cli libvgmstream)
|
||||
|
||||
|
@ -6,7 +6,7 @@ if HAVE_LIBAO
|
||||
bin_PROGRAMS += vgmstream123
|
||||
endif
|
||||
|
||||
AM_CFLAGS = -DVGMSTREAM_VERSION_AUTO -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/ $(AO_CFLAGS)
|
||||
AM_CFLAGS = -DVGMSTREAM_VERSION_AUTO -DVGM_LOG_OUTPUT -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/ $(AO_CFLAGS)
|
||||
AM_MAKEFLAGS = -f Makefile.autotools
|
||||
|
||||
vgmstream_cli_SOURCES = vgmstream_cli.c
|
||||
|
@ -272,6 +272,8 @@ static int play_vgmstream(const char* filename, song_settings_t* cfg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
vgmstream_set_log_stdout(VGM_LOG_LEVEL_ALL);
|
||||
|
||||
sf->stream_index = cfg->stream_index;
|
||||
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
||||
close_streamfile(sf);
|
||||
|
@ -694,6 +694,8 @@ static int convert_file(cli_config* cfg) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vgmstream_set_log_stdout(VGM_LOG_LEVEL_ALL);
|
||||
|
||||
sf->stream_index = cfg->subsong_index;
|
||||
vgmstream = init_vgmstream_from_STREAMFILE(sf);
|
||||
close_streamfile(sf);
|
||||
|
@ -24,6 +24,8 @@ macro(setup_target TARGET)
|
||||
target_link_libraries(${TARGET} m)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(${TARGET} PRIVATE VGM_LOG_OUTPUT)
|
||||
|
||||
if(USE_MPEG)
|
||||
target_compile_definitions(${TARGET} PRIVATE VGM_USE_MPEG)
|
||||
if(WIN32)
|
||||
|
@ -88,9 +88,6 @@ AC_PATH_XTRA
|
||||
AC_OUTPUT([
|
||||
Makefile.autotools
|
||||
src/Makefile.autotools
|
||||
src/coding/Makefile.autotools
|
||||
src/layout/Makefile.autotools
|
||||
src/meta/Makefile.autotools
|
||||
audacious/Makefile.autotools
|
||||
cli/Makefile.autotools
|
||||
])
|
||||
|
@ -117,10 +117,10 @@ All of these options are of type BOOL and can be set to either `ON` or `OFF`. Mo
|
||||
- **USE_FFMPEG**: Chooses if you wish to use FFmpeg for support of many codecs. The default is `ON`. `FFMPEG_PATH` can also be given, so it can use official/external SDK instead of the one used in vgmstream project.
|
||||
- **USE_MAIATRAC3PLUS**: Chooses if you wish to use MAIATRAC3+ for support of ATRAC3+. The default is `OFF`. It is not recommended to enable.
|
||||
- **USE_G7221**: Chooses if you wish to use G7221 for support of ITU-T G.722.1 annex C. The default is `ON`.
|
||||
- **USE_G719**: Chooses if you wish to use libg719_decode for support ITU-T G.719. The default is `ON`.
|
||||
|
||||
The following options are currently only available for Windows:
|
||||
|
||||
- **USE_G719**: Chooses if you wish to use libg719_decode for support ITU-T G.719. The default is `ON`.
|
||||
- **USE_ATRAC9**: Chooses if you wish to use LibAtrac9 for support of ATRAC9. The default is `ON`.
|
||||
- **USE_CELT**: Chooses if you wish to use libcelt for support of FSB CELT versions 0.6.1 and 0.11.0. The default is `ON`.
|
||||
- **USE_SPEEX**: Chooses if you wish to use libspeex for support of SPEEX. The default is `ON`.
|
||||
|
@ -449,7 +449,7 @@ Inside the table you define lines mapping a filename to a bunch of values, in th
|
||||
# put no name before the : to set default values
|
||||
: (value1), (...), (valueN)
|
||||
```
|
||||
Then I'll find your current file name, and you can then reference its numbers from the list as a `name_value` field, like `base_offset = name_value`, `start_offset = 0x1000 + name_value1`, `interleave = name_value5`, etc. `(filename)` can be with or without extension (like `bgm01.vag` or just `bgm01`), and if the file's name isn't found it'll use default values, and if those aren't defined you'll get 0 instead. Being "values" they can use math or offsets too (`bgm05: 5*0x010`).
|
||||
Then I'll find your current file name, and you can then reference its numbers from the list as a `name_value` field, like `base_offset = name_value`, `start_offset = 0x1000 + name_value1`, `interleave = name_value5`, etc. `(filename)` can be with or without extension (like `bgm01.vag` or just `bgm01`), and if the file's name isn't found it'll use default values, and if those aren't defined you'll get 0 instead. Being "values" they can use math or offsets too (`bgm05: 5*0x010`). You can also set a codec string too (`bgm01: PCM16LE`; `codec = name_value`).
|
||||
|
||||
You can use wildcards to match multiple names too (it stops on first name that matches), and UTF-8 names should work, case insensitive even.
|
||||
```
|
||||
|
@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.18)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(libg719_decode)
|
||||
|
||||
file(GLOB_RECURSE SOURCES "reference_code/*.c")
|
||||
|
@ -39,6 +39,10 @@ extern "C" {
|
||||
#define PLUGIN_FILENAME "foo_input_vgmstream.dll"
|
||||
|
||||
|
||||
static void log_callback(int level, const char* str) {
|
||||
console::formatter() /*<< "vgmstream: "*/ << str;
|
||||
}
|
||||
|
||||
// called every time a file is added to the playlist (to get info) or when playing
|
||||
input_vgmstream::input_vgmstream() {
|
||||
vgmstream = NULL;
|
||||
@ -64,6 +68,8 @@ input_vgmstream::input_vgmstream() {
|
||||
override_title = false;
|
||||
|
||||
load_settings();
|
||||
|
||||
vgmstream_set_log_callback(VGM_LOG_LEVEL_ALL, &log_callback);
|
||||
}
|
||||
|
||||
// called on stop or when playlist info has been read
|
||||
|
@ -4,6 +4,8 @@ file(GLOB LAYOUT_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/layout/*.h")
|
||||
file(GLOB LAYOUT_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/layout/*.c")
|
||||
file(GLOB META_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/meta/*.h")
|
||||
file(GLOB META_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/meta/*.c")
|
||||
file(GLOB UTIL_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/util/*.h")
|
||||
file(GLOB UTIL_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/util/*.c")
|
||||
set(EXT_HEADERS
|
||||
${VGM_SOURCE_DIR}/ext_includes/pstdint.h)
|
||||
file(GLOB MAIN_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
|
||||
@ -16,10 +18,12 @@ list(REMOVE_ITEM MAIN_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/stack_alloc.h)
|
||||
source_group("Header Files\\coding" FILES ${CODING_HEADERS})
|
||||
source_group("Header Files\\layout" FILES ${LAYOUT_HEADERS})
|
||||
source_group("Header Files\\meta" FILES ${META_HEADERS})
|
||||
source_group("Header Files\\util" FILES ${UTIL_HEADERS})
|
||||
source_group("Header Files\\ext" FILES ${EXT_HEADERS})
|
||||
source_group("Source Files\\coding" FILES ${CODING_SOURCES})
|
||||
source_group("Source Files\\layout" FILES ${LAYOUT_SOURCES})
|
||||
source_group("Source Files\\meta" FILES ${META_SOURCES})
|
||||
source_group("Source Files\\util" FILES ${UTIL_SOURCES})
|
||||
|
||||
add_library(libvgmstream STATIC
|
||||
${CODING_HEADERS}
|
||||
@ -28,6 +32,8 @@ add_library(libvgmstream STATIC
|
||||
${LAYOUT_SOURCES}
|
||||
${META_HEADERS}
|
||||
${META_SOURCES}
|
||||
${UTIL_HEADERS}
|
||||
${UTIL_SOURCES}
|
||||
${EXT_HEADERS}
|
||||
${MAIN_HEADERS}
|
||||
${MAIN_SOURCES})
|
||||
@ -39,4 +45,5 @@ target_include_directories(libvgmstream PRIVATE
|
||||
${VGM_SOURCE_DIR}/ext_includes
|
||||
coding
|
||||
layout
|
||||
meta)
|
||||
meta
|
||||
util)
|
||||
|
@ -21,9 +21,9 @@ META_SRCS = $(wildcard meta/*.c)
|
||||
META_OBJS = $(patsubst %.c,%.o,$(META_SRCS))
|
||||
OBJECTS += $(META_OBJS)
|
||||
|
||||
EXT_LIBS_SRCS = $(wildcard ../ext_libs/*.c)
|
||||
EXT_LIBS_OBJS = $(patsubst %.c,%.o,$(EXT_LIBS_SRCS))
|
||||
OBJECTS += $(EXT_LIBS_OBJS)
|
||||
UTIL_SRCS = $(wildcard util/*.c)
|
||||
UTIL_OBJS = $(patsubst %.c,%.o,$(UTIL_SRCS))
|
||||
OBJECTS += $(UTIL_OBJS)
|
||||
|
||||
|
||||
libvgmstream.a: $(OBJECTS)
|
||||
|
@ -1,18 +1,21 @@
|
||||
## vgmstream autotools script
|
||||
|
||||
#noinst_LTLIBRARIES = libvgmstream.la
|
||||
lib_LTLIBRARIES = libvgmstream.la
|
||||
|
||||
AM_CFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/
|
||||
AM_MAKEFLAGS=-f Makefile.autotools
|
||||
|
||||
SUBDIRS = coding layout meta
|
||||
SUBDIRS =
|
||||
|
||||
# sources/headers are updated automatically by ./bootstrap script (not all headers are needed though)
|
||||
libvgmstream_la_LDFLAGS = coding/libcoding.la layout/liblayout.la meta/libmeta.la
|
||||
libvgmstream_la_LDFLAGS =
|
||||
libvgmstream_la_SOURCES = (auto-updated)
|
||||
libvgmstream_la_LIBADD = -lm
|
||||
EXTRA_DIST = (auto-updated)
|
||||
|
||||
AM_CFLAGS += -DVGM_LOG_OUTPUT
|
||||
|
||||
AM_CFLAGS += -DVGM_USE_G7221
|
||||
|
||||
if HAVE_VORBIS
|
||||
|
@ -1,31 +0,0 @@
|
||||
## vgmstream autotools script
|
||||
|
||||
noinst_LTLIBRARIES = libcoding.la
|
||||
|
||||
AM_CFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/
|
||||
AM_MAKEFLAGS=-f Makefile.autotools
|
||||
|
||||
# sources/headers are updated automatically by ./bootstrap script (not all headers are needed though)
|
||||
libcoding_la_LDFLAGS =
|
||||
libcoding_la_SOURCES = (auto-updated)
|
||||
EXTRA_DIST = (auto-updated)
|
||||
|
||||
AM_CFLAGS += -DVGM_USE_G7221
|
||||
|
||||
if HAVE_VORBIS
|
||||
if HAVE_VORBISFILE
|
||||
AM_CFLAGS += -DVGM_USE_VORBIS
|
||||
endif
|
||||
endif
|
||||
|
||||
if HAVE_LIBMPG123
|
||||
AM_CFLAGS += -DVGM_USE_MPEG
|
||||
endif
|
||||
|
||||
if HAVE_LIBSPEEX
|
||||
AM_CFLAGS += -DVGM_USE_SPEEX
|
||||
endif
|
||||
|
||||
if HAVE_FFMPEG
|
||||
AM_CFLAGS += -DVGM_USE_FFMPEG
|
||||
endif
|
@ -1,31 +0,0 @@
|
||||
## vgmstream autotools script
|
||||
|
||||
noinst_LTLIBRARIES = liblayout.la
|
||||
|
||||
AM_CFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/
|
||||
AM_MAKEFLAGS=-f Makefile.autotools
|
||||
|
||||
# sources/headers are updated automatically by ./bootstrap script (not all headers are needed though)
|
||||
liblayout_la_LDFLAGS =
|
||||
liblayout_la_SOURCES = (auto-updated)
|
||||
EXTRA_DIST = (auto-updated)
|
||||
|
||||
AM_CFLAGS += -DVGM_USE_G7221
|
||||
|
||||
if HAVE_VORBIS
|
||||
if HAVE_VORBISFILE
|
||||
AM_CFLAGS += -DVGM_USE_VORBIS
|
||||
endif
|
||||
endif
|
||||
|
||||
if HAVE_LIBMPG123
|
||||
AM_CFLAGS += -DVGM_USE_MPEG
|
||||
endif
|
||||
|
||||
if HAVE_LIBSPEEX
|
||||
AM_CFLAGS += -DVGM_USE_SPEEX
|
||||
endif
|
||||
|
||||
if HAVE_FFMPEG
|
||||
AM_CFLAGS += -DVGM_USE_FFMPEG
|
||||
endif
|
@ -59,7 +59,7 @@
|
||||
<ClCompile>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<AdditionalIncludeDirectories>../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>WIN32;VGMSTREAM_VERSION_AUTO;VGM_LOG_OUTPUT;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
@ -72,7 +72,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>_WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_LOG_OUTPUT;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
@ -168,6 +168,8 @@
|
||||
<ClInclude Include="coding\tac_decoder_lib_data.h" />
|
||||
<ClInclude Include="coding\tac_decoder_lib_ops.h" />
|
||||
<ClInclude Include="layout\layout.h" />
|
||||
<ClInclude Include="util\chunks.h" />
|
||||
<ClInclude Include="util\log.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="coding\at3plus_decoder.c" />
|
||||
@ -708,6 +710,8 @@
|
||||
<ClCompile Include="layout\blocked_xa.c" />
|
||||
<ClCompile Include="layout\blocked_xa_aiff.c" />
|
||||
<ClCompile Include="layout\blocked_xvas.c" />
|
||||
<ClCompile Include="util\chunks.c" />
|
||||
<ClCompile Include="util\log.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
|
@ -302,6 +302,12 @@
|
||||
<ClInclude Include="meta\encrypted_bgm_streamfile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\chunks.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="formats.c">
|
||||
@ -1918,5 +1924,11 @@
|
||||
<ClCompile Include="meta\sbk.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\chunks.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\log.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -1,31 +0,0 @@
|
||||
## vgmstream autotools script
|
||||
|
||||
noinst_LTLIBRARIES = libmeta.la
|
||||
|
||||
AM_CFLAGS = -DVAR_ARRAYS -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/ext_includes/
|
||||
AM_MAKEFLAGS=-f Makefile.autotools
|
||||
|
||||
# sources/headers are updated automatically by ./bootstrap script (not all headers are needed though)
|
||||
libmeta_la_LDFLAGS =
|
||||
libmeta_la_SOURCES = (auto-updated)
|
||||
EXTRA_DIST = (auto-updated)
|
||||
|
||||
AM_CFLAGS += -DVGM_USE_G7221
|
||||
|
||||
if HAVE_VORBIS
|
||||
if HAVE_VORBISFILE
|
||||
AM_CFLAGS += -DVGM_USE_VORBIS
|
||||
endif
|
||||
endif
|
||||
|
||||
if HAVE_LIBMPG123
|
||||
AM_CFLAGS += -DVGM_USE_MPEG
|
||||
endif
|
||||
|
||||
if HAVE_LIBSPEEX
|
||||
AM_CFLAGS += -DVGM_USE_SPEEX
|
||||
endif
|
||||
|
||||
if HAVE_FFMPEG
|
||||
AM_CFLAGS += -DVGM_USE_FFMPEG
|
||||
endif
|
@ -83,14 +83,14 @@ VGMSTREAM* init_vgmstream_adx_subkey(STREAMFILE* sf, uint16_t subkey) {
|
||||
coding_type = coding_CRI_ADX_enc_8;
|
||||
version = 0x0400;
|
||||
}
|
||||
VGM_ASSERT(version != 0x0400, "ADX: keystring not found\n");
|
||||
vgm_asserti(version != 0x0400, "ADX: decryption keystring not found\n");
|
||||
}
|
||||
else if (version == 0x0409) {
|
||||
if (find_adx_key(sf, 9, &xor_start, &xor_mult, &xor_add, subkey)) {
|
||||
coding_type = coding_CRI_ADX_enc_9;
|
||||
version = 0x0400;
|
||||
}
|
||||
VGM_ASSERT(version != 0x0400, "ADX: keycode not found\n");
|
||||
vgm_asserti(version != 0x0400, "ADX: decryption keycode not found\n");
|
||||
}
|
||||
|
||||
/* version + extra data */
|
||||
|
@ -166,7 +166,7 @@ static void find_bnsf_key(STREAMFILE* sf, off_t start, g7221_codec_data* data, u
|
||||
}
|
||||
|
||||
VGM_ASSERT(best_score > 0, "BNSF: best key=%.24s (score=%i)\n", best_key, best_score);
|
||||
VGM_ASSERT(best_score < 0, "BNSF: key not found\n");
|
||||
vgm_asserti(best_score < 0 , "BNSF: decryption key not found\n");
|
||||
}
|
||||
|
||||
#define BNSF_MIN_KEY_LEN 3
|
||||
|
121
src/meta/btsnd.c
121
src/meta/btsnd.c
@ -1,68 +1,53 @@
|
||||
/*
|
||||
Wii U boot sound file for each game/app.
|
||||
*/
|
||||
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
VGMSTREAM * init_vgmstream_btsnd(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
char filename[PATH_LIMIT];
|
||||
int channel_count = 2;
|
||||
int loop_flag;
|
||||
off_t start_offset = 0x8;
|
||||
|
||||
/* check extension, case insensitive */
|
||||
streamFile->get_name(streamFile, filename, sizeof(filename));
|
||||
if (strcasecmp("btsnd", filename_extension(filename)))
|
||||
goto fail;
|
||||
|
||||
/* Checking for loop start */
|
||||
if (read_32bitBE(0x4, streamFile) > 0)
|
||||
loop_flag = 1;
|
||||
else
|
||||
loop_flag = 0;
|
||||
|
||||
if (channel_count < 1) goto fail;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* fill in the vital statistics */
|
||||
vgmstream->sample_rate = 48000;
|
||||
/* channels and loop flag are set by allocate_vgmstream */
|
||||
|
||||
// There's probably a better way to get the sample count...
|
||||
vgmstream->num_samples = vgmstream->loop_end_sample = (get_streamfile_size(streamFile) - 8) / 4;
|
||||
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x4, streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_PCM16BE;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x2; // Constant for this format
|
||||
vgmstream->meta_type = meta_WIIU_BTSND;
|
||||
|
||||
/* open the file for reading by each channel */
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i<channel_count; i++) {
|
||||
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
|
||||
STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
|
||||
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||
|
||||
vgmstream->ch[i].channel_start_offset =
|
||||
vgmstream->ch[i].offset =
|
||||
start_offset + i*vgmstream->interleave_block_size;
|
||||
}
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
/* clean up anything we may have opened */
|
||||
fail:
|
||||
if (vgmstream) close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .btsnd - Wii U boot sound file for each game/app */
|
||||
VGMSTREAM* init_vgmstream_btsnd(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
int channels, loop_flag;
|
||||
off_t start_offset, data_size;
|
||||
int32_t num_samples, loop_start;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "btsnd"))
|
||||
goto fail;
|
||||
|
||||
if (read_u32be(0x00,sf) != 0x02)
|
||||
goto fail;
|
||||
|
||||
loop_start = read_s32be(0x04, sf);
|
||||
start_offset = 0x08;
|
||||
|
||||
channels = 2;
|
||||
loop_flag = loop_start > 0;
|
||||
|
||||
/* extra check since format is so simple */
|
||||
data_size = get_streamfile_size(sf);
|
||||
num_samples = pcm16_bytes_to_samples(data_size - start_offset, channels);
|
||||
if (loop_start >= num_samples)
|
||||
goto fail;
|
||||
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_WIIU_BTSND;
|
||||
vgmstream->sample_rate = 48000;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_PCM16BE;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x02;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "cri_utf.h"
|
||||
#include "../util/log.h"
|
||||
|
||||
#define COLUMN_BITMASK_FLAG 0xf0
|
||||
#define COLUMN_BITMASK_TYPE 0x0f
|
||||
@ -113,7 +114,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
|
||||
|
||||
/* 00: early (32b rows_offset?), 01: +2017 (no apparent differences) */
|
||||
if (utf->version != 0x00 && utf->version != 0x01) {
|
||||
VGM_LOG("@UTF: unknown version\n");
|
||||
vgm_logi("@UTF: unknown version\n");
|
||||
}
|
||||
if (utf->table_offset + utf->table_size > get_streamfile_size(sf))
|
||||
goto fail;
|
||||
@ -169,7 +170,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
|
||||
!(utf->schema[i].flag & COLUMN_FLAG_NAME) ||
|
||||
((utf->schema[i].flag & COLUMN_FLAG_DEFAULT) && (utf->schema[i].flag & COLUMN_FLAG_ROW)) ||
|
||||
(utf->schema[i].flag & COLUMN_FLAG_UNDEFINED) ) {
|
||||
VGM_LOG("@UTF: unknown column flag combo found\n");
|
||||
vgm_logi("@UTF: unknown column flag combo found\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -197,7 +198,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
|
||||
//case COLUMN_TYPE_UINT128:
|
||||
// value_size = 0x16;
|
||||
default:
|
||||
VGM_LOG("@UTF: unknown column type\n");
|
||||
vgm_logi("@UTF: unknown column type\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -228,7 +229,7 @@ utf_context* utf_open(STREAMFILE* sf, uint32_t table_offset, int* p_rows, const
|
||||
return utf;
|
||||
fail:
|
||||
utf_close(utf);
|
||||
VGM_LOG("@UTF: fail\n");
|
||||
vgm_logi("@UTF: init failure\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "deblock_streamfile.h"
|
||||
#include "../util/log.h"
|
||||
|
||||
//todo move to utils or something
|
||||
|
||||
|
@ -1,48 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t type;
|
||||
uint32_t size;
|
||||
uint32_t offset;
|
||||
off_t current;
|
||||
off_t max;
|
||||
int le_type;
|
||||
int be_size;
|
||||
int full_size;
|
||||
} chunk_t;
|
||||
|
||||
static int next_chunk(chunk_t* chunk, STREAMFILE* sf) {
|
||||
uint32_t (*read_u32type)(off_t,STREAMFILE*) = !chunk->le_type ? read_u32be : read_u32le;
|
||||
uint32_t (*read_u32size)(off_t,STREAMFILE*) = chunk->be_size ? read_u32be : read_u32le;
|
||||
|
||||
if (chunk->max == 0)
|
||||
chunk->max = get_streamfile_size(sf);
|
||||
|
||||
if (chunk->current >= chunk->max)
|
||||
return 0;
|
||||
/* can be used to signal "stop" */
|
||||
if (chunk->current < 0)
|
||||
return 0;
|
||||
|
||||
chunk->type = read_u32type(chunk->current + 0x00,sf);
|
||||
chunk->size = read_u32size(chunk->current + 0x04,sf);
|
||||
|
||||
chunk->offset = chunk->current + 0x04 + 0x04;
|
||||
chunk->current += chunk->full_size ? chunk->size : 0x08 + chunk->size;
|
||||
//;VGM_LOG("CHUNK: %x, %x, %x\n", dc.offset, chunk->type, chunk->size);
|
||||
|
||||
/* read past data */
|
||||
if (chunk->type == 0xFFFFFFFF || chunk->size == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
|
||||
if (chunk->type == 0 || chunk->size == 0)
|
||||
return 0;
|
||||
|
||||
/* more chunks remain */
|
||||
return 1;
|
||||
}
|
||||
#include "../util/chunks.h"
|
||||
|
||||
enum {
|
||||
CHUNK_RIFF = 0x52494646, /* "RIFF" */
|
||||
|
@ -193,13 +193,14 @@ VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf) {
|
||||
/* check extension */
|
||||
/* .uv: early */
|
||||
/* .dct: early-mid [ex. Need for Speed II SE (PC), FIFA 98 (PC)] */
|
||||
/* .wve: early-mid [Madden NFL 99 (PC)] */
|
||||
/* .mad: mid */
|
||||
/* .vp6: late */
|
||||
if (check_extensions(sf, "uv,dct")) {
|
||||
/* starts with audio header block */
|
||||
if (read_32bitBE(0x00, sf) != EA_BLOCKID_HEADER) /* "SCHl" */
|
||||
goto fail;
|
||||
} else if (check_extensions(sf, "mad")) {
|
||||
} else if (check_extensions(sf, "mad,wve")) {
|
||||
/* check initial movie block id */
|
||||
if (read_32bitBE(0x00, sf) != 0x4D41446B) /* "MADk" */
|
||||
goto fail;
|
||||
|
@ -72,7 +72,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
|
||||
fsb5.base_header_size = (fsb5.version==0x00) ? 0x40 : 0x3C;
|
||||
|
||||
if ((fsb5.sample_header_size + fsb5.name_table_size + fsb5.sample_data_size + fsb5.base_header_size) != get_streamfile_size(sf)) {
|
||||
VGM_LOG("FSB5: bad size (%x + %x + %x + %x != %x)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(sf));
|
||||
vgm_logi("FSB5: wrong size, expected %x + %x + %x + %x vs %x (re-rip)\n", fsb5.sample_header_size, fsb5.name_table_size, fsb5.sample_data_size, fsb5.base_header_size, get_streamfile_size(sf));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
|
||||
fsb5.channels = fsb5.channels * fsb5.layers;
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("FSB5: stream %i unknown flag 0x%x at %x + 0x04 (size 0x%x)\n", i, extraflag_type, (uint32_t)extraflag_offset, extraflag_size);
|
||||
vgm_logi("FSB5: stream %i unknown flag 0x%x at %x + 0x04 + 0x%x (report)\n", i, extraflag_type, (uint32_t)extraflag_offset, extraflag_size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -301,11 +301,11 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
|
||||
break;
|
||||
|
||||
case 0x03: /* FMOD_SOUND_FORMAT_PCM24 */
|
||||
VGM_LOG("FSB5: FMOD_SOUND_FORMAT_PCM24 found\n");
|
||||
vgm_logi("FSB5: FMOD_SOUND_FORMAT_PCM24 found (report)\n");
|
||||
goto fail;
|
||||
|
||||
case 0x04: /* FMOD_SOUND_FORMAT_PCM32 */
|
||||
VGM_LOG("FSB5: FMOD_SOUND_FORMAT_PCM32 found\n");
|
||||
vgm_logi("FSB5: FMOD_SOUND_FORMAT_PCM32 found (report)\n");
|
||||
goto fail;
|
||||
|
||||
case 0x05: /* FMOD_SOUND_FORMAT_PCMFLOAT [Anima: Gate of Memories (PC)] */
|
||||
@ -494,7 +494,7 @@ VGMSTREAM* init_vgmstream_fsb5(STREAMFILE* sf) {
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
VGM_LOG("FSB5: unknown codec %x found\n", fsb5.codec);
|
||||
vgm_logi("FSB5: unknown codec 0x%x (report)\n", fsb5.codec);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -30,7 +30,10 @@ VGMSTREAM* init_vgmstream_hca_subkey(STREAMFILE* sf, uint16_t subkey) {
|
||||
|
||||
/* init vgmstream and library's context, will validate the HCA */
|
||||
hca_data = init_hca(sf);
|
||||
if (!hca_data) goto fail;
|
||||
if (!hca_data) {
|
||||
vgm_logi("HCA: unknown format (report)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
hca_info = hca_get_info(hca_data);
|
||||
|
||||
@ -184,7 +187,7 @@ static void find_hca_key(hca_codec_data* hca_data, uint64_t* p_keycode, uint16_t
|
||||
done:
|
||||
VGM_ASSERT(best_score > 1, "HCA: best key=%08x%08x (score=%i)\n",
|
||||
(uint32_t)((*p_keycode >> 32) & 0xFFFFFFFF), (uint32_t)(*p_keycode & 0xFFFFFFFF), best_score);
|
||||
VGM_ASSERT(best_score < 0, "HCA: key not found\n");
|
||||
vgm_asserti(best_score < 0, "HCA: decryption key not found\n");
|
||||
}
|
||||
|
||||
#ifdef HCA_BRUTEFORCE
|
||||
|
100
src/meta/musc.c
100
src/meta/musc.c
@ -1,50 +1,50 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
|
||||
/* MUSC - from Krome's PS2 games (The Legend of Spyro, Ty the Tasmanian Tiger) */
|
||||
VGMSTREAM * init_vgmstream_musc(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
int loop_flag, channel_count;
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
|
||||
/* .mus is the real extension, .musc is the header ID */
|
||||
if (!check_extensions(streamFile,"mus,musc"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4D555343) /* "MUSC" */
|
||||
goto fail;
|
||||
|
||||
start_offset = read_32bitLE(0x10,streamFile);
|
||||
data_size = read_32bitLE(0x14,streamFile);
|
||||
if (start_offset + data_size != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
/* always does full loops unless it ends in silence */
|
||||
loop_flag = read_32bitBE(get_streamfile_size(streamFile) - 0x10,streamFile) != 0x0C000000;
|
||||
channel_count = 2;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x06,streamFile);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channel_count);
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->meta_type = meta_MUSC;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_32bitLE(0x18,streamFile) / 2;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
|
||||
/* MUSC - from Krome's PS2 games (The Legend of Spyro, Ty the Tasmanian Tiger) */
|
||||
VGMSTREAM* init_vgmstream_musc(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
int loop_flag, channels;
|
||||
off_t start_offset;
|
||||
size_t data_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .mus: actual extension
|
||||
* .musc: header ID */
|
||||
if (!check_extensions(sf,"mus,musc"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x00,sf, "MUSC"))
|
||||
goto fail;
|
||||
|
||||
start_offset = read_u32le(0x10,sf);
|
||||
data_size = read_u32le(0x14,sf);
|
||||
if (start_offset + data_size != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
/* always does full loops unless it ends in silence */
|
||||
loop_flag = read_u32be(get_streamfile_size(sf) - 0x10,sf) != 0x0C000000;
|
||||
channels = 2;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_u16le(0x06,sf);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(data_size, channels);
|
||||
vgmstream->loop_start_sample = 0;
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->meta_type = meta_MUSC;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = read_u32le(0x18,sf) / 2;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -279,6 +279,8 @@ static int read_fmt(int big_endian, STREAMFILE* sf, off_t offset, riff_fmt_chunk
|
||||
}
|
||||
|
||||
default:
|
||||
/* FFmpeg may play it */
|
||||
//vgm_logi("WWISE: unknown codec 0x%04x (report)\n", fmt->format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -418,8 +420,10 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
}
|
||||
|
||||
/* check for truncated RIFF */
|
||||
if (file_size != riff_size + 0x08)
|
||||
if (file_size != riff_size + 0x08) {
|
||||
vgm_logi("RIFF: wrong expected size (report/re-rip?)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* read through chunks to verify format and find metadata */
|
||||
{
|
||||
|
@ -100,8 +100,12 @@ VGMSTREAM* init_vgmstream_sqex_scd(STREAMFILE* sf) {
|
||||
target_entry = i;
|
||||
}
|
||||
}
|
||||
if (meta_offset == 0) goto fail;
|
||||
|
||||
/* SCD can contain 0 entries too */
|
||||
if (meta_offset == 0) {
|
||||
vgm_logi("SQEX SCD: bank has no subsongs (ignore)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/** stream header **/
|
||||
|
@ -765,7 +765,7 @@ static void parse_sead_sab_name(sead_header *sead, STREAMFILE *sf) {
|
||||
}
|
||||
|
||||
|
||||
static int parse_sead(sead_header *sead, STREAMFILE *sf) {
|
||||
static int parse_sead(sead_header* sead, STREAMFILE* sf) {
|
||||
uint32_t (*read_u32)(off_t,STREAMFILE*) = sead->big_endian ? read_u32be : read_u32le;
|
||||
uint16_t (*read_u16)(off_t,STREAMFILE*) = sead->big_endian ? read_u16be : read_u16le;
|
||||
|
||||
@ -856,8 +856,10 @@ static int parse_sead(sead_header *sead, STREAMFILE *sf) {
|
||||
}
|
||||
|
||||
/* SAB can contain 0 entries too */
|
||||
if (sead->mtrl_offset == 0)
|
||||
if (sead->mtrl_offset == 0) {
|
||||
vgm_logi("SQEX SEAD: bank has no subsongs (ignore)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
/** stream header **/
|
||||
|
157
src/meta/txth.c
157
src/meta/txth.c
@ -40,12 +40,14 @@ typedef enum {
|
||||
ASF = 30, /* Argonaut ASF 4-bit ADPCM */
|
||||
EAXA = 31, /* Electronic Arts EA-XA 4-bit ADPCM v1 */
|
||||
OKI4S = 32, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
|
||||
} txth_type;
|
||||
|
||||
UNKNOWN = 99,
|
||||
} txth_codec_t;
|
||||
|
||||
typedef enum { DEFAULT, NEGATIVE, POSITIVE, INVERTED } txth_loop_t;
|
||||
|
||||
typedef struct {
|
||||
txth_type codec;
|
||||
txth_codec_t codec;
|
||||
uint32_t codec_mode;
|
||||
|
||||
uint32_t value_mul;
|
||||
@ -196,6 +198,25 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
|
||||
}
|
||||
|
||||
|
||||
/* set common interleaves to simplify usage
|
||||
* (maybe should ignore if manually overwritten, possibly with 0 on purpose?) */
|
||||
if (txth.interleave == 0) {
|
||||
uint32_t interleave = 0;
|
||||
switch(txth.codec) {
|
||||
case PSX: interleave = 0x10; break;
|
||||
case PSX_bf: interleave = 0x10; break;
|
||||
case NGC_DSP: interleave = 0x08; break;
|
||||
case PCM16LE: interleave = 0x02; break;
|
||||
case PCM16BE: interleave = 0x02; break;
|
||||
case PCM8: interleave = 0x01; break;
|
||||
case PCM8_U: interleave = 0x01; break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
txth.interleave = interleave;
|
||||
}
|
||||
|
||||
|
||||
/* type to coding conversion */
|
||||
switch (txth.codec) {
|
||||
case PSX: coding = coding_PSX; break;
|
||||
@ -881,63 +902,61 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static txth_codec_t parse_codec(txth_header* txth, const char* val) {
|
||||
if (is_string(val,"PSX")) return PSX;
|
||||
else if (is_string(val,"XBOX")) return XBOX;
|
||||
else if (is_string(val,"NGC_DTK")) return NGC_DTK;
|
||||
else if (is_string(val,"DTK")) return NGC_DTK;
|
||||
else if (is_string(val,"PCM16BE")) return PCM16BE;
|
||||
else if (is_string(val,"PCM16LE")) return PCM16LE;
|
||||
else if (is_string(val,"PCM8")) return PCM8;
|
||||
else if (is_string(val,"SDX2")) return SDX2;
|
||||
else if (is_string(val,"DVI_IMA")) return DVI_IMA;
|
||||
else if (is_string(val,"MPEG")) return MPEG;
|
||||
else if (is_string(val,"IMA")) return IMA;
|
||||
else if (is_string(val,"AICA")) return AICA;
|
||||
else if (is_string(val,"MSADPCM")) return MSADPCM;
|
||||
else if (is_string(val,"NGC_DSP")) return NGC_DSP;
|
||||
else if (is_string(val,"DSP")) return NGC_DSP;
|
||||
else if (is_string(val,"PCM8_U_int")) return PCM8_U_int;
|
||||
else if (is_string(val,"PSX_bf")) return PSX_bf;
|
||||
else if (is_string(val,"MS_IMA")) return MS_IMA;
|
||||
else if (is_string(val,"PCM8_U")) return PCM8_U;
|
||||
else if (is_string(val,"APPLE_IMA4")) return APPLE_IMA4;
|
||||
else if (is_string(val,"ATRAC3")) return ATRAC3;
|
||||
else if (is_string(val,"ATRAC3PLUS")) return ATRAC3PLUS;
|
||||
else if (is_string(val,"XMA1")) return XMA1;
|
||||
else if (is_string(val,"XMA2")) return XMA2;
|
||||
else if (is_string(val,"FFMPEG")) return FFMPEG;
|
||||
else if (is_string(val,"AC3")) return AC3;
|
||||
else if (is_string(val,"PCFX")) return PCFX;
|
||||
else if (is_string(val,"PCM4")) return PCM4;
|
||||
else if (is_string(val,"PCM4_U")) return PCM4_U;
|
||||
else if (is_string(val,"OKI16")) return OKI16;
|
||||
else if (is_string(val,"OKI4S")) return OKI4S;
|
||||
else if (is_string(val,"AAC")) return AAC;
|
||||
else if (is_string(val,"TGC")) return TGC;
|
||||
else if (is_string(val,"GCOM_ADPCM")) return TGC;
|
||||
else if (is_string(val,"ASF")) return ASF;
|
||||
else if (is_string(val,"EAXA")) return EAXA;
|
||||
/* special handling */
|
||||
else if (is_string(val,"name_value")) return txth->name_values[0];
|
||||
else if (is_string(val,"name_value1")) return txth->name_values[0];
|
||||
else if (is_string(val,"name_value2")) return txth->name_values[1];
|
||||
else if (is_string(val,"name_value3")) return txth->name_values[2];
|
||||
//todo rest (handle in function)
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, char* val) {
|
||||
//;VGM_LOG("TXTH: key=%s, val=%s\n", key, val);
|
||||
|
||||
/* CODEC */
|
||||
if (is_string(key,"codec")) {
|
||||
if (is_string(val,"PSX")) txth->codec = PSX;
|
||||
else if (is_string(val,"XBOX")) txth->codec = XBOX;
|
||||
else if (is_string(val,"NGC_DTK")) txth->codec = NGC_DTK;
|
||||
else if (is_string(val,"DTK")) txth->codec = NGC_DTK;
|
||||
else if (is_string(val,"PCM16BE")) txth->codec = PCM16BE;
|
||||
else if (is_string(val,"PCM16LE")) txth->codec = PCM16LE;
|
||||
else if (is_string(val,"PCM8")) txth->codec = PCM8;
|
||||
else if (is_string(val,"SDX2")) txth->codec = SDX2;
|
||||
else if (is_string(val,"DVI_IMA")) txth->codec = DVI_IMA;
|
||||
else if (is_string(val,"MPEG")) txth->codec = MPEG;
|
||||
else if (is_string(val,"IMA")) txth->codec = IMA;
|
||||
else if (is_string(val,"AICA")) txth->codec = AICA;
|
||||
else if (is_string(val,"MSADPCM")) txth->codec = MSADPCM;
|
||||
else if (is_string(val,"NGC_DSP")) txth->codec = NGC_DSP;
|
||||
else if (is_string(val,"DSP")) txth->codec = NGC_DSP;
|
||||
else if (is_string(val,"PCM8_U_int")) txth->codec = PCM8_U_int;
|
||||
else if (is_string(val,"PSX_bf")) txth->codec = PSX_bf;
|
||||
else if (is_string(val,"MS_IMA")) txth->codec = MS_IMA;
|
||||
else if (is_string(val,"PCM8_U")) txth->codec = PCM8_U;
|
||||
else if (is_string(val,"APPLE_IMA4")) txth->codec = APPLE_IMA4;
|
||||
else if (is_string(val,"ATRAC3")) txth->codec = ATRAC3;
|
||||
else if (is_string(val,"ATRAC3PLUS")) txth->codec = ATRAC3PLUS;
|
||||
else if (is_string(val,"XMA1")) txth->codec = XMA1;
|
||||
else if (is_string(val,"XMA2")) txth->codec = XMA2;
|
||||
else if (is_string(val,"FFMPEG")) txth->codec = FFMPEG;
|
||||
else if (is_string(val,"AC3")) txth->codec = AC3;
|
||||
else if (is_string(val,"PCFX")) txth->codec = PCFX;
|
||||
else if (is_string(val,"PCM4")) txth->codec = PCM4;
|
||||
else if (is_string(val,"PCM4_U")) txth->codec = PCM4_U;
|
||||
else if (is_string(val,"OKI16")) txth->codec = OKI16;
|
||||
else if (is_string(val,"OKI4S")) txth->codec = OKI4S;
|
||||
else if (is_string(val,"AAC")) txth->codec = AAC;
|
||||
else if (is_string(val,"TGC")) txth->codec = TGC;
|
||||
else if (is_string(val,"GCOM_ADPCM")) txth->codec = TGC;
|
||||
else if (is_string(val,"ASF")) txth->codec = ASF;
|
||||
else if (is_string(val,"EAXA")) txth->codec = EAXA;
|
||||
else goto fail;
|
||||
|
||||
/* set common interleaves to simplify usage
|
||||
* (do it here to in case it's overwritten later, possibly with 0 on purpose) */
|
||||
if (txth->interleave == 0) {
|
||||
switch(txth->codec) {
|
||||
case PSX: txth->interleave = 0x10; break;
|
||||
case PSX_bf: txth->interleave = 0x10; break;
|
||||
case NGC_DSP: txth->interleave = 0x08; break;
|
||||
case PCM16LE: txth->interleave = 0x02; break;
|
||||
case PCM16BE: txth->interleave = 0x02; break;
|
||||
case PCM8: txth->interleave = 0x01; break;
|
||||
case PCM8_U: txth->interleave = 0x01; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
txth->codec = parse_codec(txth, val);
|
||||
if (txth->codec == UNKNOWN)
|
||||
goto fail;
|
||||
}
|
||||
else if (is_string(key,"codec_mode")) {
|
||||
if (!parse_num(txth->sf_head,txth,val, &txth->codec_mode)) goto fail;
|
||||
@ -1372,7 +1391,7 @@ static int parse_keyval(STREAMFILE* sf_, txth_header* txth, const char* key, cha
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
VGM_LOG("TXTH: error parsing key=%s, val=%s\n", key, val);
|
||||
vgm_logi("TXTH: error parsing key=%s, val=%s\n", key, val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1589,6 +1608,26 @@ static int read_name_table_keyval(txth_header* txth, const char* line, char* key
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_name_val(txth_header* txth, char* subval) {
|
||||
int ok;
|
||||
|
||||
ok = parse_num(txth->sf_head, txth, subval, &txth->name_values[txth->name_values_count]);
|
||||
if (!ok) {
|
||||
/* in rare cases may set codec */
|
||||
txth_codec_t codec = parse_codec(txth, subval);
|
||||
if (codec == UNKNOWN)
|
||||
goto fail;
|
||||
txth->name_values[txth->name_values_count] = codec;
|
||||
}
|
||||
txth->name_values_count++;
|
||||
if (txth->name_values_count >= 16) /* surely nobody needs that many */
|
||||
goto fail;
|
||||
|
||||
return 1;
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_name_table(txth_header* txth, char* name_list) {
|
||||
STREAMFILE* sf_names = NULL;
|
||||
off_t txt_offset, file_size;
|
||||
@ -1666,9 +1705,7 @@ static int parse_name_table(txth_header* txth, char* name_list) {
|
||||
if (current[0] == ',')
|
||||
current++;
|
||||
|
||||
if (!parse_num(txth->sf_head,txth,subval, &txth->name_values[txth->name_values_count])) goto fail;
|
||||
txth->name_values_count++;
|
||||
if (txth->name_values_count >= 16) /* surely nobody needs that many */
|
||||
if (!parse_name_val(txth, subval))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1806,7 +1843,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_
|
||||
offset += txth->base_offset;
|
||||
|
||||
if (/*offset < 0 ||*/ offset > get_streamfile_size(sf)) {
|
||||
VGM_LOG("TXTH: wrong offset %x + %x\n", offset - txth->base_offset, txth->base_offset);
|
||||
vgm_logi("TXTH: wrong offset over file size (%x + %x)\n", offset - txth->base_offset, txth->base_offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -1920,7 +1957,7 @@ static int parse_num(STREAMFILE* sf, txth_header* txth, const char* val, uint32_
|
||||
//;VGM_LOG("TXTH: final result %u (0x%x)\n", result, result);
|
||||
return 1;
|
||||
fail:
|
||||
VGM_LOG("TXTH: error parsing num '%s'\n", val);
|
||||
//VGM_LOG("TXTH: error parsing num '%s'\n", val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ static VGMSTREAM* init_vgmstream_ubi_bao_header(ubi_bao_header* bao, STREAMFILE*
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
|
||||
if (bao->total_subsongs <= 0) {
|
||||
VGM_LOG("UBI BAO: no subsongs\n");
|
||||
vgm_logi("UBI BAO: bank has no subsongs (ignore)\n");
|
||||
goto fail; /* not uncommon */
|
||||
}
|
||||
|
||||
@ -1473,7 +1473,10 @@ static STREAMFILE* setup_bao_streamfile(ubi_bao_header* bao, STREAMFILE* sf) {
|
||||
|
||||
if (bao->stream_size - bao->prefetch_size != 0) {
|
||||
new_sf = open_streamfile_by_filename(sf, bao->resource_name);
|
||||
if (!new_sf) { VGM_LOG("UBI BAO: external stream '%s' not found\n", bao->resource_name); goto fail; }
|
||||
if (!new_sf) {
|
||||
vgm_logi("UBI BAO: external file '%s' not found (put together)\n", bao->resource_name);
|
||||
goto fail;
|
||||
}
|
||||
stream_segments[1] = new_sf;
|
||||
|
||||
new_sf = open_clamp_streamfile(stream_segments[1], bao->stream_offset, (bao->stream_size - bao->prefetch_size));
|
||||
@ -1495,7 +1498,10 @@ static STREAMFILE* setup_bao_streamfile(ubi_bao_header* bao, STREAMFILE* sf) {
|
||||
}
|
||||
else if (bao->is_external) {
|
||||
new_sf = open_streamfile_by_filename(sf, bao->resource_name);
|
||||
if (!new_sf) { VGM_LOG("UBI BAO: external stream '%s' not found\n", bao->resource_name); goto fail; }
|
||||
if (!new_sf) {
|
||||
vgm_logi("UBI BAO: external file '%s' not found (put together)\n", bao->resource_name);
|
||||
goto fail;
|
||||
}
|
||||
temp_sf = new_sf;
|
||||
|
||||
new_sf = open_clamp_streamfile(temp_sf, bao->stream_offset, bao->stream_size);
|
||||
@ -1884,11 +1890,10 @@ static int config_bao_version(ubi_bao_header* bao, STREAMFILE* sf) {
|
||||
* - 0x94: stream id? 0x9C: extra size */
|
||||
case 0x002A0300: /* Watch Dogs (Wii U) */
|
||||
/* similar to SC:B */
|
||||
default: /* others possibly using BAO: Just Dance, Watch_Dogs, Far Cry Primal, Far Cry 4 */
|
||||
VGM_LOG("UBI BAO: unknown BAO version %08x\n", bao->version);
|
||||
default: /* others possibly using BAO: Watch_Dogs, Far Cry Primal, Far Cry 4 */
|
||||
vgm_logi("UBI BAO: unknown BAO version %08x\n", bao->version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
VGM_LOG("UBI BAO: unknown BAO version %08x\n", bao->version);
|
||||
return 0;
|
||||
}
|
||||
|
@ -644,7 +644,7 @@ static VGMSTREAM *init_vgmstream_ubi_dat_main(ubi_sb_header *sb, STREAMFILE *sf_
|
||||
sf_data = open_streamfile_by_filename(sf, sb->resource_name);
|
||||
if (!sf_data) {
|
||||
/* play silence if external file is not found since Rayman 2 seems to rely on this behavior */
|
||||
VGM_LOG("UBI DAT: external stream '%s' not found\n", sb->resource_name);
|
||||
vgm_logi("UBI DAT: external file '%s' not found (put together)\n", sb->resource_name);
|
||||
strncat(sb->readable_name, " (missing)", sizeof(sb->readable_name));
|
||||
sb->duration = (float)pcm_bytes_to_samples(sb->stream_size, sb->channels, 16) / (float)sb->sample_rate;
|
||||
return init_vgmstream_ubi_sb_silence(sb);
|
||||
@ -1301,10 +1301,11 @@ static VGMSTREAM* init_vgmstream_ubi_sb_audio(ubi_sb_header* sb, STREAMFILE* sf_
|
||||
if (sb->is_external) {
|
||||
sf_data = open_streamfile_by_filename(sf, sb->resource_name);
|
||||
if (sf_data == NULL) {
|
||||
VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name);
|
||||
vgm_logi("UBI SB: external file '%s' not found (put together)\n", sb->resource_name);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
sf_data = sf;
|
||||
}
|
||||
|
||||
@ -1341,7 +1342,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_layer(ubi_sb_header* sb, STREAMFILE* sf_
|
||||
if (sb->is_external) {
|
||||
sf_data = open_streamfile_by_filename(sf,sb->resource_name);
|
||||
if (sf_data == NULL) {
|
||||
VGM_LOG("UBI SB: external stream '%s' not found\n", sb->resource_name);
|
||||
vgm_logi("UBI SB: external file '%s' not found (put together)\n", sb->resource_name);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -1563,7 +1564,7 @@ static VGMSTREAM* init_vgmstream_ubi_sb_header(ubi_sb_header* sb, STREAMFILE* sf
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
|
||||
if (sb->total_subsongs == 0) {
|
||||
VGM_LOG("UBI SB: no subsongs\n");
|
||||
vgm_logi("UBI SB: bank has no subsongs (ignore)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -4042,6 +4043,6 @@ static int config_sb_version(ubi_sb_header* sb, STREAMFILE* sf) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
VGM_LOG("UBI SB: unknown SB/SM version+platform %08x\n", sb->version);
|
||||
vgm_logi("UBI SB: unknown SB/SM version+platform %08x (report)\n", sb->version);
|
||||
return 0;
|
||||
}
|
||||
|
@ -592,8 +592,8 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
case HEVAG: /* PSV */
|
||||
/* changed values, another bizarre Wwise quirk */
|
||||
//ww.block_align /* unknown (1ch=2, 2ch=4) */
|
||||
@ -644,6 +644,7 @@ VGMSTREAM* init_vgmstream_wwise(STREAMFILE* sf) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
case PTADPCM: /* newer ADPCM [Bayonetta 2 (Switch), Genshin Impact (PC)] */
|
||||
if (ww.bits_per_sample != 4) goto fail;
|
||||
if (ww.block_align != 0x24 * ww.channels && ww.block_align != 0x104 * ww.channels) goto fail;
|
||||
@ -885,6 +886,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
|
||||
case 0x3041: ww->codec = OPUSWW; break; /* "OPUS_WEM", added on Wwise 2019.2.3, replaces OPUS */
|
||||
case 0x8311: ww->codec = PTADPCM; break; /* added on Wwise 2019.1, replaces IMA */
|
||||
default:
|
||||
vgm_logi("WWISE: unknown codec 0x%04x (report)\n", ww->format);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -893,11 +895,14 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
|
||||
if (ww->extra_size == 0x0c + ww->channels * 0x2e) {
|
||||
/* newer Wwise DSP with coefs [Epic Mickey 2 (Wii), Batman Arkham Origins Blackgate (3DS)] */
|
||||
ww->codec = DSP;
|
||||
} else if (ww->extra_size == 0x0a && ww->wiih_offset) { /* WiiH */
|
||||
}
|
||||
else if (ww->extra_size == 0x0a && ww->wiih_offset) { /* WiiH */
|
||||
/* few older Wwise DSP with num_samples in extra_size [Tony Hawk: Shred (Wii)] */
|
||||
ww->codec = DSP;
|
||||
} else if (ww->block_align == 0x104 * ww->channels) {
|
||||
ww->codec = PTADPCM; /* Bayonetta 2 (Switch) */
|
||||
}
|
||||
else if (ww->block_align == 0x104 * ww->channels) {
|
||||
/* Bayonetta 2 (Switch) */
|
||||
ww->codec = PTADPCM;
|
||||
}
|
||||
}
|
||||
|
||||
@ -911,7 +916,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
|
||||
/* catch wrong rips as truncated tracks' file_size should be much smaller than data_size,
|
||||
* but it's possible to pre-fetch small files too [Punch Out!! (Wii)] */
|
||||
if (ww->data_offset + ww->data_size - ww->file_size < 0x5000 && ww->file_size > 0x10000) {
|
||||
VGM_LOG("WWISE: wrong expected data_size\n");
|
||||
vgm_logi("WWISE: wrong expected size (re-rip?)\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -919,7 +924,7 @@ static int parse_wwise(STREAMFILE* sf, wwise_header* ww) {
|
||||
ww->codec == OPUSNX || ww->codec == OPUS || ww->codec == OPUSWW || ww->codec == PTADPCM) {
|
||||
ww->truncated = 1; /* only seen those, probably all exist (XWMA, AAC, HEVAG, ATRAC9?) */
|
||||
} else {
|
||||
VGM_LOG("WWISE: wrong size, maybe truncated\n");
|
||||
vgm_logi("WWISE: wrong expected size, maybe truncated (report)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf) {
|
||||
|
||||
sf_body = open_streamfile_by_filename(sf,filename);
|
||||
if (!sf_body) {
|
||||
VGM_LOG("XSH: can't find %s\n", filename);
|
||||
vgm_logi("XSH: external file '%s' not found (put together)\n", filename);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -116,7 +116,7 @@ VGMSTREAM* init_vgmstream_xsh_xsd_xss(STREAMFILE* sf) {
|
||||
snprintf(filename, sizeof(filename), "%s", "STREAMS.XSS");
|
||||
sf_body = open_streamfile_by_filename(sf,filename);
|
||||
if (!sf_body) {
|
||||
VGM_LOG("XSH: can't find %s\n", filename);
|
||||
vgm_logi("XSH: external file '%s' not found (put together)\n", filename);
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "vgmstream.h"
|
||||
#include "plugins.h"
|
||||
#include "mixing.h"
|
||||
#include "util/log.h"
|
||||
|
||||
|
||||
/* ****************************************** */
|
||||
@ -546,3 +547,16 @@ void vgmstream_mixing_stereo_only(VGMSTREAM *vgmstream, int start) {
|
||||
/* remove channels after stereo */
|
||||
mixing_push_killmix(vgmstream, start + 2);
|
||||
}
|
||||
|
||||
|
||||
/* ****************************************** */
|
||||
/* LOG: log */
|
||||
/* ****************************************** */
|
||||
|
||||
void vgmstream_set_log_callback(int level, void* callback) {
|
||||
vgm_log_set_callback(NULL, level, 0, callback);
|
||||
}
|
||||
|
||||
void vgmstream_set_log_stdout(int level) {
|
||||
vgm_log_set_callback(NULL, level, 1, NULL);
|
||||
}
|
||||
|
@ -77,6 +77,14 @@ typedef struct {
|
||||
/* get a simple title for plugins */
|
||||
void vgmstream_get_title(char* buf, int buf_len, const char* filename, VGMSTREAM* vgmstream, vgmstream_title_t* cfg);
|
||||
|
||||
enum {
|
||||
VGM_LOG_LEVEL_INFO = 1,
|
||||
VGM_LOG_LEVEL_DEBUG = 2,
|
||||
VGM_LOG_LEVEL_ALL = 100,
|
||||
};
|
||||
// CB: void (*callback)(int level, const char* str)
|
||||
void vgmstream_set_log_callback(int level, void* callback);
|
||||
void vgmstream_set_log_stdout(int level);
|
||||
|
||||
|
||||
#if 0
|
||||
|
45
src/util.h
45
src/util.h
@ -136,49 +136,4 @@ void swap_samples_le(sample_t *buf, int count);
|
||||
|
||||
void concatn(int length, char * dst, const char * src);
|
||||
|
||||
|
||||
/* Simple stdout logging for debugging and regression testing purposes.
|
||||
* Needs C99 variadic macros, uses do..while to force ";" as statement */
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
|
||||
/* equivalent to printf when condition is true */
|
||||
#define VGM_ASSERT(condition, ...) \
|
||||
do { if (condition) {printf(__VA_ARGS__);} } while (0)
|
||||
#define VGM_ASSERT_ONCE(condition, ...) \
|
||||
do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0)
|
||||
/* equivalent to printf */
|
||||
#define VGM_LOG(...) \
|
||||
do { printf(__VA_ARGS__); } while (0)
|
||||
#define VGM_LOG_ONCE(...) \
|
||||
do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0)
|
||||
/* prints file/line/func */
|
||||
#define VGM_LOGF() \
|
||||
do { printf("%s:%i '%s'\n", __FILE__, __LINE__, __func__); } while (0)
|
||||
/* prints to a file */
|
||||
#define VGM_LOGT(txt, ...) \
|
||||
do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0)
|
||||
/* prints a buffer/array */
|
||||
#define VGM_LOGB(buf, buf_size, bytes_per_line) \
|
||||
do { \
|
||||
int i; \
|
||||
for (i=0; i < buf_size; i++) { \
|
||||
printf("%02x",buf[i]); \
|
||||
if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \
|
||||
} \
|
||||
printf("\n"); \
|
||||
} while (0)
|
||||
|
||||
#else/*VGM_DEBUG_OUTPUT*/
|
||||
|
||||
#define VGM_ASSERT(condition, ...) /* nothing */
|
||||
#define VGM_ASSERT_ONCE(condition, ...) /* nothing */
|
||||
#define VGM_LOG(...) /* nothing */
|
||||
#define VGM_LOG_ONCE(...) /* nothing */
|
||||
#define VGM_LOGF() /* nothing */
|
||||
#define VGM_LOGT() /* nothing */
|
||||
#define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */
|
||||
|
||||
|
||||
#endif/*VGM_DEBUG_OUTPUT*/
|
||||
|
||||
#endif
|
||||
|
35
src/util/chunks.c
Normal file
35
src/util/chunks.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include "chunks.h"
|
||||
//#include "log.h"
|
||||
|
||||
|
||||
int next_chunk(chunk_t* chunk, STREAMFILE* sf) {
|
||||
uint32_t (*read_u32type)(off_t,STREAMFILE*) = !chunk->le_type ? read_u32be : read_u32le;
|
||||
uint32_t (*read_u32size)(off_t,STREAMFILE*) = chunk->be_size ? read_u32be : read_u32le;
|
||||
|
||||
if (chunk->max == 0)
|
||||
chunk->max = get_streamfile_size(sf);
|
||||
|
||||
if (chunk->current >= chunk->max)
|
||||
return 0;
|
||||
/* can be used to signal "stop" */
|
||||
if (chunk->current < 0)
|
||||
return 0;
|
||||
|
||||
chunk->type = read_u32type(chunk->current + 0x00,sf);
|
||||
chunk->size = read_u32size(chunk->current + 0x04,sf);
|
||||
|
||||
chunk->offset = chunk->current + 0x04 + 0x04;
|
||||
chunk->current += chunk->full_size ? chunk->size : 0x08 + chunk->size;
|
||||
//;VGM_LOG("CHUNK: %x, %x, %x\n", dc.offset, chunk->type, chunk->size);
|
||||
|
||||
/* read past data */
|
||||
if (chunk->type == 0xFFFFFFFF || chunk->size == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
|
||||
if (chunk->type == 0 || chunk->size == 0)
|
||||
return 0;
|
||||
|
||||
/* more chunks remain */
|
||||
return 1;
|
||||
}
|
27
src/util/chunks.h
Normal file
27
src/util/chunks.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef _UTIL_CHUNKS_H
|
||||
#define _UTIL_CHUNKS_H
|
||||
|
||||
#include "../streamfile.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t type; /* chunk id/fourcc */
|
||||
uint32_t size; /* chunk size */
|
||||
uint32_t offset; /* chunk offset (after type/size) */
|
||||
off_t current; /* start position, or next chunk after size (set to -1 to break) */
|
||||
off_t max; /* max offset, or filesize if not set */
|
||||
|
||||
int le_type; /* read type as LE instead of more common BE */
|
||||
int be_size; /* read type as BE instead of more common LE */
|
||||
int full_size; /* chunk size includes type+size */
|
||||
} chunk_t;
|
||||
|
||||
int next_chunk(chunk_t* chunk, STREAMFILE* sf);
|
||||
|
||||
#if 0
|
||||
enum {
|
||||
CHUNK_RIFF = 0x52494646, /* "RIFF" */
|
||||
CHUNK_LIST = 0x4C495354, /* "LIST" */
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
90
src/util/log.c
Normal file
90
src/util/log.c
Normal file
@ -0,0 +1,90 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* log context; should probably make a unique instance and pass to metas/decoders/etc, but for the time being use global */
|
||||
//extern ...* log;
|
||||
|
||||
typedef struct {
|
||||
int level;
|
||||
void (*callback)(int level, const char* str);
|
||||
} logger_t;
|
||||
|
||||
logger_t log_impl = {0};
|
||||
//void* log = &log_impl;
|
||||
|
||||
enum {
|
||||
LOG_LEVEL_INFO = 1,
|
||||
LOG_LEVEL_DEBUG = 2,
|
||||
LOG_LEVEL_ALL = 100,
|
||||
};
|
||||
|
||||
static void vgm_log_callback_printf(int level, const char* str) {
|
||||
printf("%s", str);
|
||||
}
|
||||
|
||||
void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback) {
|
||||
logger_t* ctx = ctx_p;
|
||||
if (!ctx) ctx = &log_impl;
|
||||
|
||||
ctx->level = level;
|
||||
|
||||
switch(type) {
|
||||
case 0:
|
||||
ctx->callback = callback;
|
||||
break;
|
||||
case 1:
|
||||
ctx->callback = vgm_log_callback_printf;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void log_internal(void* ctx_p, int level, const char* fmt, va_list args) {
|
||||
char line[255];
|
||||
int out;
|
||||
logger_t* ctx = ctx_p;
|
||||
if (!ctx) ctx = &log_impl;
|
||||
|
||||
if (!ctx->callback)
|
||||
return;
|
||||
|
||||
if (level > ctx->level)
|
||||
return;
|
||||
|
||||
out = vsnprintf(line, sizeof(line), fmt, args);
|
||||
if (out < 0 || out > sizeof(line))
|
||||
strcpy(line, "(ignored log)"); //to-do something better, meh
|
||||
ctx->callback(level, line);
|
||||
}
|
||||
|
||||
void vgm_logd(const char* fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
log_internal(NULL, LOG_LEVEL_DEBUG, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vgm_logi(const char* fmt, ...) {
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
log_internal(NULL, LOG_LEVEL_INFO, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void vgm_asserti(int condition, const char* fmt, ...) {
|
||||
if (!condition)
|
||||
return;
|
||||
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
log_internal(NULL, LOG_LEVEL_INFO, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
78
src/util/log.h
Normal file
78
src/util/log.h
Normal file
@ -0,0 +1,78 @@
|
||||
#ifndef _UTIL_LOG_H
|
||||
#define _UTIL_LOG_H
|
||||
|
||||
/* Dumb logger utils (tuned for simplicity). Notes:
|
||||
* - must set callback/defaults to print anything
|
||||
* - mainly used to print info for users, like format detected but wrong size
|
||||
* (don't clutter by logging code that happens most of the time, since log may be shared with other plugins)
|
||||
* - callbacks receive formed string for simplicity (to be adjusted)
|
||||
* - DO NOT put logs in tight loops (like decoders), slow fn calls and clutter
|
||||
* (metas are usually fine but also consider cluttering)
|
||||
* - as compiler must support variable args, needs to pass VGM_LOG_OUTPUT flag to enable
|
||||
* - debug logs are removed unless VGM_DEBUG_OUTPUT is passed to compiler args
|
||||
* (passing either of them works)
|
||||
* - callback should be thread-safe (no internal checks and only one log ATM)
|
||||
* - still WIP, some stuff not working ATM or may change
|
||||
*/
|
||||
|
||||
// void (*callback)(int level, const char* str);
|
||||
void vgm_log_set_callback(void* ctx_p, int level, int type, void* callback);
|
||||
|
||||
#if defined(VGM_LOG_OUTPUT) || defined(VGM_DEBUG_OUTPUT)
|
||||
void vgm_logi(/*void* ctx,*/ const char* fmt, ...);
|
||||
void vgm_asserti(/*void* ctx,*/ int condition, const char* fmt, ...);
|
||||
//void vgm_logi_once(/*void* ctx, int* once_flag, */ const char* fmt, ...);
|
||||
#else
|
||||
#define vgm_logi(...) /* nothing */
|
||||
#define vgm_asserti(...) /* nothing */
|
||||
#endif
|
||||
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
void vgm_logd(/*void* ctx,*/ const char* fmt, ...);
|
||||
#define VGM_LOG(...) do { vgm_logd(__VA_ARGS__); } while (0)
|
||||
#define VGM_ASSERT(condition, ...) do { if (condition) {vgm_logd(__VA_ARGS__);} } while (0)
|
||||
#else
|
||||
#define vgm_logd(...) /* nothing */
|
||||
#define VGM_LOG(...) /* nothing */
|
||||
#define VGM_ASSERT(condition, ...) /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
/* original stdout logging for debugging and regression testing purposes, may be removed later.
|
||||
* Needs C99 variadic macros, uses do..while to force ";" as statement */
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
|
||||
#define VGM_LOG_ONCE(...) \
|
||||
do { static int written; if (!written) { printf(__VA_ARGS__); written = 1; } } while (0)
|
||||
|
||||
#define VGM_ASSERT_ONCE(condition, ...) \
|
||||
do { static int written; if (!written) { if (condition) {printf(__VA_ARGS__); written = 1;} } } while (0)
|
||||
|
||||
/* prints to a file */
|
||||
#define VGM_LOGT(txt, ...) \
|
||||
do { FILE *fl = fopen(txt,"a+"); if(fl){fprintf(fl,__VA_ARGS__); fflush(fl);} fclose(fl); } while(0)
|
||||
|
||||
/* prints a buffer/array */
|
||||
#define VGM_LOGB(buf, buf_size, bytes_per_line) \
|
||||
do { \
|
||||
int i; \
|
||||
for (i=0; i < buf_size; i++) { \
|
||||
printf("%02x",buf[i]); \
|
||||
if (bytes_per_line && (i+1) % bytes_per_line == 0) printf("\n"); \
|
||||
} \
|
||||
printf("\n"); \
|
||||
} while (0)
|
||||
|
||||
#else /* VGM_DEBUG_OUTPUT */
|
||||
|
||||
#define VGM_LOG_ONCE(...) /* nothing */
|
||||
|
||||
#define VGM_ASSERT_ONCE(condition, ...) /* nothing */
|
||||
|
||||
#define VGM_LOGT() /* nothing */
|
||||
|
||||
#define VGM_LOGB(buf, buf_size, bytes_per_line) /* nothing */
|
||||
|
||||
#endif /*VGM_DEBUG_OUTPUT*/
|
||||
|
||||
#endif
|
@ -24,7 +24,6 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
||||
init_vgmstream_bfwav,
|
||||
init_vgmstream_bfstm,
|
||||
init_vgmstream_mca,
|
||||
init_vgmstream_btsnd,
|
||||
init_vgmstream_nds_strm,
|
||||
init_vgmstream_agsc,
|
||||
init_vgmstream_ngc_adpdtk,
|
||||
@ -533,6 +532,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
|
||||
init_vgmstream_encrypted, /* encrypted stuff */
|
||||
init_vgmstream_btsnd, /* semi-headerless */
|
||||
init_vgmstream_raw_int, /* .int raw PCM */
|
||||
init_vgmstream_ps_headerless, /* tries to detect a bunch of PS-ADPCM formats */
|
||||
init_vgmstream_raw_snds, /* .snds raw SNDS IMA (*after* ps_headerless) */
|
||||
|
@ -17,6 +17,7 @@ enum {
|
||||
};
|
||||
|
||||
#include "streamfile.h"
|
||||
#include "util/log.h"
|
||||
|
||||
/* Due mostly to licensing issues, Vorbis, MPEG, G.722.1, etc decoding is done by external libraries.
|
||||
* Libs are disabled by default, defined on compile-time for builds that support it */
|
||||
|
@ -347,6 +347,36 @@ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||
break;
|
||||
}
|
||||
|
||||
case IDC_LOG_BUTTON: { /* shows log */
|
||||
TCHAR wbuf[257*32];
|
||||
char buf[257*32];
|
||||
size_t buf_size = 257*32;
|
||||
int i, max = 0;
|
||||
const char** lines = logger_get_lines(&max);
|
||||
|
||||
/* could use some nice scrollable text but I don't know arcane Windows crap */
|
||||
if (lines == NULL) {
|
||||
snprintf(buf, 257, "%s\n", "couldn't read log");
|
||||
}
|
||||
else if (max == 0) {
|
||||
snprintf(buf, 257, "%s\n", "(empty)");
|
||||
}
|
||||
else {
|
||||
//todo improve
|
||||
char* tmp = buf;
|
||||
for (i = 0; i < max; i++) {
|
||||
int done = snprintf(tmp, 256, "%s", lines[i]);
|
||||
if (done < 0 || done >= 256)
|
||||
break;
|
||||
tmp += (done); // + 1
|
||||
}
|
||||
}
|
||||
|
||||
cfg_char_to_wchar(wbuf, buf_size, buf);
|
||||
MessageBox(hDlg, buf, TEXT("vgmstream log"), MB_OK);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
@ -370,3 +400,82 @@ INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lPara
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* ************************************* */
|
||||
/* IN_LOG */
|
||||
/* ************************************* */
|
||||
|
||||
/* could just write to file but to avoid leaving temp crap just log to memory and print what when requested */
|
||||
|
||||
winamp_log_t* walog;
|
||||
#define WALOG_MAX_LINES 32
|
||||
#define WALOG_MAX_CHARS 256
|
||||
|
||||
struct winamp_log_t {
|
||||
char data[WALOG_MAX_LINES * WALOG_MAX_CHARS];
|
||||
int logged;
|
||||
const char* lines[WALOG_MAX_LINES];
|
||||
} ;
|
||||
|
||||
void logger_init() {
|
||||
walog = malloc(sizeof(winamp_log_t));
|
||||
if (!walog) return;
|
||||
|
||||
walog->logged = 0;
|
||||
}
|
||||
|
||||
void logger_free() {
|
||||
free(walog);
|
||||
walog = NULL;
|
||||
}
|
||||
|
||||
/* logs to data as a sort of circular buffer. example if max_lines is 6:
|
||||
* - log 0 = "msg1"
|
||||
* ...
|
||||
* - log 5 = "msg5" > limit reached, next will overwrite 0
|
||||
* - log 0 = "msg6" (max 6 logs, but can only write las 6)
|
||||
* - when requested lines should go from current to: 1,2,3,4,5,0
|
||||
*/
|
||||
void logger_callback(int level, const char* str) {
|
||||
char* buf;
|
||||
int pos;
|
||||
if (!walog)
|
||||
return;
|
||||
|
||||
pos = (walog->logged % WALOG_MAX_LINES) * WALOG_MAX_CHARS;
|
||||
buf = &walog->data[pos];
|
||||
snprintf(buf, WALOG_MAX_CHARS, "%s", str);
|
||||
|
||||
walog->logged++;
|
||||
|
||||
/* ??? */
|
||||
if (walog->logged >= 0x7FFFFFFF)
|
||||
walog->logged = 0;
|
||||
}
|
||||
|
||||
const char** logger_get_lines(int* p_max) {
|
||||
int i, from, max;
|
||||
|
||||
if (!walog) {
|
||||
*p_max = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (walog->logged > WALOG_MAX_LINES) {
|
||||
from = (walog->logged % WALOG_MAX_LINES);
|
||||
max = WALOG_MAX_LINES;
|
||||
}
|
||||
else {
|
||||
from = 0;
|
||||
max = walog->logged;
|
||||
}
|
||||
|
||||
for (i = 0; i < max; i++) {
|
||||
int pos = ((from + i) % WALOG_MAX_LINES) * WALOG_MAX_CHARS;
|
||||
walog->lines[i] = &walog->data[pos];
|
||||
}
|
||||
|
||||
*p_max = max;
|
||||
return walog->lines;
|
||||
}
|
||||
|
@ -344,6 +344,9 @@ void winamp_Init() {
|
||||
|
||||
settings.is_xmplay = is_xmplay();
|
||||
|
||||
logger_init();
|
||||
vgmstream_set_log_callback(VGM_LOG_LEVEL_ALL, logger_callback);
|
||||
|
||||
/* get ini config */
|
||||
load_defaults(&defaults);
|
||||
load_config(&input_module, &settings, &defaults);
|
||||
@ -359,6 +362,7 @@ void winamp_Init() {
|
||||
|
||||
/* called at program quit */
|
||||
void winamp_Quit() {
|
||||
logger_free();
|
||||
}
|
||||
|
||||
/* called before extension checks, to allow detection of mms://, etc */
|
||||
|
@ -74,6 +74,16 @@ void load_config(In_Module* input_module, winamp_settings_t* settings, winamp_se
|
||||
INT_PTR CALLBACK configDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
|
||||
/* logger */
|
||||
typedef struct winamp_log_t winamp_log_t;
|
||||
void logger_init();
|
||||
void logger_free();
|
||||
void logger_callback(int level, const char* str);
|
||||
const char** logger_get_lines(int* p_max);
|
||||
|
||||
extern winamp_log_t* walog;
|
||||
|
||||
|
||||
/* ************************************* */
|
||||
/* IN_UNICODE */
|
||||
/* ************************************* */
|
||||
|
@ -16,3 +16,4 @@
|
||||
#define IDC_EXTS_UNKNOWN_ON 1015
|
||||
#define IDC_EXTS_COMMON_ON 1016
|
||||
#define IDC_FORCE_TITLE 1017
|
||||
#define IDC_LOG_BUTTON 1018
|
||||
|
@ -4,7 +4,7 @@
|
||||
#define IDC_STATIC -1
|
||||
|
||||
//elements: text, id, x, y, width, height [, style [, extended-style]]
|
||||
IDD_CONFIG DIALOGEX 0, 0, 187, 196
|
||||
IDD_CONFIG DIALOGEX 0, 0, 188, 220
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "in_vgmstream configuration"
|
||||
FONT 8, "MS Sans Serif", 0, 0, 0x0
|
||||
@ -44,12 +44,14 @@ BEGIN
|
||||
LTEXT "Downmix",IDC_STATIC,7,115,48,12
|
||||
EDITTEXT IDC_DOWNMIX_CHANNELS,52,112,37,14,ES_AUTOHSCROLL
|
||||
|
||||
CONTROL "Disable tagfile",IDC_TAGFILE_DISABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,87,10
|
||||
CONTROL "Disable tagfile",IDC_TAGFILE_DISABLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,132,87,10
|
||||
|
||||
CONTROL "Force internal title",IDC_FORCE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,147,87,10
|
||||
CONTROL "Force internal title",IDC_FORCE_TITLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,148,87,10
|
||||
|
||||
CONTROL "Enable unknown exts",IDC_EXTS_UNKNOWN_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,163,87,10
|
||||
CONTROL "Enable unknown exts",IDC_EXTS_UNKNOWN_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,164,87,10
|
||||
|
||||
CONTROL "Enable common exts",IDC_EXTS_COMMON_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,179,87,10
|
||||
CONTROL "Enable common exts",IDC_EXTS_COMMON_ON,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,180,87,10
|
||||
|
||||
PUSHBUTTON "Open Log",IDC_LOG_BUTTON,7,196,50,14
|
||||
|
||||
END
|
||||
|
Loading…
Reference in New Issue
Block a user