Merge pull request #1357 from bnnm/csmp-cleanup

- Fix .CSMP loops [Metroid Prime Trilogy (Wii)]
- Add .opu extension [Ys Memoire: The Oath in Felghana (Switch)]
- Fix some MUSX loops
- internal cleanup
- vrts: add report-diffs option
This commit is contained in:
bnnm 2023-05-15 17:24:43 +02:00 committed by GitHub
commit c0e8fa4a4a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
95 changed files with 1259 additions and 1085 deletions

View File

@ -16,7 +16,7 @@
extern "C" {
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
}
#include "plugin.h"
#include "vfs.h"

View File

@ -52,8 +52,7 @@ def parse_args():
ap.add_argument("-r","--recursive", help="search files in subfolders", action='store_true')
ap.add_argument("-z","--fuzzy", help="fuzzy threshold of +-N PCM16LE", type=int, default=1)
ap.add_argument("-nd","--no-delete", help="don't delete output", action='store_true')
ap.add_argument("-rd","--result-diffs", help="only report full diffs", action='store_true')
ap.add_argument("-rz","--result-fuzzy", help="only report full and fuzzy diffs", action='store_true')
ap.add_argument("-rd","--report-diffs", help="only report full diffs", action='store_true')
ap.add_argument("-p","--performance-both", help="compare decode performance", action='store_true')
ap.add_argument("-pn","--performance-new", help="test performance of new CLI", action='store_true')
ap.add_argument("-po","--performance-old", help="test performance of old CLI", action='store_true')
@ -335,7 +334,15 @@ class VrtsPrinter:
RESULT_MISSING_OLD: 'missing old',
}
def __init__(self):
REPORTS_DIFFS = [
#RESULT_NONE,
RESULT_SIZES,
RESULT_MISSING_NEW,
RESULT_MISSING_OLD
]
def __init__(self, args):
self._args = args
try:
os.system('color') #win only?
except:
@ -347,7 +354,7 @@ class VrtsPrinter:
else:
print(msg)
def result(self, msg, code, fuzzy_diff=0, fuzzy_offset=0):
text = self.TEXT_RESULT.get(code)
color = self.COLOR_RESULT.get(code)
@ -356,7 +363,13 @@ class VrtsPrinter:
msg = "%s: %s" % (msg, text)
if fuzzy_diff != 0:
msg += " (%s @0x%x)" % (fuzzy_diff, fuzzy_offset)
self._print(msg, color)
report = True
if self._args.report_diffs and code not in self.REPORTS_DIFFS:
report = False
if report:
self._print(msg, color)
def info(self, msg):
@ -471,7 +484,7 @@ class VrtsApp:
self._args = args
self._files = VrtsFiles(args)
self._prc = VrtsProcess()
self._p = VrtsPrinter()
self._p = VrtsPrinter(args)
self._cli_new = None
self._cli_old = None
self._temp_files = []

View File

@ -38,7 +38,7 @@
#endif
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
#include "../src/util/samples_ops.h"
#include "../version.h"

View File

@ -5,7 +5,7 @@
#include <getopt.h>
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
#include "../src/util.h"
#include "../src/util/samples_ops.h"
//todo use <>?

View File

@ -10,7 +10,7 @@ vgmstream can be compiled using one of several build scripts that are available
Because each module has different quirks one can't use a single tool for everything. You should be able to build most using a standard *compiler* (GCC/MSVC/Clang) using common *build systems* (scripts/CMake/autotools) in any typical *OS* (Windows/Linux/macOS).
64-bit support should work but hasn't been throughly tested (may have subtle decoding bugs in some codecs), since most used components are plugins for 32-bit players. Windows libraries for extra codecs are included for 32-bit only at the moment.
64-bit support should work but hasn't been as throughly tested, since most used components are plugins for 32-bit players. Windows libraries for extra codecs are included for 32-bit only at the moment.
Though it's rather flexible (like using Windows with GCC and autotools), some combos may be a bit more complex to get working depending on your system and other factors.

View File

@ -122,7 +122,7 @@ Very simplified it goes like this:
- layout prepares samples and offsets to read from the stream *[render_vgmstream_(layout)]*
- decoder reads and decodes bytes into PCM samples *[decode_vgmstream_(coding)]*
- player plays those samples, asks to fill sample buffer again, repeats (until total_samples)
- layout moves offsets back to loop_start when loop_end is reached *[vgmstream_do_loop]*
- layout moves offsets back to loop_start when loop_end is reached *[decode_do_loop]*
- player closes the VGMSTREAM once the stream is finished
vgsmtream's main code (located in src) may be considered "libvgmstream", and plugins interface it through vgmstream.h, mainly the part commented as "vgmstream public API". There isn't a clean external API at the moment, this may be improved later.
@ -201,10 +201,10 @@ If the decoder needs to keep state between calls it may use the VGMSTREAM for co
Adding a new decoder involves:
- *src/coding/(decoder-name).c*: create `decode_x` function that decodes stream data into the passed sample buffer. If the codec requires custom internals it may need `init/reset/seek/free_x`, or other helper functions.
- *src/coding/coding.h*: define decoder's functions and type
- *src/decode.c: get_vgmstream_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples)
- *src/decode.c: get_vgmstream_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way.
- *src/decode.c: decode_get_samples_per_frame*: define so vgmstream only asks for N samples per decode_x call. May return 0 if variable/unknown/etc (decoder then must handle arbitrary number of samples)
- *src/decode.c: decode_get_frame_size*: define so vgmstream can do certain internal calculations. May return 0 if variable/unknown/etc, but blocked/interleave layouts will need to be used in a certain way.
- *src/decode.c: decode_vgmstream*: call `decode_x`, possibly once per channel if the decoder works with a channel at a time.
- *src/decode.c: add handling in `reset/seek/free_codec` if needed
- *src/decode.c: add handling in `reset/seek/decode_free` if needed
- *src/formats.c*: add coding type description
- *src/libvgmstream.vcproj/vcxproj/filters*: add to compile new (decoder-name).c parser in VS
- if the codec depends on a external library don't forget to mark parts with: *#ifdef VGM_USE_X ... #endif*

View File

@ -12,7 +12,7 @@
extern "C" {
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
}
#include "foo_vgmstream.h"
#include "foo_filetypes.h"

View File

@ -270,8 +270,18 @@ function MakePackage
Copy-Item $fb2kFiles32 bin/foobar2000/ -Recurse -Force
Copy-Item $fb2kFiles64 bin/foobar2000/x64/ -Recurse -Force
Remove-Item $fb2kFiles_remove -ErrorAction Ignore
Compress-Archive -Path bin/foobar2000/* bin/foo_input_vgmstream.zip -Force
Move-Item bin/foo_input_vgmstream.zip bin/foo_input_vgmstream.fb2k-component -Force
# workaround for a foobar 2.0 64-bit bug: (earlier?) powershell creates zip paths with '\' (which seem
# non-standard), and apparently that confuses foobar when trying to unpack the zip
try {
# possibly available in github actions
& '7z' a -tzip bin/foo_input_vgmstream.fb2k-component bin/foobar2000/*
} catch {
# works for 32-bit at least
Compress-Archive -Path bin/foobar2000/* bin/foo_input_vgmstream.zip -Force
Move-Item bin/foo_input_vgmstream.zip bin/foo_input_vgmstream.fb2k-component -Force
}
Remove-Item -Path bin/foobar2000 -Recurse -ErrorAction Ignore
}

View File

@ -1,6 +1,10 @@
//possible future public/opaque API
#ifndef _API_H_
#define _API_H_
#include "base/plugins.h"
//possible future public/opaque API
#if 0
#include <stdint.h>

View File

@ -1,14 +1,14 @@
#include "vgmstream.h"
#include "../vgmstream.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "decode.h"
#include "layout/layout.h"
#include "coding/coding.h"
#include "mixing.h"
#include "plugins.h"
/* custom codec handling, not exactly "decode" stuff but here to simplify adding new codecs */
void free_codec(VGMSTREAM* vgmstream) {
void decode_free(VGMSTREAM* vgmstream) {
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type == coding_OGG_VORBIS) {
@ -119,7 +119,7 @@ void free_codec(VGMSTREAM* vgmstream) {
}
void seek_codec(VGMSTREAM* vgmstream) {
void decode_seek(VGMSTREAM* vgmstream) {
if (vgmstream->coding_type == coding_CIRCUS_VQ) {
seek_circus_vq(vgmstream->codec_data, vgmstream->loop_current_sample);
}
@ -213,7 +213,7 @@ void seek_codec(VGMSTREAM* vgmstream) {
}
void reset_codec(VGMSTREAM* vgmstream) {
void decode_reset(VGMSTREAM* vgmstream) {
#ifdef VGM_USE_VORBIS
if (vgmstream->coding_type == coding_OGG_VORBIS) {
@ -325,7 +325,7 @@ void reset_codec(VGMSTREAM* vgmstream) {
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
/* Value returned here is the max (or less) that vgmstream will ask a decoder per
* "decode_x" call. Decoders with variable samples per frame or internal discard
* may return 0 here and handle arbitrary samples_to_do values internally
@ -555,7 +555,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
}
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
int decode_get_frame_size(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_SILENCE:
return 0;
@ -747,21 +747,21 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
}
/* In NDS IMA the frame size is the block size, so the last one is short */
int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream) {
int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return (vgmstream->interleave_last_block_size-4)*2;
default:
return get_vgmstream_samples_per_frame(vgmstream);
return decode_get_samples_per_frame(vgmstream);
}
}
int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream) {
int decode_get_shortframe_size(VGMSTREAM* vgmstream) {
switch (vgmstream->coding_type) {
case coding_NDS_IMA:
return vgmstream->interleave_last_block_size;
default:
return get_vgmstream_frame_size(vgmstream);
return decode_get_frame_size(vgmstream);
}
}
@ -1488,7 +1488,7 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
/* Calculate number of consecutive samples we can decode. Takes into account hitting
* a loop start or end, or going past a single frame. */
int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) {
int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream) {
int samples_to_do;
int samples_left_this_block;
@ -1521,7 +1521,7 @@ int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, V
/* Detect loop start and save values, or detect loop end and restore (loop back).
* Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM* vgmstream) {
int decode_do_loop(VGMSTREAM* vgmstream) {
/*if (!vgmstream->loop_flag) return 0;*/
/* is this the loop end? = new loop, continue from loop_start_sample */
@ -1557,7 +1557,7 @@ int vgmstream_do_loop(VGMSTREAM* vgmstream) {
* - loop_ch[] is copied to ch[] (with custom value)
* - then codec will use ch[]'s offset
* regular codecs may use copied loop_ch[] offset without issue */
seek_codec(vgmstream);
decode_seek(vgmstream);
/* restore! */
memcpy(vgmstream->ch, vgmstream->loop_ch, sizeof(VGMSTREAMCHANNEL) * vgmstream->channels);

View File

@ -1,32 +1,32 @@
#ifndef _DECODE_H
#define _DECODE_H
#include "vgmstream.h"
#include "../vgmstream.h"
void free_codec(VGMSTREAM* vgmstream);
void seek_codec(VGMSTREAM* vgmstream);
void reset_codec(VGMSTREAM* vgmstream);
void decode_free(VGMSTREAM* vgmstream);
void decode_seek(VGMSTREAM* vgmstream);
void decode_reset(VGMSTREAM* vgmstream);
/* Decode samples into the buffer. Assume that we have written samples_written into the
* buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer);
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */
int vgmstream_do_loop(VGMSTREAM* vgmstream);
int decode_do_loop(VGMSTREAM* vgmstream);
/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
int get_vgmstream_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);
int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);
/* Get the number of samples of a single frame (smallest self-contained sample group, 1/N channels) */
int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream);
int decode_get_samples_per_frame(VGMSTREAM* vgmstream);
/* Get the number of bytes of a single frame (smallest self-contained byte group, 1/N channels) */
int get_vgmstream_frame_size(VGMSTREAM* vgmstream);
int decode_get_frame_size(VGMSTREAM* vgmstream);
/* In NDS IMA the frame size is the block size, but last one is shorter */
int get_vgmstream_samples_per_shortframe(VGMSTREAM* vgmstream);
int get_vgmstream_shortframe_size(VGMSTREAM* vgmstream);
int decode_get_samples_per_shortframe(VGMSTREAM* vgmstream);
int decode_get_shortframe_size(VGMSTREAM* vgmstream);
#endif

View File

@ -1,7 +1,7 @@
#include <ctype.h>
#include "../vgmstream.h"
#include "../coding/coding.h"
#include "../mixing.h"
#include "mixing.h"
#include "../util/channel_mappings.h"

View File

@ -1,7 +1,7 @@
#include "vgmstream.h"
#include "../vgmstream.h"
#include "../util/channel_mappings.h"
#include "mixing.h"
#include "plugins.h"
#include "util/channel_mappings.h"
#include <math.h>
#include <limits.h>

View File

@ -1,7 +1,7 @@
#ifndef _MIXING_H_
#define _MIXING_H_
#include "vgmstream.h"
#include "../vgmstream.h"
/* Applies mixing commands to the sample buffer. Mixing must be externally enabled and
* outbuf must big enough to hold output_channels*samples_to_do */

View File

@ -1,7 +1,9 @@
#include "vgmstream.h"
#include "../vgmstream.h"
#include "../util/log.h"
#include "../util/reader_sf.h"
#include "../util/reader_text.h"
#include "plugins.h"
#include "mixing.h"
#include "util/log.h"
/* ****************************************** */

View File

@ -4,8 +4,8 @@
#ifndef _PLUGINS_H_
#define _PLUGINS_H_
#include "streamfile.h"
#include "vgmstream.h"
#include "../streamfile.h"
#include "../vgmstream.h"
/* ****************************************** */

View File

@ -1,5 +1,5 @@
#include "vgmstream.h"
#include "layout/layout.h"
#include "../vgmstream.h"
#include "../layout/layout.h"
#include "render.h"
#include "decode.h"
#include "mixing.h"
@ -222,7 +222,7 @@ void setup_state_vgmstream(VGMSTREAM* vgmstream) {
/*****************************************************************************/
void free_layout(VGMSTREAM* vgmstream) {
void render_free(VGMSTREAM* vgmstream) {
if (vgmstream->layout_type == layout_segmented) {
free_layout_segmented(vgmstream->layout_data);
@ -233,7 +233,7 @@ void free_layout(VGMSTREAM* vgmstream) {
}
}
void reset_layout(VGMSTREAM* vgmstream) {
void render_reset(VGMSTREAM* vgmstream) {
if (vgmstream->layout_type == layout_segmented) {
reset_layout_segmented(vgmstream->layout_data);

View File

@ -1,10 +1,10 @@
#ifndef _RENDER_H
#define _RENDER_H
#include "vgmstream.h"
#include "../vgmstream.h"
void free_layout(VGMSTREAM* vgmstream);
void reset_layout(VGMSTREAM* vgmstream);
void render_free(VGMSTREAM* vgmstream);
void render_reset(VGMSTREAM* vgmstream);
int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream);

View File

@ -1,5 +1,5 @@
#include "vgmstream.h"
#include "layout/layout.h"
#include "../vgmstream.h"
#include "../layout/layout.h"
#include "render.h"
#include "decode.h"
#include "mixing.h"
@ -14,7 +14,7 @@ static void seek_force_loop(VGMSTREAM* vgmstream, int loop_count) {
/* pretend decoder reached loop end so state is set to loop start */
vgmstream->loop_count = loop_count - 1; /* seeking to first loop must become ++ > 0 */
vgmstream->current_sample = vgmstream->loop_end_sample;
vgmstream_do_loop(vgmstream);
decode_do_loop(vgmstream);
}
static void seek_force_decode(VGMSTREAM* vgmstream, int samples) {

View File

@ -2,6 +2,7 @@
#define _CODING_H
#include "../vgmstream.h"
#include "../util/reader_sf.h"
#include "../util/reader_get_nibbles.h"
//todo remove
#include "hca_decoder_clhca.h"

View File

@ -1,5 +1,6 @@
#include "coding.h"
#include "../util/channel_mappings.h"
#include "../util/chunks.h"
#ifdef VGM_USE_FFMPEG

View File

@ -1317,9 +1317,11 @@ size_t xbox_ima_bytes_to_samples(size_t bytes, int channels) {
size_t dat4_ima_bytes_to_samples(size_t bytes, int channels) {
int block_align = 0x20 * channels;
if (channels <= 0) return 0;
int mod = bytes % block_align;
/* DAT4 IMA blocks have a 4 byte header per channel; 2 samples per byte (2 nibbles) */
return (bytes / block_align) * (block_align - 4 * channels) * 2 / channels
+ ((bytes % block_align) ? ((bytes % block_align) - 4 * channels) * 2 / channels : 0); /* unlikely (encoder aligns) */
+ ((mod > 0 && mod > 0x04*channels) ? (mod - 0x04*channels) * 2 / channels : 0); /* unlikely (encoder aligns) */
}
size_t apple_ima4_bytes_to_samples(size_t bytes, int channels) {

View File

@ -61,7 +61,7 @@
#include <stdlib.h>
#include "nwa_decoder.h"
#include "../util/reader_sf.h"
//NWAInfo::UseRunLength
static int is_use_runlength(NWAData* nwa) {

View File

@ -1,8 +1,7 @@
#include "vorbis_custom_decoder.h"
#ifdef VGM_USE_VORBIS
#define BITSTREAM_READ_ONLY /* config */
#include "vorbis_bitreader.h"
#include "../util/bitstream_lsb.h"
#include <vorbis/codec.h>
@ -108,12 +107,12 @@ static int build_header_comment(uint8_t* buf, size_t bufsize) {
if (bytes > bufsize) return 0;
put_8bit (buf+0x00, 0x03); /* packet_type (comments) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_32bitLE(buf+0x07, 0x09); /* vendor_length */
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */
put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_u32le(buf+0x07, 0x09); /* vendor_length */
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
return bytes;
}
@ -129,11 +128,11 @@ static int get_packet_header(STREAMFILE* sf, off_t* offset, size_t* size) {
if (read_streamfile(ibuf,(*offset),ibufsize, sf) != ibufsize)
goto fail;
init_bitstream(&ib, ibuf, ibufsize);
bl_setup(&ib, ibuf, ibufsize);
/* read using Vorbis weird LSF */
rv_bits(&ib, 4,&size_bits);
rv_bits(&ib, (size_bits+1),(uint32_t*)size);
bl_get(&ib, 4,&size_bits);
bl_get(&ib, (size_bits+1),(uint32_t*)size);
/* special meaning, seen in silent frames */
if (size_bits == 0 && *size == 0 && (uint8_t)read_8bit(*offset, sf) == 0x80) {

View File

@ -1,8 +1,8 @@
#include "vorbis_custom_decoder.h"
#ifdef VGM_USE_VORBIS
#include "vorbis_bitreader.h"
#include <vorbis/codec.h>
#include "../util/bitstream_lsb.h"
#define WWISE_VORBIS_USE_PRECOMPILED_WVC 1 /* if enabled vgmstream weights ~150kb more but doesn't need external .wvc packets */
#if WWISE_VORBIS_USE_PRECOMPILED_WVC
@ -212,8 +212,8 @@ static size_t rebuild_packet(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STRE
ok = read_packet(wp, ibuf, ibufsize, sf, offset, data, 0);
if (!ok) goto fail;
init_bitstream(&ow, obuf, obufsize);
init_bitstream(&iw, ibuf, ibufsize);
bl_setup(&ow, obuf, obufsize);
bl_setup(&iw, ibuf, ibufsize);
ok = ww2ogg_generate_vorbis_packet(&ow, &iw, wp, data);
if (!ok) goto fail;
@ -242,8 +242,8 @@ static size_t rebuild_setup(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STREA
ok = read_packet(wp, ibuf, ibufsize, sf, offset, data, 1);
if (!ok) goto fail;
init_bitstream(&ow, obuf, obufsize);
init_bitstream(&iw, ibuf, ibufsize);
bl_setup(&ow, obuf, obufsize);
bl_setup(&iw, ibuf, ibufsize);
ok = ww2ogg_generate_vorbis_setup(&ow,&iw, data, wp->packet_size, sf);
if (!ok) goto fail;
@ -267,16 +267,16 @@ static size_t build_header_identification(uint8_t* buf, size_t bufsize, vorbis_c
blocksizes = (cfg->blocksize_0_exp << 4) | (cfg->blocksize_1_exp);
put_8bit (buf+0x00, 0x01); /* packet_type (id) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_32bitLE(buf+0x07, 0x00); /* vorbis_version (fixed) */
put_8bit (buf+0x0b, cfg->channels); /* audio_channels */
put_32bitLE(buf+0x0c, cfg->sample_rate);/* audio_sample_rate */
put_32bitLE(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
put_32bitLE(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
put_32bitLE(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
put_8bit (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
put_8bit (buf+0x1d, 0x01); /* framing_flag (fixed) */
put_u8 (buf+0x00, 0x01); /* packet_type (id) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_u32le(buf+0x07, 0x00); /* vorbis_version (fixed) */
put_u8 (buf+0x0b, cfg->channels); /* audio_channels */
put_u32le(buf+0x0c, cfg->sample_rate);/* audio_sample_rate */
put_u32le(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
put_u32le(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
put_u32le(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
put_u8 (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
put_u8 (buf+0x1d, 0x01); /* framing_flag (fixed) */
return bytes;
}
@ -286,12 +286,12 @@ static size_t build_header_comment(uint8_t* buf, size_t bufsize) {
if (bytes > bufsize) return 0;
put_8bit (buf+0x00, 0x03); /* packet_type (comments) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_32bitLE(buf+0x07, 0x09); /* vendor_length */
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
put_32bitLE(buf+0x14, 0x00); /* user_comment_list_length */
put_8bit (buf+0x18, 0x01); /* framing_flag (fixed) */
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
memcpy (buf+0x01, "vorbis", 6); /* id */
put_u32le(buf+0x07, 0x09); /* vendor_length */
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
return bytes;
}
@ -306,14 +306,14 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) {
for (i = 0; i < bytes / 4; i++) {
uint32_t c = 0;
rv_bits(ib, 32, &c);
wv_bits(ob, 32, c);
bl_get(ib, 32, &c);
bl_put(ob, 32, c);
}
for (i = 0; i < bytes % 4; i++) {
uint32_t c = 0;
rv_bits(ib, 8, &c);
wv_bits(ob, 8, c);
bl_get(ib, 8, &c);
bl_put(ob, 8, c);
}
#endif
@ -325,8 +325,8 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) {
for (i = 0; i < bytes; i++, iw_pos++) {
uint32_t c = ib->buf[iw_pos];
//rv_bits(ib, 8, &c);
wv_bits(ob, 8, c);
//bl_get(ib, 8, &c);
bl_put(ob, 8, c);
}
ib->b_off += bytes * 8;
@ -337,8 +337,8 @@ static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) {
for (i = 0; i < bytes; i++) {
uint32_t c = 0;
rv_bits(ib, 8, &c);
wv_bits(ob, 8, c);
bl_get(ib, 8, &c);
bl_put(ob, 8, c);
}
return 1;
@ -369,13 +369,13 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
/* audio packet type */
packet_type = 0;
wv_bits(ow, 1, packet_type);
bl_put(ow, 1, packet_type);
/* collect this packet mode from the first byte */
rv_bits(iw, data->mode_bits,&mode_number); /* max 6b */
wv_bits(ow, data->mode_bits, mode_number);
bl_get(iw, data->mode_bits,&mode_number); /* max 6b */
bl_put(ow, data->mode_bits, mode_number);
rv_bits(iw, 8-data->mode_bits,&remainder);
bl_get(iw, 8-data->mode_bits,&remainder);
/* adjust window info */
if (data->mode_blockflag[mode_number]) {
@ -387,9 +387,9 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
uint32_t next_mode_number;
bitstream_t nw;
init_bitstream(&nw, wp->inxt, sizeof(wp->inxt));
bl_setup(&nw, wp->inxt, sizeof(wp->inxt));
rv_bits(&nw, data->mode_bits,&next_mode_number); /* max 6b */
bl_get(&nw, data->mode_bits,&next_mode_number); /* max 6b */
next_blockflag = data->mode_blockflag[next_mode_number];
}
@ -399,15 +399,15 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
}
prev_window_type = data->prev_blockflag;
wv_bits(ow, 1, prev_window_type);
bl_put(ow, 1, prev_window_type);
next_window_type = next_blockflag;
wv_bits(ow, 1, next_window_type);
bl_put(ow, 1, next_window_type);
}
data->prev_blockflag = data->mode_blockflag[mode_number]; /* save for next packet */
wv_bits(ow, 8-data->mode_bits, remainder);
bl_put(ow, 8-data->mode_bits, remainder);
/* rest of the packet (input/output bytes aren't byte aligned here, so no memcpy) */
copy_bytes(ow, iw, wp->packet_size - 1);
@ -417,7 +417,7 @@ static int ww2ogg_generate_vorbis_packet(bitstream_t* ow, bitstream_t* iw, wpack
uint32_t padding = 0;
int padding_bits = 8 - (ow->b_off % 8);
wv_bits(ow, padding_bits, padding);
bl_put(ow, padding_bits, padding);
}
}
else {
@ -480,12 +480,12 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0;
rv_bits(iw, 24,&id);
wv_bits(ow, 24, id);
rv_bits(iw, 16,&dimensions);
wv_bits(ow, 16, dimensions);
rv_bits(iw, 24,&entries);
wv_bits(ow, 24, entries);
bl_get(iw, 24,&id);
bl_put(ow, 24, id);
bl_get(iw, 16,&dimensions);
bl_put(ow, 16, dimensions);
bl_get(iw, 24,&entries);
bl_put(ow, 24, entries);
if (0x564342 != id) { /* "VCB" */
VGM_LOG("Wwise Vorbis: invalid codebook identifier\n");
@ -493,21 +493,21 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
}
/* codeword lengths */
rv_bits(iw, 1,&ordered);
wv_bits(ow, 1, ordered);
bl_get(iw, 1,&ordered);
bl_put(ow, 1, ordered);
if (ordered) {
uint32_t initial_length = 0, current_entry = 0;
rv_bits(iw, 5,&initial_length);
wv_bits(ow, 5, initial_length);
bl_get(iw, 5,&initial_length);
bl_put(ow, 5, initial_length);
current_entry = 0;
while (current_entry < entries) {
uint32_t number = 0;
int numberv_bits = ww2ogg_tremor_ilog(entries-current_entry);
int numbebl_get = ww2ogg_tremor_ilog(entries-current_entry);
rv_bits(iw, numberv_bits,&number);
wv_bits(ow, numberv_bits, number);
bl_get(iw, numbebl_get,&number);
bl_put(ow, numbebl_get, number);
current_entry += number;
}
if (current_entry > entries) {
@ -518,8 +518,8 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
else {
uint32_t sparse = 0;
rv_bits(iw, 1,&sparse);
wv_bits(ow, 1, sparse);
bl_get(iw, 1,&sparse);
bl_put(ow, 1, sparse);
for (i = 0; i < entries; i++) {
uint32_t present_bool = 0;
@ -528,8 +528,8 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
if (sparse) {
uint32_t present = 0;
rv_bits(iw, 1,&present);
wv_bits(ow, 1, present);
bl_get(iw, 1,&present);
bl_put(ow, 1, present);
present_bool = (0 != present);
}
@ -537,16 +537,16 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
if (present_bool) {
uint32_t codeword_length = 0;
rv_bits(iw, 5,&codeword_length);
wv_bits(ow, 5, codeword_length);
bl_get(iw, 5,&codeword_length);
bl_put(ow, 5, codeword_length);
}
}
}
/* lookup table */
rv_bits(iw, 4,&lookup_type);
wv_bits(ow, 4, lookup_type);
bl_get(iw, 4,&lookup_type);
bl_put(ow, 4, lookup_type);
if (0 == lookup_type) {
//VGM_LOG("Wwise Vorbis: no lookup table\n");
@ -556,22 +556,22 @@ static int ww2ogg_codebook_library_copy(bitstream_t* ow, bitstream_t* iw) {
uint32_t quantvals = 0, min = 0, max = 0;
uint32_t value_length = 0, sequence_flag = 0;
rv_bits(iw, 32,&min);
wv_bits(ow, 32, min);
rv_bits(iw, 32,&max);
wv_bits(ow, 32, max);
rv_bits(iw, 4,&value_length);
wv_bits(ow, 4, value_length);
rv_bits(iw, 1,&sequence_flag);
wv_bits(ow, 1, sequence_flag);
bl_get(iw, 32,&min);
bl_put(ow, 32, min);
bl_get(iw, 32,&max);
bl_put(ow, 32, max);
bl_get(iw, 4,&value_length);
bl_put(ow, 4, value_length);
bl_get(iw, 1,&sequence_flag);
bl_put(ow, 1, sequence_flag);
quantvals = ww2ogg_tremor_book_maptype1_quantvals(entries, dimensions);
for (i = 0; i < quantvals; i++) {
uint32_t val = 0, val_bits = 0;
val_bits = value_length+1;
rv_bits(iw, val_bits,&val);
wv_bits(ow, val_bits, val);
bl_get(iw, val_bits,&val);
bl_put(ow, val_bits, val);
}
}
else if (2 == lookup_type) {
@ -596,28 +596,28 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz
id = 0x564342; /* "VCB" */
wv_bits(ow, 24, id);
rv_bits(iw, 4,&dimensions);
wv_bits(ow, 16, dimensions); /* 4 to 16 */
rv_bits(iw, 14,&entries);
wv_bits(ow, 24, entries); /* 14 to 24*/
bl_put(ow, 24, id);
bl_get(iw, 4,&dimensions);
bl_put(ow, 16, dimensions); /* 4 to 16 */
bl_get(iw, 14,&entries);
bl_put(ow, 24, entries); /* 14 to 24*/
/* codeword lengths */
rv_bits(iw, 1,&ordered);
wv_bits(ow, 1, ordered);
bl_get(iw, 1,&ordered);
bl_put(ow, 1, ordered);
if (ordered) {
uint32_t initial_length = 0, current_entry = 0;
rv_bits(iw, 5,&initial_length);
wv_bits(ow, 5, initial_length);
bl_get(iw, 5,&initial_length);
bl_put(ow, 5, initial_length);
current_entry = 0;
while (current_entry < entries) {
uint32_t number = 0;
int numberv_bits = ww2ogg_tremor_ilog(entries-current_entry);
int numbebl_get = ww2ogg_tremor_ilog(entries-current_entry);
rv_bits(iw, numberv_bits,&number);
wv_bits(ow, numberv_bits, number);
bl_get(iw, numbebl_get,&number);
bl_put(ow, numbebl_get, number);
current_entry += number;
}
if (current_entry > entries) {
@ -628,9 +628,9 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz
else {
uint32_t codeword_length_length = 0, sparse = 0;
rv_bits(iw, 3,&codeword_length_length);
rv_bits(iw, 1,&sparse);
wv_bits(ow, 1, sparse);
bl_get(iw, 3,&codeword_length_length);
bl_get(iw, 1,&sparse);
bl_put(ow, 1, sparse);
if (0 == codeword_length_length || 5 < codeword_length_length) {
VGM_LOG("Wwise Vorbis: nonsense codeword length\n");
@ -644,8 +644,8 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz
if (sparse) {
uint32_t present = 0;
rv_bits(iw, 1,&present);
wv_bits(ow, 1, present);
bl_get(iw, 1,&present);
bl_put(ow, 1, present);
present_bool = (0 != present);
}
@ -653,16 +653,16 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz
if (present_bool) {
uint32_t codeword_length = 0;
rv_bits(iw, codeword_length_length,&codeword_length);
wv_bits(ow, 5, codeword_length); /* max 7 (3b) to 5 */
bl_get(iw, codeword_length_length,&codeword_length);
bl_put(ow, 5, codeword_length); /* max 7 (3b) to 5 */
}
}
}
/* lookup table */
rv_bits(iw, 1,&lookup_type);
wv_bits(ow, 4, lookup_type); /* 1 to 4 */
bl_get(iw, 1,&lookup_type);
bl_put(ow, 4, lookup_type); /* 1 to 4 */
if (0 == lookup_type) {
//VGM_LOG("Wwise Vorbis: no lookup table\n");
@ -672,22 +672,22 @@ static int ww2ogg_codebook_library_rebuild(bitstream_t* ow, bitstream_t* iw, siz
uint32_t quantvals = 0, min = 0, max = 0;
uint32_t value_length = 0, sequence_flag = 0;
rv_bits(iw, 32,&min);
wv_bits(ow, 32, min);
rv_bits(iw, 32,&max);
wv_bits(ow, 32, max);
rv_bits(iw, 4,&value_length);
wv_bits(ow, 4, value_length);
rv_bits(iw, 1,&sequence_flag);
wv_bits(ow, 1, sequence_flag);
bl_get(iw, 32,&min);
bl_put(ow, 32, min);
bl_get(iw, 32,&max);
bl_put(ow, 32, max);
bl_get(iw, 4,&value_length);
bl_put(ow, 4, value_length);
bl_get(iw, 1,&sequence_flag);
bl_put(ow, 1, sequence_flag);
quantvals = ww2ogg_tremor_book_maptype1_quantvals(entries, dimensions);
for (i = 0; i < quantvals; i++) {
uint32_t val = 0, val_bits = 0;
val_bits = value_length+1;
rv_bits(iw, val_bits,&val);
wv_bits(ow, val_bits, val);
bl_get(iw, val_bits,&val);
bl_put(ow, val_bits, val);
}
}
else if (2 == lookup_type) {
@ -722,7 +722,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(bitstream_t* ow, uint32_t codeb
cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, sf);
if (cb_size == 0) goto fail;
init_bitstream(&iw, ibuf, ibufsize);
bl_setup(&iw, ibuf, ibufsize);
return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, sf);
fail:
@ -746,8 +746,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
/* Codebooks */
rv_bits(iw, 8,&codebook_count_less1);
wv_bits(ow, 8, codebook_count_less1);
bl_get(iw, 8,&codebook_count_less1);
bl_put(ow, 8, codebook_count_less1);
codebook_count = codebook_count_less1 + 1;
if (data->config.setup_type == WWV_FULL_SETUP) {
@ -770,7 +770,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
int rc;
uint32_t codebook_id = 0;
rv_bits(iw, 10,&codebook_id);
bl_get(iw, 10,&codebook_id);
rc = ww2ogg_codebook_library_rebuild_by_id(ow, codebook_id, data->config.setup_type, sf);
if (!rc) goto fail;
@ -780,9 +780,9 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
/* Time domain transforms */
time_count_less1 = 0;
wv_bits(ow, 6, time_count_less1);
bl_put(ow, 6, time_count_less1);
dummy_time_value = 0;
wv_bits(ow, 16, dummy_time_value);
bl_put(ow, 16, dummy_time_value);
if (data->config.setup_type == WWV_FULL_SETUP) {
@ -792,8 +792,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t setup_packet_size_bits = packet_size * 8;
while (total_bits_read < setup_packet_size_bits) {
rv_bits(iw, 1,&bitly);
wv_bits(ow, 1, bitly);
bl_get(iw, 1,&bitly);
bl_put(ow, 1, bitly);
total_bits_read = iw->b_off;
}
}
@ -806,8 +806,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
/* Floors */
rv_bits(iw, 6,&floor_count_less1);
wv_bits(ow, 6, floor_count_less1);
bl_get(iw, 6,&floor_count_less1);
bl_put(ow, 6, floor_count_less1);
floor_count = floor_count_less1 + 1;
for (i = 0; i < floor_count; i++) {
@ -818,10 +818,10 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
// Always floor type 1
floor_type = 1;
wv_bits(ow, 16, floor_type);
bl_put(ow, 16, floor_type);
rv_bits(iw, 5,&floor1_partitions);
wv_bits(ow, 5, floor1_partitions);
bl_get(iw, 5,&floor1_partitions);
bl_put(ow, 5, floor1_partitions);
memset(floor1_partition_class_list, 0, sizeof(uint32_t)*32);
@ -829,8 +829,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
for (j = 0; j < floor1_partitions; j++) {
uint32_t floor1_partition_class = 0;
rv_bits(iw, 4,&floor1_partition_class);
wv_bits(ow, 4, floor1_partition_class);
bl_get(iw, 4,&floor1_partition_class);
bl_put(ow, 4, floor1_partition_class);
floor1_partition_class_list[j] = floor1_partition_class;
@ -843,19 +843,19 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
for (j = 0; j <= maximum_class; j++) {
uint32_t class_dimensions_less1 = 0, class_subclasses = 0;
rv_bits(iw, 3,&class_dimensions_less1);
wv_bits(ow, 3, class_dimensions_less1);
bl_get(iw, 3,&class_dimensions_less1);
bl_put(ow, 3, class_dimensions_less1);
floor1_class_dimensions_list[j] = class_dimensions_less1 + 1;
rv_bits(iw, 2,&class_subclasses);
wv_bits(ow, 2, class_subclasses);
bl_get(iw, 2,&class_subclasses);
bl_put(ow, 2, class_subclasses);
if (0 != class_subclasses) {
uint32_t masterbook = 0;
rv_bits(iw, 8,&masterbook);
wv_bits(ow, 8, masterbook);
bl_get(iw, 8,&masterbook);
bl_put(ow, 8, masterbook);
if (masterbook >= codebook_count) {
VGM_LOG("Wwise Vorbis: invalid floor1 masterbook\n");
@ -867,8 +867,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t subclass_book_plus1 = 0;
int subclass_book = 0; /* this MUST be int */
rv_bits(iw, 8,&subclass_book_plus1);
wv_bits(ow, 8, subclass_book_plus1);
bl_get(iw, 8,&subclass_book_plus1);
bl_put(ow, 8, subclass_book_plus1);
subclass_book = subclass_book_plus1 - 1;
if (subclass_book >= 0 && subclass_book >= codebook_count) {
@ -878,11 +878,11 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
}
}
rv_bits(iw, 2,&floor1_multiplier_less1);
wv_bits(ow, 2, floor1_multiplier_less1);
bl_get(iw, 2,&floor1_multiplier_less1);
bl_put(ow, 2, floor1_multiplier_less1);
rv_bits(iw, 4,&rangebits);
wv_bits(ow, 4, rangebits);
bl_get(iw, 4,&rangebits);
bl_put(ow, 4, rangebits);
for (j = 0; j < floor1_partitions; j++) {
uint32_t current_class_number = 0;
@ -891,16 +891,16 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
for (k = 0; k < floor1_class_dimensions_list[current_class_number]; k++) {
uint32_t X = 0; /* max 4b (15) */
rv_bits(iw, rangebits,&X);
wv_bits(ow, rangebits, X);
bl_get(iw, rangebits,&X);
bl_put(ow, rangebits, X);
}
}
}
/* Residues */
rv_bits(iw, 6,&residue_count_less1);
wv_bits(ow, 6, residue_count_less1);
bl_get(iw, 6,&residue_count_less1);
bl_put(ow, 6, residue_count_less1);
residue_count = residue_count_less1 + 1;
for (i = 0; i < residue_count; i++) {
@ -908,24 +908,24 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t residue_begin = 0, residue_end = 0, residue_partition_size_less1 = 0, residue_classifications_less1 = 0, residue_classbook = 0;
uint32_t residue_cascade[64+1]; /* 6b +1 */
rv_bits(iw, 2,&residue_type);
wv_bits(ow, 16, residue_type); /* 2b to 16b */
bl_get(iw, 2,&residue_type);
bl_put(ow, 16, residue_type); /* 2b to 16b */
if (residue_type > 2) {
VGM_LOG("Wwise Vorbis: invalid residue type\n");
goto fail;
}
rv_bits(iw, 24,&residue_begin);
wv_bits(ow, 24, residue_begin);
rv_bits(iw, 24,&residue_end);
wv_bits(ow, 24, residue_end);
rv_bits(iw, 24,&residue_partition_size_less1);
wv_bits(ow, 24, residue_partition_size_less1);
rv_bits(iw, 6,&residue_classifications_less1);
wv_bits(ow, 6, residue_classifications_less1);
rv_bits(iw, 8,&residue_classbook);
wv_bits(ow, 8, residue_classbook);
bl_get(iw, 24,&residue_begin);
bl_put(ow, 24, residue_begin);
bl_get(iw, 24,&residue_end);
bl_put(ow, 24, residue_end);
bl_get(iw, 24,&residue_partition_size_less1);
bl_put(ow, 24, residue_partition_size_less1);
bl_get(iw, 6,&residue_classifications_less1);
bl_put(ow, 6, residue_classifications_less1);
bl_get(iw, 8,&residue_classbook);
bl_put(ow, 8, residue_classbook);
residue_classifications = residue_classifications_less1 + 1;
if (residue_classbook >= codebook_count) {
@ -936,21 +936,21 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
memset(residue_cascade, 0, sizeof(uint32_t)*(64+1));
for (j = 0; j < residue_classifications; j++) {
uint32_t high_bits = 0, lowv_bits = 0, bitflag = 0;
uint32_t high_bits = 0, lobl_put = 0, bitflag = 0;
high_bits = 0;
rv_bits(iw, 3,&lowv_bits);
wv_bits(ow, 3, lowv_bits);
bl_get(iw, 3,&lobl_put);
bl_put(ow, 3, lobl_put);
rv_bits(iw, 1,&bitflag);
wv_bits(ow, 1, bitflag);
bl_get(iw, 1,&bitflag);
bl_put(ow, 1, bitflag);
if (bitflag) {
rv_bits(iw, 5,&high_bits);
wv_bits(ow, 5, high_bits);
bl_get(iw, 5,&high_bits);
bl_put(ow, 5, high_bits);
}
residue_cascade[j] = high_bits * 8 + lowv_bits;
residue_cascade[j] = high_bits * 8 + lobl_put;
}
for (j = 0; j < residue_classifications; j++) {
@ -958,8 +958,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
if (residue_cascade[j] & (1 << k)) {
uint32_t residue_book = 0;
rv_bits(iw, 8,&residue_book);
wv_bits(ow, 8, residue_book);
bl_get(iw, 8,&residue_book);
bl_put(ow, 8, residue_book);
if (residue_book >= codebook_count) {
VGM_LOG("Wwise Vorbis: invalid residue book\n");
@ -972,8 +972,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
/* Mappings */
rv_bits(iw, 6,&mapping_count_less1);
wv_bits(ow, 6, mapping_count_less1);
bl_get(iw, 6,&mapping_count_less1);
bl_put(ow, 6, mapping_count_less1);
mapping_count = mapping_count_less1 + 1;
for (i = 0; i < mapping_count; i++) {
@ -982,28 +982,28 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
// always mapping type 0, the only one
mapping_type = 0;
wv_bits(ow, 16, mapping_type);
bl_put(ow, 16, mapping_type);
rv_bits(iw, 1,&submaps_flag);
wv_bits(ow, 1, submaps_flag);
bl_get(iw, 1,&submaps_flag);
bl_put(ow, 1, submaps_flag);
submaps = 1;
if (submaps_flag) {
uint32_t submaps_less1 = 0;
rv_bits(iw, 4,&submaps_less1);
wv_bits(ow, 4, submaps_less1);
bl_get(iw, 4,&submaps_less1);
bl_put(ow, 4, submaps_less1);
submaps = submaps_less1 + 1;
}
rv_bits(iw, 1,&square_polar_flag);
wv_bits(ow, 1, square_polar_flag);
bl_get(iw, 1,&square_polar_flag);
bl_put(ow, 1, square_polar_flag);
if (square_polar_flag) {
uint32_t coupling_steps_less1 = 0, coupling_steps = 0;
rv_bits(iw, 8,&coupling_steps_less1);
wv_bits(ow, 8, coupling_steps_less1);
bl_get(iw, 8,&coupling_steps_less1);
bl_put(ow, 8, coupling_steps_less1);
coupling_steps = coupling_steps_less1 + 1;
for (j = 0; j < coupling_steps; j++) {
@ -1011,10 +1011,10 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
int magnitude_bits = ww2ogg_tremor_ilog(channels-1);
int angle_bits = ww2ogg_tremor_ilog(channels-1);
rv_bits(iw, magnitude_bits,&magnitude);
wv_bits(ow, magnitude_bits, magnitude);
rv_bits(iw, angle_bits,&angle);
wv_bits(ow, angle_bits, angle);
bl_get(iw, magnitude_bits,&magnitude);
bl_put(ow, magnitude_bits, magnitude);
bl_get(iw, angle_bits,&angle);
bl_put(ow, angle_bits, angle);
if (angle == magnitude || magnitude >= channels || angle >= channels) {
VGM_LOG("Wwise Vorbis: invalid coupling (angle=%i, mag=%i, ch=%i)\n", angle, magnitude,channels);
@ -1024,8 +1024,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
}
// a rare reserved field not removed by Ak!
rv_bits(iw, 2,&mapping_reserved);
wv_bits(ow, 2, mapping_reserved);
bl_get(iw, 2,&mapping_reserved);
bl_put(ow, 2, mapping_reserved);
if (0 != mapping_reserved) {
VGM_LOG("Wwise Vorbis: mapping reserved field nonzero\n");
goto fail;
@ -1035,8 +1035,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
for (j = 0; j < channels; j++) {
uint32_t mapping_mux = 0;
rv_bits(iw, 4,&mapping_mux);
wv_bits(ow, 4, mapping_mux);
bl_get(iw, 4,&mapping_mux);
bl_put(ow, 4, mapping_mux);
if (mapping_mux >= submaps) {
VGM_LOG("Wwise Vorbis: mapping_mux >= submaps\n");
goto fail;
@ -1048,18 +1048,18 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t time_config = 0, floor_number = 0, residue_number = 0;
// Another! Unused time domain transform configuration placeholder!
rv_bits(iw, 8,&time_config);
wv_bits(ow, 8, time_config);
bl_get(iw, 8,&time_config);
bl_put(ow, 8, time_config);
rv_bits(iw, 8,&floor_number);
wv_bits(ow, 8, floor_number);
bl_get(iw, 8,&floor_number);
bl_put(ow, 8, floor_number);
if (floor_number >= floor_count) {
VGM_LOG("Wwise Vorbis: invalid floor mapping\n");
goto fail;
}
rv_bits(iw, 8,&residue_number);
wv_bits(ow, 8, residue_number);
bl_get(iw, 8,&residue_number);
bl_put(ow, 8, residue_number);
if (residue_number >= residue_count) {
VGM_LOG("Wwise Vorbis: invalid residue mapping\n");
goto fail;
@ -1069,8 +1069,8 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
/* Modes */
rv_bits(iw, 6,&mode_count_less1);
wv_bits(ow, 6, mode_count_less1);
bl_get(iw, 6,&mode_count_less1);
bl_put(ow, 6, mode_count_less1);
mode_count = mode_count_less1 + 1;
memset(data->mode_blockflag, 0, sizeof(uint8_t)*(64+1)); /* up to max mode_count */
@ -1079,18 +1079,18 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
for (i = 0; i < mode_count; i++) {
uint32_t block_flag = 0, windowtype = 0, transformtype = 0, mapping = 0;
rv_bits(iw, 1,&block_flag);
wv_bits(ow, 1, block_flag);
bl_get(iw, 1,&block_flag);
bl_put(ow, 1, block_flag);
data->mode_blockflag[i] = (block_flag != 0); /* for mod_packets */
windowtype = 0;
transformtype = 0;
wv_bits(ow, 16, windowtype);
wv_bits(ow, 16, transformtype);
bl_put(ow, 16, windowtype);
bl_put(ow, 16, transformtype);
rv_bits(iw, 8,&mapping);
wv_bits(ow, 8, mapping);
bl_get(iw, 8,&mapping);
bl_put(ow, 8, mapping);
if (mapping >= mapping_count) {
VGM_LOG("Wwise Vorbis: invalid mode mapping\n");
goto fail;
@ -1104,7 +1104,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t framing = 0;
framing = 1;
wv_bits(ow, 1, framing);
bl_put(ow, 1, framing);
}
/* remove trailing garbage bits */
@ -1112,7 +1112,7 @@ static int ww2ogg_generate_vorbis_setup(bitstream_t* ow, bitstream_t* iw, vorbis
uint32_t padding = 0;
int padding_bits = 8 - (ow->b_off % 8);
wv_bits(ow, padding_bits, padding);
bl_put(ow, padding_bits, padding);
}

View File

@ -116,7 +116,7 @@ static const char* extension_list[] = {
"bk2",
"bkr", //txth/reserved [P.N.03 (GC), Viewtiful Joe (GC)]
"blk",
"bmdx",
"bmdx", //fake extension (to be removed?)
"bms",
"bnk",
"bnm",
@ -393,6 +393,7 @@ static const char* extension_list[] = {
"ogv",
"oma", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"omu",
"opu",
//"opus", //common
"opusx",
"otm",

View File

@ -1,6 +1,6 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../decode.h"
#include "../base/decode.h"
#include "../coding/coding.h"
@ -11,13 +11,13 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
int samples_written = 0;
int frame_size, samples_per_frame, samples_this_block;
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = 0;
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -28,11 +28,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, readjust back to loop start values */
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -54,7 +54,7 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
break;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
@ -74,11 +74,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
block_update(vgmstream->next_block_offset,vgmstream);
/* update since these may change each block */
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: get_vgmstream_frame_size() really should return bits... */
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;

View File

@ -1,6 +1,6 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../decode.h"
#include "../base/decode.h"
/* Decodes samples for flat streams.
@ -9,19 +9,19 @@ void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vg
int samples_written = 0;
int samples_per_frame, samples_this_block;
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = vgmstream->num_samples; /* do all samples if possible */
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping */
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -1,6 +1,6 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../decode.h"
#include "../base/decode.h"
/* Decodes samples for interleaved streams.
@ -19,20 +19,20 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
/* setup */
{
int frame_size_d = get_vgmstream_frame_size(vgmstream);
samples_per_frame_d = get_vgmstream_samples_per_frame(vgmstream);
int frame_size_d = decode_get_frame_size(vgmstream);
samples_per_frame_d = decode_get_samples_per_frame(vgmstream);
if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail;
samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d;
}
if (has_interleave_first) {
int frame_size_f = get_vgmstream_frame_size(vgmstream);
samples_per_frame_f = get_vgmstream_samples_per_frame(vgmstream); //todo samples per shortframe
int frame_size_f = decode_get_frame_size(vgmstream);
samples_per_frame_f = decode_get_samples_per_frame(vgmstream); //todo samples per shortframe
if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail;
samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f;
}
if (has_interleave_last) {
int frame_size_l = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame_l = get_vgmstream_samples_per_shortframe(vgmstream);
int frame_size_l = decode_get_shortframe_size(vgmstream);
samples_per_frame_l = decode_get_samples_per_shortframe(vgmstream);
if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail;
samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l;
}
@ -62,7 +62,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, restore standard interleave sizes */
if (has_interleave_first &&
@ -83,7 +83,7 @@ void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTR
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;

View File

@ -1,8 +1,8 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../decode.h"
#include "../mixing.h"
#include "../plugins.h"
#include "../base/decode.h"
#include "../base/mixing.h"
#include "../base/plugins.h"
#define VGMSTREAM_MAX_LAYERS 255
#define VGMSTREAM_LAYER_SAMPLE_BUFFER 8192
@ -25,12 +25,12 @@ void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM*
int layer, ch;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below) */
continue;
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
@ -105,7 +105,7 @@ void loop_layout_layered(VGMSTREAM* vgmstream, int32_t loop_sample) {
* calls to do_loop work (used in seek_vgmstream) */
if (data->layers[layer]->loop_flag) { /* mixing looping and non-looping layers is allowed */
data->layers[layer]->current_sample = data->layers[layer]->loop_end_sample; /* forces do loop */
vgmstream_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */
decode_do_loop(data->layers[layer]); /* guaranteed to work should loop_layout be called */
}
else {
/* needed when mixing non-looping layers and installing loop externally */

View File

@ -3,6 +3,7 @@
#include "../streamtypes.h"
#include "../vgmstream.h"
#include "../util/reader_sf.h"
/* blocked layouts */
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream);

View File

@ -1,8 +1,8 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../decode.h"
#include "../mixing.h"
#include "../plugins.h"
#include "../base/decode.h"
#include "../base/mixing.h"
#include "../base/plugins.h"
#define VGMSTREAM_MAX_SEGMENTS 1024
#define VGMSTREAM_SEGMENT_SAMPLE_BUFFER 8192
@ -34,7 +34,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below, changes segments/state) */
samples_this_block = vgmstream_get_samples(data->segments[data->current_segment]);
mixing_info(data->segments[data->current_segment], NULL, &current_channels);
@ -60,7 +60,7 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
}
samples_to_do = get_vgmstream_samples_to_do(samples_this_block, sample_count, vgmstream);
samples_to_do = decode_get_samples_to_do(samples_this_block, sample_count, vgmstream);
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */

View File

@ -81,15 +81,15 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="api.h" />
<ClInclude Include="decode.h" />
<ClInclude Include="mixing.h" />
<ClInclude Include="plugins.h" />
<ClInclude Include="render.h" />
<ClInclude Include="streamfile.h" />
<ClInclude Include="streamtypes.h" />
<ClInclude Include="util.h" />
<ClInclude Include="vgmstream.h" />
<ClInclude Include="vgmstream_types.h" />
<ClInclude Include="base\decode.h" />
<ClInclude Include="base\mixing.h" />
<ClInclude Include="base\plugins.h" />
<ClInclude Include="base\render.h" />
<ClInclude Include="coding\acm_decoder_libacm.h" />
<ClInclude Include="coding\circus_decoder_lib.h" />
<ClInclude Include="coding\circus_decoder_lib_data.h" />
@ -110,7 +110,6 @@
<ClInclude Include="coding\tac_decoder_lib.h" />
<ClInclude Include="coding\tac_decoder_lib_data.h" />
<ClInclude Include="coding\tac_decoder_lib_ops.h" />
<ClInclude Include="coding\vorbis_bitreader.h" />
<ClInclude Include="coding\vorbis_custom_data_fsb.h" />
<ClInclude Include="coding\vorbis_custom_data_wwise.h" />
<ClInclude Include="coding\vorbis_custom_decoder.h" />
@ -168,32 +167,37 @@
<ClInclude Include="meta\xwb_xsb.h" />
<ClInclude Include="meta\xwma_konami_streamfile.h" />
<ClInclude Include="meta\zsnd_streamfile.h" />
<ClInclude Include="util\bitstream_lsb.h" />
<ClInclude Include="util\bitstream_msb.h" />
<ClInclude Include="util\channel_mappings.h" />
<ClInclude Include="util\chunks.h" />
<ClInclude Include="util\companion_files.h" />
<ClInclude Include="util\cri_keys.h" />
<ClInclude Include="util\cri_utf.h" />
<ClInclude Include="util\endianness.h" />
<ClInclude Include="util\log.h" />
<ClInclude Include="util\m2_psb.h" />
<ClInclude Include="util\miniz.h" />
<ClInclude Include="util\paths.h" />
<ClInclude Include="util\reader_get.h" />
<ClInclude Include="util\reader_get_nibbles.h" />
<ClInclude Include="util\reader_put.h" />
<ClInclude Include="util\reader_sf.h" />
<ClInclude Include="util\reader_text.h" />
<ClInclude Include="util\samples_ops.h" />
<ClInclude Include="util\text_reader.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="decode.c" />
<ClCompile Include="formats.c" />
<ClCompile Include="mixing.c" />
<ClCompile Include="plugins.c" />
<ClCompile Include="render.c" />
<ClCompile Include="seek.c" />
<ClCompile Include="streamfile.c" />
<ClCompile Include="util.c" />
<ClCompile Include="vgmstream.c" />
<ClCompile Include="base\decode.c" />
<ClCompile Include="base\info.c" />
<ClCompile Include="base\mixing.c" />
<ClCompile Include="base\plugins.c" />
<ClCompile Include="base\render.c" />
<ClCompile Include="base\seek.c" />
<ClCompile Include="coding\acm_decoder.c" />
<ClCompile Include="coding\acm_decoder_decode.c" />
<ClCompile Include="coding\acm_decoder_util.c" />
@ -736,12 +740,14 @@
<ClCompile Include="meta\zwdsp.c" />
<ClCompile Include="meta\zwv.c" />
<ClCompile Include="util\chunks.c" />
<ClCompile Include="util\companion_files.c" />
<ClCompile Include="util\cri_keys.c" />
<ClCompile Include="util\cri_utf.c" />
<ClCompile Include="util\log.c" />
<ClCompile Include="util\m2_psb.c" />
<ClCompile Include="util\miniz.c" />
<ClCompile Include="util\reader_put.c" />
<ClCompile Include="util\paths.c" />
<ClCompile Include="util\reader.c" />
<ClCompile Include="util\samples_ops.c" />
<ClCompile Include="util\text_reader.c" />
</ItemGroup>

View File

@ -68,18 +68,6 @@
<ClInclude Include="api.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="decode.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="mixing.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="plugins.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="render.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="streamfile.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -95,6 +83,18 @@
<ClInclude Include="vgmstream_types.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="base\decode.h">
<Filter>base\Header Files</Filter>
</ClInclude>
<ClInclude Include="base\mixing.h">
<Filter>base\Header Files</Filter>
</ClInclude>
<ClInclude Include="base\plugins.h">
<Filter>base\Header Files</Filter>
</ClInclude>
<ClInclude Include="base\render.h">
<Filter>base\Header Files</Filter>
</ClInclude>
<ClInclude Include="coding\acm_decoder_libacm.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
@ -155,9 +155,6 @@
<ClInclude Include="coding\tac_decoder_lib_ops.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
<ClInclude Include="coding\vorbis_bitreader.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
<ClInclude Include="coding\vorbis_custom_data_fsb.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
@ -329,6 +326,9 @@
<ClInclude Include="meta\zsnd_streamfile.h">
<Filter>meta\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\bitstream_lsb.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\bitstream_msb.h">
<Filter>util\Header Files</Filter>
</ClInclude>
@ -338,6 +338,9 @@
<ClInclude Include="util\chunks.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\companion_files.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\cri_keys.h">
<Filter>util\Header Files</Filter>
</ClInclude>
@ -356,6 +359,9 @@
<ClInclude Include="util\miniz.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\paths.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\reader_get.h">
<Filter>util\Header Files</Filter>
</ClInclude>
@ -365,6 +371,12 @@
<ClInclude Include="util\reader_put.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\reader_sf.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\reader_text.h">
<Filter>util\Header Files</Filter>
</ClInclude>
<ClInclude Include="util\samples_ops.h">
<Filter>util\Header Files</Filter>
</ClInclude>
@ -373,24 +385,9 @@
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="decode.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="formats.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="mixing.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="plugins.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="render.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="seek.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="streamfile.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -400,9 +397,24 @@
<ClCompile Include="vgmstream.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="base\decode.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\info.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\mixing.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\plugins.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\render.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\seek.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\acm_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
@ -2029,6 +2041,9 @@
<ClCompile Include="util\chunks.c">
<Filter>util\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\companion_files.c">
<Filter>util\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\cri_keys.c">
<Filter>util\Source Files</Filter>
</ClCompile>
@ -2044,7 +2059,10 @@
<ClCompile Include="util\miniz.c">
<Filter>util\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\reader_put.c">
<ClCompile Include="util\paths.c">
<Filter>util\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\reader.c">
<Filter>util\Source Files</Filter>
</ClCompile>
<ClCompile Include="util\samples_ops.c">

View File

@ -7,6 +7,7 @@
#include "adx_keys.h"
#include "../coding/coding.h"
#include "../util/cri_keys.h"
#include "../util/companion_files.h"
#ifdef VGM_DEBUG_OUTPUT

View File

@ -2,6 +2,7 @@
#include "../coding/coding.h"
#include "ahx_keys.h"
#include "../util/cri_keys.h"
#include "../util/companion_files.h"
#ifdef VGM_USE_MPEG
static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey);

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/companion_files.h"
//typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type_t;

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* .BAF - Bizarre Creations bank file [Blur (PS3), Project Gotham Racing 4 (X360), Geometry Wars (PC)] */
VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
@ -8,7 +10,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
size_t stream_size;
uint32_t channel_count, sample_rate, num_samples, version, codec, tracks;
int loop_flag, total_subsongs, target_subsong = sf->stream_index;
uint32_t (*read_u32)(off_t,STREAMFILE*);
read_u32_t read_u32;
/* checks */
if (!is_id32be(0x00, sf, "BANK"))
@ -18,7 +20,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
goto fail;
/* use BANK size to check endianness */
if (guess_endianness32bit(0x04,sf)) {
if (guess_endian32(0x04,sf)) {
read_u32 = read_u32be;
} else {
read_u32 = read_u32le;

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
#include "../util/endianness.h"
/* BKHD - Wwise soundbank container */
@ -10,8 +11,8 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) {
uint32_t subfile_offset, subfile_size, base_offset = 0;
uint32_t subfile_id, version;
int big_endian, is_dummy = 0, is_wmid = 0;
uint32_t (*read_u32)(off_t,STREAMFILE*);
float (*read_f32)(off_t,STREAMFILE*);
read_u32_t read_u32;
read_f32_t read_f32;
int total_subsongs, target_subsong = sf->stream_index;
int prefetch = 0;
@ -24,7 +25,7 @@ VGMSTREAM* init_vgmstream_bkhd(STREAMFILE* sf) {
base_offset = 0x0c;
if (!is_id32be(base_offset + 0x00, sf, "BKHD"))
goto fail;
big_endian = guess_endianness32bit(base_offset + 0x04, sf);
big_endian = guess_endian32(base_offset + 0x04, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_f32 = big_endian ? read_f32be : read_f32le;
@ -200,7 +201,7 @@ VGMSTREAM* init_vgmstream_bkhd_fx(STREAMFILE* sf) {
/* .wem: used when (rarely) external */
if (!check_extensions(sf,"wem,bnk"))
goto fail;
big_endian = guess_endianness32bit(0x00, sf);
big_endian = guess_endian32(0x00, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
/* Not an actual stream but typically convolution reverb models and other FX plugin helpers.

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
#include "../util/companion_files.h"
#include "bnsf_keys.h"

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/cri_utf.h"
#include "../util/companion_files.h"
typedef enum { HCA, CWAV, ADX } cpk_type_t;

View File

@ -1,8 +1,9 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii), Donkey Kong Country Returns (Wii)] */
/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii)-sfx, Donkey Kong Country Returns (Wii)-sfx] */
VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset, first_offset = 0x08, chunk_offset;
@ -10,21 +11,20 @@ VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) {
/* checks */
if (!check_extensions(sf, "csmp"))
goto fail;
if (!is_id32be(0x00, sf, "CSMP"))
goto fail;
if (read_u32be(0x04, sf) != 1)
if (!check_extensions(sf, "csmp"))
goto fail;
if (read_u32be(0x04, sf) != 1) /* version? */
goto fail;
if (!find_chunk(sf, 0x44415441,first_offset,0, &chunk_offset,NULL, 1, 0)) /*"DATA"*/
/* INFO > PAD > DATA */
if (!find_chunk(sf, get_id32be("DATA"),first_offset,0, &chunk_offset,NULL, 1, 0))
goto fail;
/* contains standard DSP header, but somehow some validations (start/loop ps)
* don't seem to work, so no point to handle as standard DSP */
channels = 1;
loop_flag = read_s16be(chunk_offset+0x0c,sf);
/* contains a not quite standard DSP header */
channels = 1; /* also at INFO + 0x00? (in practice uses dual stereo in separate files) */
loop_flag = read_s16be(chunk_offset+0x0c,sf); /* also at INFO + 0x01 */
start_offset = chunk_offset + 0x60;
@ -35,10 +35,8 @@ VGMSTREAM* init_vgmstream_csmp(STREAMFILE* sf) {
vgmstream->meta_type = meta_CSMP;
vgmstream->sample_rate = read_s32be(chunk_offset+0x08,sf);
vgmstream->num_samples = read_s32be(chunk_offset+0x00,sf);
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x10,sf));
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_u32be(chunk_offset+0x14,sf)) + 1;
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->loop_start_sample = read_s32be(chunk_offset+0x10,sf); /* unlike regular DSP's nibbles */
vgmstream->loop_end_sample = read_s32be(chunk_offset+0x14,sf) + 1;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;

View File

@ -2,6 +2,8 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/companion_files.h"
#include "ea_eaac_streamfile.h"
/* EAAudioCore (aka SND10) formats, EA's current audio middleware */
@ -85,7 +87,7 @@ VGMSTREAM* init_vgmstream_ea_snu(STREAMFILE* sf) {
* 0x0c(4): some sub-offset? (0x20, found when @0x01 is set) */
/* use start_offset as endianness flag */
if (guess_endianness32bit(0x08,sf)) {
if (guess_endian32(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -125,7 +127,7 @@ VGMSTREAM* init_vgmstream_ea_abk_eaac(STREAMFILE* sf) {
goto fail;
/* use table offset to check endianness */
if (guess_endianness32bit(0x1C, sf)) {
if (guess_endian32(0x1C, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {

View File

@ -1,6 +1,8 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/companion_files.h"
#include "ea_schl_streamfile.h"
/* header version */
@ -222,7 +224,7 @@ VGMSTREAM* init_vgmstream_ea_schl_video(STREAMFILE* sf) {
}
/* use block size to check endianness */
if (guess_endianness32bit(0x04, sf)) {
if (guess_endian32(0x04, sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -329,7 +331,7 @@ VGMSTREAM* init_vgmstream_ea_abk(STREAMFILE* sf) {
goto fail;
/* use table offset to check endianness */
if (guess_endianness32bit(0x1C, sf)) {
if (guess_endian32(0x1C, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
@ -1142,7 +1144,7 @@ static VGMSTREAM* parse_schl_block(STREAMFILE* sf, off_t offset) {
ea.codec_config |= (header_id & 0xFFFF) << 16;
}
if (guess_endianness32bit(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */
if (guess_endian32(offset + 0x04, sf)) { /* size is always LE, except in early SS/MAC */
header_size = read_32bitBE(offset + 0x04, sf);
ea.codec_config |= 0x02;
}

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "../util/endianness.h"
/* EA WVE (Ad10) - from early Electronic Arts movies [Wing Commander 3/4 (PS1), Madden NHL 97 (PC)-w95] */
VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) {
@ -22,7 +23,7 @@ VGMSTREAM* init_vgmstream_ea_wve_ad10(STREAMFILE* sf) {
!is_id32be(0x00, sf, "Ad11")) /* last audio block, but could be first */
goto fail;
big_endian = guess_endianness32bit(0x04, sf);
big_endian = guess_endian32(0x04, sf);
if (is_id32be(0x00, sf, "AABB"))
start_offset += big_endian ? read_u32be(0x04, sf) : read_u32le(0x04, sf);

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/companion_files.h"
#include "../util/chunks.h"
#include "ogg_vorbis_streamfile.h"
#include "encrypted_bgm_streamfile.h"
#include "encrypted_mc161_streamfile.h"

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
static int get_subsongs(STREAMFILE* sf, off_t fsb5_offset, size_t fsb5_size);
@ -16,13 +17,14 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "RIFF"))
goto fail;
if (!is_id32be(0x08,sf, "FEV "))
goto fail;
if (!check_extensions(sf, "bank"))
goto fail;
if (read_u32be(0x00,sf) != 0x52494646) /* "RIFF" */
goto fail;
if (read_u32be(0x08,sf) != 0x46455620) /* "FEV " */
goto fail;
version = read_u32le(0x14,sf); /* newer FEV have some kind of sub-version at 0x18 */
/* .fev is an event format referencing various external .fsb, but FMOD can bake .fev and .fsb to

View File

@ -1,4 +1,5 @@
#include "meta.h"
#include "../util/companion_files.h"
#include "fsb_keys.h"
#include "fsb_encrypted_streamfile.h"

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */
VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {

View File

@ -3,6 +3,7 @@
#include "../coding/coding.h"
#include "../coding/hca_decoder_clhca.h"
#include "../util/channel_mappings.h"
#include "../util/companion_files.h"
#ifdef VGM_DEBUG_OUTPUT
//#define HCA_BRUTEFORCE

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* LucasArts iMUSE (Interactive Music Streaming Engine) formats */

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
typedef enum { PCM16, MSADPCM, DSP_HEAD, DSP_BODY, AT9, MSF_APEX, XMA2 } kwb_codec;
@ -594,7 +595,7 @@ static int parse_kwb(kwb_header* kwb, STREAMFILE* sf_h, STREAMFILE* sf_b) {
head_offset = 0x00;
body_offset = 0x00;
kwb->big_endian = guess_endianness32bit(head_offset + 0x08, sf_h);
kwb->big_endian = guess_endian32(head_offset + 0x08, sf_h);
read_u32 = kwb->big_endian ? read_u32be : read_u32le;
}

View File

@ -2,6 +2,8 @@
#define _META_H
#include "../vgmstream.h"
#include "../util/reader_sf.h"
#include "../util/reader_text.h"
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE* sf);

View File

@ -33,7 +33,7 @@ VGMSTREAM* init_vgmstream_mul(STREAMFILE* sf) {
read_u32be(0x1c,sf) != 0)
goto fail;
big_endian = guess_endianness32bit(0x00, sf);
big_endian = guess_endian32(0x00, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_f32 = big_endian ? read_f32be : read_f32le;

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/chunks.h"
static void load_name(char* name, size_t name_size, STREAMFILE* sf, int big_endian, int total_subsongs, int target_subsong);
@ -19,21 +21,21 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) {
/* checks */
version = read_u32be(0x00,sf);
if (version != 0x00020000 && /* v2.0 (rare, ex. Ridge Race 6 (X360)) */
version != 0x00020100 && /* v2.1 (common) */
version != 0x01020100) /* same but LE (seen in PSP/PC games, except PS4) */
goto fail;
if (read_u32be(0x04,sf) != 0x00000000) /* null */
goto fail;
/* .nub: standard
* .nub2: rare [iDOLM@STER - Gravure For You (PS3)] */
if (!check_extensions(sf, "nub,nub2"))
goto fail;
version = read_32bitBE(0x00,sf);
if (version != 0x00020000 && /* v2.0 (rare, ex. Ridge Race 6 (X360)) */
version != 0x00020100 && /* v2.1 (common) */
version != 0x01020100) /* same but LE (seen in PSP/PC games, except PS4) */
goto fail;
if (read_32bitBE(0x04,sf) != 0x00000000) /* null */
goto fail;
/* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */
big_endian = guess_endianness32bit(0x18, sf);
big_endian = guess_endian32(0x18, sf);
if (big_endian) {
read_32bit = read_32bitBE;
} else{
@ -249,7 +251,7 @@ VGMSTREAM* init_vgmstream_nub_wav(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x77617600) /* "wav\0" "*/
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
} else {
@ -313,7 +315,7 @@ VGMSTREAM* init_vgmstream_nub_vag(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x76616700) /* "vag\0" */
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
@ -598,7 +600,7 @@ VGMSTREAM* init_vgmstream_nub_is14(STREAMFILE* sf) {
if (read_32bitBE(0x00,sf) != 0x69733134) /* "is14" */
goto fail;
if (guess_endianness32bit(0x1c, sf)) {
if (guess_endian32(0x1c, sf)) {
read_32bit = read_32bitBE;
} else{
read_32bit = read_32bitLE;

View File

@ -133,9 +133,10 @@ VGMSTREAM* init_vgmstream_opus_std(STREAMFILE* sf) {
if (read_u32le(0x00,sf) != 0x80000001) /* 'basic info' chunk */
goto fail;
/* .opus: standard
* .bgm: Cotton Reboot (Switch) */
if (!check_extensions(sf,"opus,lopus,bgm"))
/* .opus: standard / .lopus: for plugins
* .bgm: Cotton Reboot (Switch)
* .opu: Ys Memoire: The Oath in Felghana (Switch) */
if (!check_extensions(sf,"opus,lopus,bgm,opu"))
goto fail;
offset = 0x00;

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* .SBK - from Addiction Pinball (PC) */
VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) {
@ -11,13 +13,12 @@ VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) {
int target_subsong = sf->stream_index, total_subsongs, loop_flag, is_streamed;
/* checks */
if (!check_extensions(sf, "sbk"))
if (!is_id32be(0x00,sf, "RIFF"))
goto fail;
if (!is_id32be(0x08,sf, "SBNK"))
goto fail;
/* check header */
if (read_u32be(0x00, sf) != 0x52494646) /* "RIFF" */
goto fail;
if (read_u32be(0x08, sf) != 0x53424E4B) /* "SBNK" */
if (!check_extensions(sf, "sbk"))
goto fail;
if (!find_chunk_le(sf, 0x57415649, 0x0c, 0, &table_offset, &table_size)) /* "WAVI" */

View File

@ -1,5 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* SEG - from Stormfront games [Eragon (multi), Forgotten Realms: Demon Stone (multi) */
VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
@ -19,7 +21,7 @@ VGMSTREAM* init_vgmstream_seg(STREAMFILE* sf) {
codec = read_32bitBE(0x04,sf);
/* 0x08: version? (2: Eragon, Spiderwick Chronicles Wii / 3: Spiderwick Chronicles X360 / 4: Spiderwick Chronicles PC) */
if (guess_endianness32bit(0x08,sf)) {
if (guess_endian32(0x08,sf)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* also see init_vgmstream_dsp_sps_n1 and init_vgmstream_opus_sps_n1 */
@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sps_n1(STREAMFILE* sf) {
if (!check_extensions(sf,"sps"))
goto fail;
if (guess_endianness32bit(0x00, sf)) { /* PS3 */
if (guess_endian32(0x00, sf)) { /* PS3 */
read_u32 = read_u32be;
read_u16 = read_u16be;
}

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
/* SSPR - Capcom container [Sengoku Basara 4 (PS3/PS4), Mega Man Zero ZX Legacy Collection (PS4)] */
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) {
@ -21,7 +22,7 @@ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) {
/* Simple (audio only) container used some Capcom games (common engine?).
* Some files come with a .stqr with unknown data (cues?). */
big_endian = guess_endianness32bit(0x04, sf); /* 0x01 (version?) */
big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */
read_u32 = big_endian ? read_u32be : read_u32le;
total_subsongs = read_u32(0x08,sf);

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */

View File

@ -4,6 +4,7 @@
#include "txth_streamfile.h"
#include "../util/text_reader.h"
#include "../util/endianness.h"
#include "../util/paths.h"
#define TXT_LINE_MAX 2048 /* probably ~1000 would be ok */
#define TXT_LINE_KEY_MAX 128

View File

@ -1,9 +1,10 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "../mixing.h"
#include "../plugins.h"
#include "../base/mixing.h"
#include "../base/plugins.h"
#include "../util/text_reader.h"
#include "../util/paths.h"
#include <math.h>

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "ubi_bao_streamfile.h"
#define BAO_MIN_VERSION 0x1B
@ -1570,7 +1571,7 @@ static void config_bao_endian(ubi_bao_header* bao, off_t offset, STREAMFILE* sf)
* This could be done once as all BAOs share endianness */
/* negate as fields looks like LE (0xN0000000) */
bao->big_endian = !guess_endianness32bit(offset+bao->cfg.bao_class, sf);
bao->big_endian = !guess_endian32(offset+bao->cfg.bao_class, sf);
}
@ -1714,7 +1715,7 @@ static int config_bao_version(ubi_bao_header* bao, STREAMFILE* sf) {
/* next BAO uses machine endianness, entry should always exist
* (maybe should use project BAO to detect?) */
if (guess_endianness32bit(header_size + 0x04, sf)) {
if (guess_endian32(header_size + 0x04, sf)) {
version |= 0xFF00; /* signal Wii=BE, but don't modify original */
}
}

View File

@ -1,6 +1,7 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/chunks.h"
typedef enum { MSADPCM, DSP, MP3, XMA2 } ckd_codec;
@ -30,7 +31,7 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) {
if (!is_id32be(0x0c,sf, "fmt "))
goto fail;
big_endian = guess_endianness32bit(0x04, sf);
big_endian = guess_endian32(0x04, sf);
read_u32 = big_endian ? read_u32be : read_u32le;
read_u16 = big_endian ? read_u16be : read_u16le;

View File

@ -2,6 +2,7 @@
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util/endianness.h"
#include "../util/chunks.h"
typedef enum { PCM, UBI, PSX, DSP, XIMA, ATRAC3, XMA2, MP3, SILENCE } ubi_hx_codec;

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* VXN - from Gameloft mobile games */
@ -11,11 +12,12 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
int total_subsongs, target_subsong = sf->stream_index;
/* checks */
if (!is_id32be(0x00,sf, "VoxN"))
goto fail;
if (!check_extensions(sf,"vxn"))
goto fail;
if (!is_id32be(0x00,sf, "VoxN"))
goto fail;
/* 0x04: chunk size */
/* 0x08: ASCII version? ("0.0.1") */
if (read_u32le(0x10,sf) != get_streamfile_size(sf))

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
//#include <ctype.h>
/* .WBK - seen in some Treyarch games [Spider-Man 2, Ultimate Spider-Man, Call of Duty 2: Big Red One] */

View File

@ -1,64 +1,65 @@
#include "meta.h"
#include "../util.h"
#include "../coding/coding.h"
#include "../util/chunks.h"
/* XAU - XPEC Entertainment sound format (Beat Down PS2/Xbox, Spectral Force Chronicle [SLPM-65967]) */
VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
/* XAU - XPEC Entertainment sound format [Beat Down (PS2/Xbox), Spectral Force Chronicle (PS2)] */
VGMSTREAM* init_vgmstream_xau(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, type, loop_start, loop_end;
int loop_flag, channels, type, loop_start, loop_end;
/* check extension */
if (!check_extensions(streamFile, "xau"))
goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x58415500) /* "XAU\0" "*/
if (!is_id32be(0x00,sf, "XAU\0"))
goto fail;
if (read_32bitLE(0x08,streamFile) != 0x40) /* header start */
if (!check_extensions(sf, "xau"))
goto fail;
if (read_32bitLE(0x08,sf) != 0x40) /* header start */
goto fail;
/* 0x04: version? (0x100) */
type = read_32bitBE(0x0c, streamFile);
loop_start = read_32bitLE(0x10, streamFile);
loop_end = read_32bitLE(0x14, streamFile);
loop_flag = (loop_end > 0);
type = read_32bitBE(0x0c, sf);
loop_start = read_32bitLE(0x10, sf);
loop_end = read_32bitLE(0x14, sf);
loop_flag = (loop_end > 0);
channel_count = read_8bit(0x18,streamFile);
channels = read_8bit(0x18,sf);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->channels = channel_count;
vgmstream->channels = channels;
vgmstream->meta_type = meta_XAU;
/* miniheader over a common header with some tweaks, so we'll simplify parsing */
switch(type) {
case 0x50533200: /* "PS2\0" */
if (read_32bitBE(0x40,streamFile) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */
/* miniheader over a common header with some tweaks, so we'll simplify parsing */
switch(type) {
case 0x50533200: /* "PS2\0" */
if (read_32bitBE(0x40,sf) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */
start_offset = 0x800;
vgmstream->sample_rate = read_32bitBE(0x50, streamFile);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,streamFile) * channel_count, channel_count);
start_offset = 0x800;
vgmstream->sample_rate = read_32bitBE(0x50, sf);
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,sf) * channels, channels);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x8000;
break;
vgmstream->interleave_block_size = 0x8000;
break;
case 0x58420000: /* "XB\0\0" */
if (read_32bitBE(0x40,streamFile) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */
case 0x58420000: /* "XB\0\0" */
if (read_32bitBE(0x40,sf) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */
/* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */
if (!find_chunk_le(streamFile, 0x64617461, 0x4c, 0, &start_offset, NULL) )
goto fail;
/* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */
if (!find_chunk_le(sf, 0x64617461, 0x4c, 0, &start_offset, NULL) )
goto fail;
vgmstream->sample_rate = read_32bitLE(0x58, streamFile);
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count);
vgmstream->sample_rate = read_32bitLE(0x58, sf);
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, sf), channels);
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
@ -66,13 +67,13 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_none;
break;
default:
goto fail;
}
default:
goto fail;
}
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
goto fail;
return vgmstream;

View File

@ -2,17 +2,20 @@
#define _XNB_STREAMFILE_H_
//#define XNB_ENABLE_LZX 1
#include "../streamfile.h"
#include "../util/log.h"
#include "xnb_lz4mg.h"
#ifdef XNB_ENABLE_LZX
/* lib from https://github.com/sumatrapdfreader/chmlib
/* can be safely enabled but useless since LZX isn't used for audio assets
* lib from https://github.com/sumatrapdfreader/chmlib
* which is a cleaned-up version of https://github.com/jedwing/CHMLib */
#include "lzx.h"
#include "../utils/lzx.h"
#define LZX_XNB_WINDOW_BITS 16
#endif
#include "xnb_lz4mg.h"
#define XNB_TYPE_LZX 1
#define XNB_TYPE_LZ4 2

View File

@ -2,6 +2,7 @@
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "xvag_streamfile.h"
#include "../util/chunks.h"
typedef struct {
@ -41,12 +42,13 @@ VGMSTREAM* init_vgmstream_xvag(STREAMFILE* sf) {
/* checks */
if (!is_id32be(0x00,sf, "XVAG"))
goto fail;
/* .xvag: standard
* (extensionless): The Last of Us (PS3) speech files */
if (!check_extensions(sf,"xvag,"))
goto fail;
if (!is_id32be(0x00,sf, "XVAG"))
goto fail;
/* endian flag (XVAGs of the same game can use BE or LE, usually when reusing from other platforms) */
xvag.big_endian = read_8bit(0x08,sf) & 0x01;

View File

@ -1,6 +1,7 @@
#ifndef _XWB_XSB_H_
#define _XWB_XSB_H_
#include "meta.h"
#include "../util/companion_files.h"
#define XSB_XACT1_0_MAX 5 /* Unreal Championship (Xbox) */
#define XSB_XACT1_1_MAX 8 /* Die Hard: Vendetta (Xbox) */

View File

@ -1,6 +1,8 @@
#include "streamfile.h"
#include "util.h"
#include "vgmstream.h"
#include "util/reader_sf.h"
#include "util/paths.h"
#include <string.h>
/* for dup/fdopen in some systems */
@ -8,15 +10,6 @@
#include <unistd.h>
#endif
//TODO: move
#ifndef DIR_SEPARATOR
#if defined (_WIN32) || defined (WIN32)
#define DIR_SEPARATOR '\\'
#else
#define DIR_SEPARATOR '/'
#endif
#endif
/* For (rarely needed) +2GB file support we use fseek64/ftell64. Those are usually available
* but may depend on compiler.
* - MSVC: +VS2008 should work
@ -1085,279 +1078,6 @@ STREAMFILE* reopen_streamfile(STREAMFILE* sf, size_t buffer_size) {
return sf->open(sf, pathname, buffer_size);
}
/* **************************************************** */
size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) {
int i;
off_t file_size = get_streamfile_size(sf);
int extra_bytes = 0; /* how many bytes over those put in the buffer were read */
if (p_line_ok) *p_line_ok = 0;
for (i = 0; i < buf_size-1 && offset+i < file_size; i++) {
char in_char = read_8bit(offset+i, sf);
/* check for end of line */
if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */
extra_bytes = 2;
if (p_line_ok) *p_line_ok = 1;
break;
}
else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */
extra_bytes = 1;
if (p_line_ok) *p_line_ok = 1;
break;
}
buf[i] = in_char;
}
buf[i] = '\0';
/* did we fill the buffer? */
if (i == buf_size) {
char in_char = read_8bit(offset+i, sf);
/* did the bytes we missed just happen to be the end of the line? */
if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */
extra_bytes = 2;
if (p_line_ok) *p_line_ok = 1;
}
else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */
extra_bytes = 1;
if (p_line_ok) *p_line_ok = 1;
}
}
/* did we hit the file end? */
if (offset+i == file_size) {
/* then we did in fact finish reading the last line */
if (p_line_ok) *p_line_ok = 1;
}
return i + extra_bytes;
}
size_t read_bom(STREAMFILE* sf) {
if (read_u16le(0x00, sf) == 0xFFFE ||
read_u16le(0x00, sf) == 0xFEFF) {
return 0x02;
}
if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) {
return 0x03;
}
return 0x00;
}
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
size_t pos;
for (pos = 0; pos < buf_size; pos++) {
uint8_t byte = read_u8(offset + pos, sf);
char c = (char)byte;
if (buf) buf[pos] = c;
if (c == '\0')
return pos;
if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */
if (buf) buf[pos] = '\0';
return buf_size;
}
/* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */
if (byte < 0x20 || byte > 0xF0)
goto fail;
}
fail:
if (buf) buf[0] = '\0';
return 0;
}
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) {
size_t pos, offpos;
uint16_t (*read_u16)(off_t,STREAMFILE*) = big_endian ? read_u16be : read_u16le;
for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) {
char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */
if (buf) buf[pos] = c;
if (c == '\0')
return pos;
if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */
if (buf) buf[pos] = '\0';
return buf_size;
}
if (c < 0x20 || (uint8_t)c > 0xA5)
goto fail;
}
fail:
if (buf) buf[0] = '\0';
return 0;
}
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
return read_string_utf16(buf, buf_size, offset, sf, 0);
}
size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
return read_string_utf16(buf, buf_size, offset, sf, 1);
}
/* ************************************************************************* */
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
char keyname[PATH_LIMIT];
char filename[PATH_LIMIT];
const char *path, *ext;
STREAMFILE* sf_key = NULL;
size_t keysize;
get_streamfile_name(sf, filename, sizeof(filename));
if (strlen(filename)+4 > sizeof(keyname)) goto fail;
/* try to open a keyfile using variations */
{
ext = strrchr(filename,'.');
if (ext!=NULL) ext = ext+1;
path = strrchr(filename, DIR_SEPARATOR);
if (path!=NULL) path = path+1;
/* "(name.ext)key" */
strcpy(keyname, filename);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(name.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
/* "(.ext)key" */
if (path) {
strcpy(keyname, filename);
keyname[path-filename] = '\0';
strcat(keyname, ".");
} else {
strcpy(keyname, ".");
}
if (ext) strcat(keyname, ext);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
goto fail;
}
found:
keysize = get_streamfile_size(sf_key);
if (keysize > buf_size) goto fail;
if (read_streamfile(buf, 0, keysize, sf_key) != keysize)
goto fail;
close_streamfile(sf_key);
return keysize;
fail:
close_streamfile(sf_key);
return 0;
}
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
return read_filemap_file_pos(sf, file_num, NULL);
}
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
char filename[PATH_LIMIT];
off_t txt_offset, file_size;
STREAMFILE* sf_map = NULL;
int file_pos = 0;
sf_map = open_streamfile_by_filename(sf, ".txtm");
if (!sf_map) goto fail;
get_streamfile_filename(sf, filename, sizeof(filename));
txt_offset = read_bom(sf_map);
file_size = get_streamfile_size(sf_map);
/* read lines and find target filename, format is (filename): value1, ... valueN */
while (txt_offset < file_size) {
char line[0x2000];
char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 };
int ok, bytes_read, line_ok;
bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok);
if (!line_ok) goto fail;
txt_offset += bytes_read;
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
/* better way? */
if (strcmp(line, "#@reset-pos") == 0) {
file_pos = 0;
}
continue;
}
if (strcmp(key, filename) == 0) {
int n;
char subval[PATH_LIMIT];
const char* current = val;
int i;
for (i = 0; i <= file_num; i++) {
if (current[0] == '\0')
goto fail;
ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n);
if (ok != 1)
goto fail;
if (i == file_num) {
if (p_pos) *p_pos = file_pos;
close_streamfile(sf_map);
return open_streamfile_by_filename(sf, subval);
}
current += n;
if (current[0] == ',')
current++;
}
}
file_pos++;
}
fail:
close_streamfile(sf_map);
return NULL;
}
void fix_dir_separators(char* filename) {
char c;
int i = 0;
while ((c = filename[i]) != '\0') {
if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\'))
filename[i] = DIR_SEPARATOR;
i++;
}
}
/* ************************************************************************* */
int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
@ -1392,73 +1112,6 @@ int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
/* ************************************************************************* */
/**
* Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size.
* Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF).
* The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt ").
* "full_chunk_size" signals chunk_size includes 4+4+data.
*
* returns 0 on failure
*/
static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) {
int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE;
int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE;
off_t offset, max_offset;
size_t file_size = get_streamfile_size(sf);
if (max_size == 0)
max_size = file_size;
offset = start_offset;
max_offset = offset + max_size;
if (max_offset > file_size)
max_offset = file_size;
/* read chunks */
while (offset < max_offset) {
uint32_t chunk_type = read_32bit_type(offset + 0x00,sf);
uint32_t chunk_size = read_32bit_size(offset + 0x04,sf);
if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF)
return 0;
if (chunk_type == chunk_id) {
if (out_chunk_offset) *out_chunk_offset = offset + 0x08;
if (out_chunk_size) *out_chunk_size = chunk_size;
return 1;
}
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
if (chunk_size == 0 && zero_size_end)
return 0;
offset += full_chunk_size ? chunk_size : 0x08 + chunk_size;
}
return 0;
}
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0);
}
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0);
}
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) {
return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end);
}
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0);
}
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0);
}
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 0);
}
/* ************************************************************************* */
/* copies name as-is (may include full path included) */
void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) {
sf->get_name(sf, buffer, size);

View File

@ -161,214 +161,12 @@ static inline size_t get_streamfile_size(STREAMFILE* sf) {
}
/* Sometimes you just need an int, and we're doing the buffering.
* Note, however, that if these fail to read they'll return -1,
* so that should not be a valid value or there should be some backup. */
static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitLE(buf);
}
static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitBE(buf);
}
static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitLE(buf);
}
static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitBE(buf);
}
static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitLE(buf);
}
static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[1];
if (read_streamfile(buf,offset,1,sf)!=1) return -1;
return buf[0];
}
/* alias of the above */
static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); }
static inline float read_f32be(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32be(buf);
}
static inline float read_f32le(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32le(buf);
}
#if 0
// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring:
// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle;
// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant).
// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants
// so may result on bloatness?
// (from godbolt tests, test more real cases)
/* collection of callbacks for quick access */
typedef struct sf_reader {
int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32
float (*read_f32)(off_t,STREAMFILE*);
/* ... */
} sf_reader;
static inline void sf_reader_init(sf_reader* r, int big_endian) {
memset(r, 0, sizeof(sf_reader));
if (big_endian) {
r->read_s32 = read_s32be;
r->read_f32 = read_f32be;
}
else {
r->read_s32 = read_s32le;
r->read_f32 = read_f32le;
}
}
/* sf_reader r;
* ...
* sf_reader_init(&r, big_endian);
* val = r.read_s32; //maybe r.s32?
*/
#endif
#if 0 //todo improve + test + simplify code (maybe not inline?)
static inline int read_s4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return get_nibble_signed(byte, 1);
}
static inline int read_u4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return (byte >> 4) & 0x0f;
}
static inline int read_s4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int read_u4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; }
static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; }
//align32, align16, clamp16, etc
#endif
/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */
static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32be(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32le(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u64be(offset, sf) == get_id64be(s);
}
//TODO: maybe move to streamfile.c
/* guess byte endianness from a given value, return true if big endian and false if little endian */
static inline int guess_endianness16bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x02];
if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */
return get_u16le(buf) > get_u16be(buf) ? 1 : 0;
}
static inline int guess_endianness32bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x04];
if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */
return get_u32le(buf) > get_u32be(buf) ? 1 : 0;
}
static inline size_t align_size_to_block(size_t value, size_t block_align) {
size_t extra_size = value % block_align;
if (extra_size == 0) return value;
return (value + block_align - extra_size);
}
/* various STREAMFILE helpers functions */
/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated
* and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length.
* p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */
size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok);
/* skip BOM if needed */
size_t read_bom(STREAMFILE* sf);
/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian);
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
/* Opens a file containing decryption keys and copies to buffer.
* Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames.
* returns size of key if found and copied */
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match
* then loads the associated companion file if one is found */
STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num);
STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos);
/* hack to allow relative paths in various OSs */
void fix_dir_separators(char* filename);
/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix").
* Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */
int check_extensions(STREAMFILE* sf, const char* cmp_exts);
/* chunk-style file helpers */
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end);
/* find a RIFF-style chunk (with chunk_size not including id and size) */
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian);
/* filename helpers */
void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size);
void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size);

View File

@ -1,11 +1,12 @@
/*
* streamtypes.h - widely used type definitions
*/
#ifndef _STREAMTYPES_H
#define _STREAMTYPES_H
#include <stddef.h> //size_t
#include <stdbool.h> //bool
#ifdef _MSC_VER
/* Common versions:
* - 1500: VS2008
@ -15,25 +16,24 @@
* - 1900: VS2015
* - 1920: VS2019 */
#if (_MSC_VER >= 1600)
#if (_MSC_VER >= 1600)
#include <stdint.h>
#else
#include <pstdint.h>
#endif
#include <stdint.h>
#if (_MSC_VER < 1800) && !defined(__cplusplus)
#define inline __inline
#endif
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#if (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
#else
#include <pstdint.h>
#endif
#if (_MSC_VER < 1800) && !defined(__cplusplus)
#define inline __inline
#endif
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#if (_MSC_VER < 1900)
#define snprintf _snprintf
#endif
#else
#include <stdint.h>
#endif /* _MSC_VER */

View File

@ -42,3 +42,12 @@ void concatn(int length, char * dst, const char * src) {
dst[i]=src[j];
dst[i]='\0';
}
size_t align_size_to_block(size_t value, size_t block_align) {
if (!block_align)
return 0;
size_t extra_size = value % block_align;
if (extra_size == 0) return value;
return (value + block_align - extra_size);
}

View File

@ -51,4 +51,6 @@ const char* filename_extension(const char* pathname);
void concatn(int length, char * dst, const char * src);
size_t align_size_to_block(size_t value, size_t block_align);
#endif

View File

@ -1,8 +1,11 @@
#ifndef _VORBIS_BITREADER_H
#define _VORBIS_BITREADER_H
#ifndef _BITSTREAM_LSB_H
#define _BITSTREAM_LSB_H
/* Simple bitreader for Vorbis' bit format.
* Kept in .h since it's slightly faster (compiler can optimize statics better) */
#include "../streamtypes.h"
/* Simple bitreader for Vorbis' bit style, in 'least significant byte' (LSB) format.
* Example: 0x12345678 is read as 12,34,56,78 (continuous).
* Kept in .h since it's slightly faster (compiler can optimize statics better using default compile flags). */
typedef struct {
@ -12,7 +15,7 @@ typedef struct {
} bitstream_t;
/* convenience util */
static void init_bitstream(bitstream_t* b, uint8_t* buf, size_t bufsize) {
static inline void bl_setup(bitstream_t* b, uint8_t* buf, size_t bufsize) {
b->buf = buf;
b->bufsize = bufsize;
b->b_off = 0;
@ -29,7 +32,7 @@ static const uint32_t MASK_TABLE[33] = {
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int rv_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) {
static inline int bl_get(bitstream_t* ib, uint32_t bits, uint32_t* value) {
uint32_t shift, mask, pos, val;
if (bits > 32 || ib->b_off + bits > ib->bufsize * 8)
@ -59,15 +62,14 @@ static int rv_bits(bitstream_t* ib, uint32_t bits, uint32_t* value) {
return 1;
fail:
VGM_LOG_ONCE("BITREADER: read fail\n");
//VGM_LOG_ONCE("BITREADER: read fail\n");
*value = 0;
return 0;
}
#ifndef BITSTREAM_READ_ONLY
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
static int wv_bits(bitstream_t* ob, uint32_t bits, uint32_t value) {
static inline int bl_put(bitstream_t* ob, uint32_t bits, uint32_t value) {
uint32_t shift, mask, pos;
if (bits > 32 || ob->b_off + bits > ob->bufsize*8)
@ -95,9 +97,8 @@ static int wv_bits(bitstream_t* ob, uint32_t bits, uint32_t value) {
ob->b_off += bits;
return 1;
fail:
VGM_LOG_ONCE("BITREADER: write fail\n");
//VGM_LOG_ONCE("BITREADER: write fail\n");
return 0;
}
#endif
#endif

View File

@ -1,10 +1,11 @@
#ifndef _BITSTREAM_MSB_H
#define _BITSTREAM_MSB_H
#include <stdint.h>
#include "../streamtypes.h"
/* Simple bitreader for MPEG/standard bit format.
* Kept in .h since it's slightly faster (compiler can optimize better) */
/* Simple bitreader for MPEG/standard bit style, in 'most significant byte' (MSB) format.
* Example: 0x12345678 is read as 78,56,34,12 then each byte's bits.
* Kept in .h since it's slightly faster (compiler can optimize statics better using default compile flags). */
typedef struct {
uint8_t* buf; /* buffer to read/write */
@ -70,6 +71,7 @@ static inline int bm_get(bitstream_t* ib, uint32_t bits, uint32_t* value) {
pos = ib->b_off / 8; /* byte offset */
shift = ib->b_off % 8; /* bit sub-offset */
#if 1 //naive approach
val = 0;
for (i = 0; i < bits; i++) {
bit_buf = (1U << (8-1-shift)) & 0xFF; /* bit check for buf */
@ -84,6 +86,35 @@ static inline int bm_get(bitstream_t* ib, uint32_t bits, uint32_t* value) {
pos++;
}
}
#else //has bugs
pos = ib->b_off / 8; /* byte offset */
shift = ib->b_off % 8; /* bit sub-offset */
uint32_t mask = MASK_TABLE[bits]; /* to remove upper in highest byte */
int left = 0;
if (bits == 0)
val = 0;
else
val = ib->buf[pos+0];
left = 8 - (bits + shift);
if (bits + shift > 8) {
val = (val << 8u) | ib->buf[pos+1];
left = 16 - (bits + shift);
if (bits + shift > 16) {
val = (val << 8u) | ib->buf[pos+2];
left = 32 - (bits + shift);
if (bits + shift > 24) {
val = (val << 8u) | ib->buf[pos+3];
left = 32 - (bits + shift);
if (bits + shift > 32) {
val = (val << 8u) | ib->buf[pos+4]; /* upper bits are lost (shifting over 32) */ TO-DO
left = 40 - (bits + shift);
}
}
}
}
val = ((val >> left) & mask);
#endif
*value = val;
ib->b_off += bits;

View File

@ -1,5 +1,5 @@
#include "chunks.h"
//#include "log.h"
#include "reader_sf.h"
int next_chunk(chunk_t* chunk, STREAMFILE* sf) {
@ -33,3 +33,71 @@ int next_chunk(chunk_t* chunk, STREAMFILE* sf) {
/* more chunks remain */
return 1;
}
/* ************************************************************************* */
/**
* Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size.
* Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF).
* The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt ").
* "full_chunk_size" signals chunk_size includes 4+4+data.
*
* returns 0 on failure
*/
static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) {
int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE;
int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE;
off_t offset, max_offset;
size_t file_size = get_streamfile_size(sf);
if (max_size == 0)
max_size = file_size;
offset = start_offset;
max_offset = offset + max_size;
if (max_offset > file_size)
max_offset = file_size;
/* read chunks */
while (offset < max_offset) {
uint32_t chunk_type = read_32bit_type(offset + 0x00,sf);
uint32_t chunk_size = read_32bit_size(offset + 0x04,sf);
if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF)
return 0;
if (chunk_type == chunk_id) {
if (out_chunk_offset) *out_chunk_offset = offset + 0x08;
if (out_chunk_size) *out_chunk_size = chunk_size;
return 1;
}
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
if (chunk_size == 0 && zero_size_end)
return 0;
offset += full_chunk_size ? chunk_size : 0x08 + chunk_size;
}
return 0;
}
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0);
}
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0);
}
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) {
return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end);
}
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0);
}
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0);
}
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) {
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 0);
}

View File

@ -26,4 +26,16 @@ enum {
};
#endif
/* chunk-style file helpers (the above is more performant, this is mainly for quick checks) */
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end);
/* find a RIFF-style chunk (with chunk_size not including id and size) */
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian);
#endif

149
src/util/companion_files.c Normal file
View File

@ -0,0 +1,149 @@
#include "companion_files.h"
#include "paths.h"
#include "../vgmstream.h"
#include "../util/reader_text.h"
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
char keyname[PATH_LIMIT];
char filename[PATH_LIMIT];
const char *path, *ext;
STREAMFILE* sf_key = NULL;
size_t keysize;
get_streamfile_name(sf, filename, sizeof(filename));
if (strlen(filename)+4 > sizeof(keyname)) goto fail;
/* try to open a keyfile using variations */
{
ext = strrchr(filename,'.');
if (ext!=NULL) ext = ext+1;
path = strrchr(filename, DIR_SEPARATOR);
if (path!=NULL) path = path+1;
/* "(name.ext)key" */
strcpy(keyname, filename);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(name.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
/* "(.ext)key" */
if (path) {
strcpy(keyname, filename);
keyname[path-filename] = '\0';
strcat(keyname, ".");
} else {
strcpy(keyname, ".");
}
if (ext) strcat(keyname, ext);
strcat(keyname, "key");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
/* "(.ext)KEY" */
/*
strcpy(keyname+strlen(keyname)-3,"KEY");
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (sf_key) goto found;
*/
goto fail;
}
found:
keysize = get_streamfile_size(sf_key);
if (keysize > buf_size) goto fail;
if (read_streamfile(buf, 0, keysize, sf_key) != keysize)
goto fail;
close_streamfile(sf_key);
return keysize;
fail:
close_streamfile(sf_key);
return 0;
}
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
return read_filemap_file_pos(sf, file_num, NULL);
}
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
char filename[PATH_LIMIT];
off_t txt_offset, file_size;
STREAMFILE* sf_map = NULL;
int file_pos = 0;
sf_map = open_streamfile_by_filename(sf, ".txtm");
if (!sf_map) goto fail;
get_streamfile_filename(sf, filename, sizeof(filename));
txt_offset = read_bom(sf_map);
file_size = get_streamfile_size(sf_map);
/* read lines and find target filename, format is (filename): value1, ... valueN */
while (txt_offset < file_size) {
char line[0x2000];
char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 };
int ok, bytes_read, line_ok;
bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok);
if (!line_ok) goto fail;
txt_offset += bytes_read;
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
/* better way? */
if (strcmp(line, "#@reset-pos") == 0) {
file_pos = 0;
}
continue;
}
if (strcmp(key, filename) == 0) {
int n;
char subval[PATH_LIMIT];
const char* current = val;
int i;
for (i = 0; i <= file_num; i++) {
if (current[0] == '\0')
goto fail;
ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n);
if (ok != 1)
goto fail;
if (i == file_num) {
if (p_pos) *p_pos = file_pos;
close_streamfile(sf_map);
return open_streamfile_by_filename(sf, subval);
}
current += n;
if (current[0] == ',')
current++;
}
}
file_pos++;
}
fail:
close_streamfile(sf_map);
return NULL;
}

View File

@ -0,0 +1,16 @@
#ifndef _COMPANION_FILES_H
#define _COMPANION_FILES_H
#include "../streamfile.h"
/* Opens a file containing decryption keys and copies to buffer.
* Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames.
* returns size of key if found and copied */
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match
* then loads the associated companion file if one is found */
STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num);
STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos);
#endif

View File

@ -1,5 +1,6 @@
#include "cri_utf.h"
#include "log.h"
#include "reader_sf.h"
#define UTF_MAX_SCHEMA_SIZE 0x8000 /* arbitrary max */
#define COLUMN_BITMASK_FLAG 0xf0

View File

@ -2,6 +2,7 @@
#define _UTIL_ENDIAN_H
#include "../streamfile.h"
#include "reader_get.h"
typedef uint32_t (*read_u32_t)(off_t, STREAMFILE*);
typedef int32_t (*read_s32_t)(off_t, STREAMFILE*);
@ -11,8 +12,17 @@ typedef float (*read_f32_t)(off_t, STREAMFILE*);
typedef int16_t (*get_s16_t)(const uint8_t*);
//todo move here
#define guess_endian32 guess_endianness32bit
#define guess_endian16 guess_endianness16bit
/* guess byte endianness from a given value, return true if big endian and false if little endian */
static inline int guess_endian16(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x02];
if (read_streamfile(buf, offset, 0x02, sf) != 0x02) return -1; /* ? */
return get_u16le(buf) > get_u16be(buf) ? 1 : 0;
}
static inline int guess_endian32(off_t offset, STREAMFILE* sf) {
uint8_t buf[0x04];
if (read_streamfile(buf, offset, 0x04, sf) != 0x04) return -1; /* ? */
return get_u32le(buf) > get_u32be(buf) ? 1 : 0;
}
#endif

11
src/util/paths.c Normal file
View File

@ -0,0 +1,11 @@
#include "paths.h"
void fix_dir_separators(char* filename) {
char c;
int i = 0;
while ((c = filename[i]) != '\0') {
if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\'))
filename[i] = DIR_SEPARATOR;
i++;
}
}

17
src/util/paths.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef _PATHS_H
#define _PATHS_H
#ifndef DIR_SEPARATOR
#if defined (_WIN32) || defined (WIN32)
#define DIR_SEPARATOR '\\'
#else
#define DIR_SEPARATOR '/'
#endif
#endif
/* hack to allow relative paths in various OSs */
void fix_dir_separators(char* filename);
//const char* filename_extension(const char* pathname);
#endif

149
src/util/reader.c Normal file
View File

@ -0,0 +1,149 @@
#include "reader_put.h"
#include "reader_text.h"
#include "reader_sf.h"
#include "endianness.h"
void put_8bit(uint8_t* buf, int8_t i) {
buf[0] = i;
}
void put_16bitLE(uint8_t* buf, int16_t i) {
buf[0] = (i & 0xFF);
buf[1] = i >> 8;
}
void put_32bitLE(uint8_t* buf, int32_t i) {
buf[0] = (uint8_t)(i & 0xFF);
buf[1] = (uint8_t)((i >> 8) & 0xFF);
buf[2] = (uint8_t)((i >> 16) & 0xFF);
buf[3] = (uint8_t)((i >> 24) & 0xFF);
}
void put_16bitBE(uint8_t* buf, int16_t i) {
buf[0] = i >> 8;
buf[1] = (i & 0xFF);
}
void put_32bitBE(uint8_t* buf, int32_t i) {
buf[0] = (uint8_t)((i >> 24) & 0xFF);
buf[1] = (uint8_t)((i >> 16) & 0xFF);
buf[2] = (uint8_t)((i >> 8) & 0xFF);
buf[3] = (uint8_t)(i & 0xFF);
}
/* **************************************************** */
size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok) {
int i;
off_t file_size = get_streamfile_size(sf);
int extra_bytes = 0; /* how many bytes over those put in the buffer were read */
if (p_line_ok) *p_line_ok = 0;
for (i = 0; i < buf_size-1 && offset+i < file_size; i++) {
char in_char = read_8bit(offset+i, sf);
/* check for end of line */
if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */
extra_bytes = 2;
if (p_line_ok) *p_line_ok = 1;
break;
}
else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */
extra_bytes = 1;
if (p_line_ok) *p_line_ok = 1;
break;
}
buf[i] = in_char;
}
buf[i] = '\0';
/* did we fill the buffer? */
if (i == buf_size) {
char in_char = read_8bit(offset+i, sf);
/* did the bytes we missed just happen to be the end of the line? */
if (in_char == 0x0d && read_8bit(offset+i+1, sf) == 0x0a) { /* CRLF */
extra_bytes = 2;
if (p_line_ok) *p_line_ok = 1;
}
else if (in_char == 0x0d || in_char == 0x0a) { /* CR or LF */
extra_bytes = 1;
if (p_line_ok) *p_line_ok = 1;
}
}
/* did we hit the file end? */
if (offset+i == file_size) {
/* then we did in fact finish reading the last line */
if (p_line_ok) *p_line_ok = 1;
}
return i + extra_bytes;
}
size_t read_bom(STREAMFILE* sf) {
if (read_u16le(0x00, sf) == 0xFFFE ||
read_u16le(0x00, sf) == 0xFEFF) {
return 0x02;
}
if ((read_u32be(0x00, sf) & 0xFFFFFF00) == 0xEFBBBF00) {
return 0x03;
}
return 0x00;
}
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
size_t pos;
for (pos = 0; pos < buf_size; pos++) {
uint8_t byte = read_u8(offset + pos, sf);
char c = (char)byte;
if (buf) buf[pos] = c;
if (c == '\0')
return pos;
if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */
if (buf) buf[pos] = '\0';
return buf_size;
}
/* UTF-8 only goes to 0x7F, but allow a bunch of Windows-1252 codes that some games use */
if (byte < 0x20 || byte > 0xF0)
goto fail;
}
fail:
if (buf) buf[0] = '\0';
return 0;
}
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian) {
size_t pos, offpos;
read_u16_t read_u16 = big_endian ? read_u16be : read_u16le;
for (pos = 0, offpos = 0; pos < buf_size; pos++, offpos += 2) {
char c = read_u16(offset + offpos, sf) & 0xFF; /* lower byte for now */
if (buf) buf[pos] = c;
if (c == '\0')
return pos;
if (pos+1 == buf_size) { /* null at maxsize and don't validate (expected to be garbage) */
if (buf) buf[pos] = '\0';
return buf_size;
}
if (c < 0x20 || (uint8_t)c > 0xA5)
goto fail;
}
fail:
if (buf) buf[0] = '\0';
return 0;
}
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
return read_string_utf16(buf, buf_size, offset, sf, 0);
}
size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf) {
return read_string_utf16(buf, buf_size, offset, sf, 1);
}

View File

@ -1,29 +0,0 @@
#include "reader_put.h"
void put_8bit(uint8_t * buf, int8_t i) {
buf[0] = i;
}
void put_16bitLE(uint8_t * buf, int16_t i) {
buf[0] = (i & 0xFF);
buf[1] = i >> 8;
}
void put_32bitLE(uint8_t * buf, int32_t i) {
buf[0] = (uint8_t)(i & 0xFF);
buf[1] = (uint8_t)((i >> 8) & 0xFF);
buf[2] = (uint8_t)((i >> 16) & 0xFF);
buf[3] = (uint8_t)((i >> 24) & 0xFF);
}
void put_16bitBE(uint8_t * buf, int16_t i) {
buf[0] = i >> 8;
buf[1] = (i & 0xFF);
}
void put_32bitBE(uint8_t * buf, int32_t i) {
buf[0] = (uint8_t)((i >> 24) & 0xFF);
buf[1] = (uint8_t)((i >> 16) & 0xFF);
buf[2] = (uint8_t)((i >> 8) & 0xFF);
buf[3] = (uint8_t)(i & 0xFF);
}

149
src/util/reader_sf.h Normal file
View File

@ -0,0 +1,149 @@
#ifndef _READER_SF_H
#define _READER_SF_H
#include "../streamfile.h"
/* Sometimes you just need an int, and we're doing the buffering.
* Note, however, that if these fail to read they'll return -1,
* so that should not be a valid value or there should be some backup. */
static inline int16_t read_16bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitLE(buf);
}
static inline int16_t read_16bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[2];
if (read_streamfile(buf,offset,2,sf)!=2) return -1;
return get_16bitBE(buf);
}
static inline int32_t read_32bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitLE(buf);
}
static inline int32_t read_32bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf,offset,4,sf)!=4) return -1;
return get_32bitBE(buf);
}
static inline int64_t read_64bitLE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitLE(buf);
}
static inline int64_t read_64bitBE(off_t offset, STREAMFILE* sf) {
uint8_t buf[8];
if (read_streamfile(buf,offset,8,sf)!=8) return -1;
return get_64bitBE(buf);
}
static inline int8_t read_8bit(off_t offset, STREAMFILE* sf) {
uint8_t buf[1];
if (read_streamfile(buf,offset,1,sf)!=1) return -1;
return buf[0];
}
/* alias of the above */
static inline int8_t read_s8 (off_t offset, STREAMFILE* sf) { return read_8bit(offset, sf); }
static inline uint8_t read_u8 (off_t offset, STREAMFILE* sf) { return (uint8_t) read_8bit(offset, sf); }
static inline int16_t read_s16le(off_t offset, STREAMFILE* sf) { return read_16bitLE(offset, sf); }
static inline uint16_t read_u16le(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitLE(offset, sf); }
static inline int16_t read_s16be(off_t offset, STREAMFILE* sf) { return read_16bitBE(offset, sf); }
static inline uint16_t read_u16be(off_t offset, STREAMFILE* sf) { return (uint16_t)read_16bitBE(offset, sf); }
static inline int32_t read_s32le(off_t offset, STREAMFILE* sf) { return read_32bitLE(offset, sf); }
static inline uint32_t read_u32le(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitLE(offset, sf); }
static inline int32_t read_s32be(off_t offset, STREAMFILE* sf) { return read_32bitBE(offset, sf); }
static inline uint32_t read_u32be(off_t offset, STREAMFILE* sf) { return (uint32_t)read_32bitBE(offset, sf); }
static inline int64_t read_s64be(off_t offset, STREAMFILE* sf) { return read_64bitBE(offset, sf); }
static inline uint64_t read_u64be(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitBE(offset, sf); }
static inline int64_t read_s64le(off_t offset, STREAMFILE* sf) { return read_64bitLE(offset, sf); }
static inline uint64_t read_u64le(off_t offset, STREAMFILE* sf) { return (uint64_t)read_64bitLE(offset, sf); }
static inline float read_f32be(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32be(buf);
}
static inline float read_f32le(off_t offset, STREAMFILE* sf) {
uint8_t buf[4];
if (read_streamfile(buf, offset, sizeof(buf), sf) != sizeof(buf))
return -1;
return get_f32le(buf);
}
#if 0
// on GCC, this reader will be correctly optimized out (as long as it's static/inline), would be same as declaring:
// uintXX_t (*read_uXX)(off_t,uint8_t*) = be ? get_uXXbe : get_uXXle;
// only for the functions actually used in code, and inlined if possible (like big_endian param being a constant).
// on MSVC seems all read_X in sf_reader are compiled and included in the translation unit, plus ignores constants
// so may result on bloatness?
// (from godbolt tests, test more real cases)
/* collection of callbacks for quick access */
typedef struct sf_reader {
int32_t (*read_s32)(off_t,STREAMFILE*); //maybe r.s32
float (*read_f32)(off_t,STREAMFILE*);
/* ... */
} sf_reader;
static inline void sf_reader_init(sf_reader* r, int big_endian) {
memset(r, 0, sizeof(sf_reader));
if (big_endian) {
r->read_s32 = read_s32be;
r->read_f32 = read_f32be;
}
else {
r->read_s32 = read_s32le;
r->read_f32 = read_f32le;
}
}
/* sf_reader r;
* ...
* sf_reader_init(&r, big_endian);
* val = r.read_s32; //maybe r.s32?
*/
#endif
#if 0 //todo improve + test + simplify code (maybe not inline?)
static inline int read_s4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return get_nibble_signed(byte, 1);
}
static inline int read_u4h(off_t offset, STREAMFILE* sf) {
uint8_t byte = read_u8(offset, streamfile);
return (byte >> 4) & 0x0f;
}
static inline int read_s4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int read_u4l(off_t offset, STREAMFILE* sf) {
...
}
static inline int max_s32(int32_t a, int32_t b) { return a > b ? a : b; }
static inline int min_s32(int32_t a, int32_t b) { return a < b ? a : b; }
//align32, align16, clamp16, etc
#endif
/* fastest to compare would be read_u32x == (uint32), but should be pre-optimized (see get_id32x) */
static inline /*const*/ int is_id32be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32be(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id32le(off_t offset, STREAMFILE* sf, const char* s) {
return read_u32le(offset, sf) == get_id32be(s);
}
static inline /*const*/ int is_id64be(off_t offset, STREAMFILE* sf, const char* s) {
return read_u64be(offset, sf) == get_id64be(s);
}
#endif

21
src/util/reader_text.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef _READER_TEXT_H
#define _READER_TEXT_H
#include "../streamfile.h"
/* Read into dst a line delimited by CRLF (Windows) / LF (Unux) / CR (Mac) / EOF, null-terminated
* and without line feeds. Returns bytes read (including CR/LF), *not* the same as string length.
* p_line_ok is set to 1 if the complete line was read; pass NULL to ignore. */
size_t read_line(char* buf, int buf_size, off_t offset, STREAMFILE* sf, int* p_line_ok);
/* skip BOM if needed */
size_t read_bom(STREAMFILE* sf);
/* reads a c-string (ANSI only), up to bufsize or NULL, returning size. buf is optional (works as get_string_size). */
size_t read_string(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
/* reads a UTF16 string... but actually only as ANSI (discards the upper byte) */
size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf, int big_endian);
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
#endif

View File

@ -9,15 +9,16 @@
#include "meta/meta.h"
#include "layout/layout.h"
#include "coding/coding.h"
#include "decode.h"
#include "render.h"
#include "mixing.h"
#include "base/decode.h"
#include "base/render.h"
#include "base/mixing.h"
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM* (*init_vgmstream_function)(STREAMFILE*));
typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*);
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function);
/* list of metadata parser functions that will recognize files, used on init */
VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
init_vgmstream_t init_vgmstream_functions[] = {
init_vgmstream_adx,
init_vgmstream_brstm,
init_vgmstream_brwav,
@ -563,25 +564,25 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
#endif
};
#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
static const int init_vgmstream_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions);
/*****************************************************************************/
/* INIT/META */
/*****************************************************************************/
#define LOCAL_ARRAY_LENGTH(array) (sizeof(array) / sizeof(array[0]))
/* internal version with all parameters */
static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
int i, fcns_count;
if (!sf)
return NULL;
fcns_count = LOCAL_ARRAY_LENGTH(init_vgmstream_functions);
/* try a series of formats, see which works */
for (i = 0; i < fcns_count; i++) {
for (int i = 0; i < init_vgmstream_count; i++) {
init_vgmstream_t init_vgmstream_function = init_vgmstream_functions[i];
/* call init function and see if valid VGMSTREAM was returned */
VGMSTREAM* vgmstream = (init_vgmstream_functions[i])(sf);
VGMSTREAM* vgmstream = init_vgmstream_function(sf);
if (!vgmstream)
continue;
@ -614,7 +615,7 @@ static VGMSTREAM* init_vgmstream_internal(STREAMFILE* sf) {
/* test if candidate for dual stereo */
if (vgmstream->channels == 1 && vgmstream->allow_dual_stereo == 1) {
try_dual_file_stereo(vgmstream, sf, init_vgmstream_functions[i]);
try_dual_file_stereo(vgmstream, sf, init_vgmstream_function);
}
/* clean as loops are readable metadata but loop fields may contain garbage
@ -714,9 +715,9 @@ void reset_vgmstream(VGMSTREAM* vgmstream) {
* Otherwise hit_loop will be 0 and it will be copied over anyway when we
* really hit the loop start. */
reset_codec(vgmstream);
decode_reset(vgmstream);
reset_layout(vgmstream);
render_reset(vgmstream);
/* note that this does not reset the constituent STREAMFILES
* (vgmstream->ch[N].streamfiles' internal state, like internal offset, though shouldn't matter) */
@ -737,7 +738,7 @@ VGMSTREAM* allocate_vgmstream(int channel_count, int loop_flag) {
* - ch: config+state per channel, also modified by those
* - start_vgmstream: vgmstream clone copied on init_vgmstream and restored on reset_vgmstream
* - start_ch: ch clone copied on init_vgmstream and restored on reset_vgmstream
* - loop_ch: ch clone copied on loop start and restored on loop end (vgmstream_do_loop)
* - loop_ch: ch clone copied on loop start and restored on loop end (decode_do_loop)
* - codec/layout_data: custom state for complex codecs or layouts, handled externally
*
* Here we only create the basic structs to be filled, and only after init_vgmstream it
@ -799,10 +800,10 @@ void close_vgmstream(VGMSTREAM* vgmstream) {
if (!vgmstream)
return;
free_codec(vgmstream);
decode_free(vgmstream);
vgmstream->codec_data = NULL;
free_layout(vgmstream);
render_free(vgmstream);
vgmstream->layout_data = NULL;
@ -915,7 +916,7 @@ void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target) {
/* See if there is a second file which may be the second channel, given an already opened mono vgmstream.
* If a suitable file is found, open it and change opened_vgmstream to a stereo vgmstream. */
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, VGMSTREAM*(*init_vgmstream_function)(STREAMFILE*)) {
static void try_dual_file_stereo(VGMSTREAM* opened_vgmstream, STREAMFILE* sf, init_vgmstream_t init_vgmstream_function) {
/* filename search pairs for dual file stereo */
static const char* const dfs_pairs[][2] = {
{"L","R"}, /* most common in .dsp and .vag */

View File

@ -22,7 +22,7 @@
#include <math.h>
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
#include "sdk/in2.h"
#include "sdk/wa_ipc.h"
#include "sdk/ipc_pe.h"

View File

@ -13,7 +13,7 @@
#include "xmpin.h"
#include "../src/vgmstream.h"
#include "../src/plugins.h"
#include "../src/api.h"
#include "../version.h"