Updated VGMStream to r1831-27-ge6883cbd
Signed-off-by: Christopher Snowhill <kode54@gmail.com>main
parent
dfa5f41984
commit
d2adf39e04
|
@ -57,15 +57,15 @@
|
|||
/** State of the decoder. One decoder state is needed for each stream.
|
||||
It is initialised once at the beginning of the stream. Do *not*
|
||||
re-initialise the state for every frame */
|
||||
typedef struct CELT0061Decoder CELT0061Decoder;
|
||||
typedef struct CELT0110Decoder CELT0110Decoder;
|
||||
typedef struct CELTDecoder0061 CELTDecoder0061;
|
||||
typedef struct CELTDecoder CELTDecoder0110;
|
||||
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialised
|
||||
with exactly the same mode, otherwise the quality will be very
|
||||
bad */
|
||||
typedef struct CELT0061Mode CELT0061Mode;
|
||||
typedef struct CELT0110Mode CELT0110Mode;
|
||||
typedef struct CELTMode0061 CELTMode0061;
|
||||
typedef struct CELTMode0110 CELTMode0110;
|
||||
|
||||
|
||||
/* Mode calls */
|
||||
|
@ -80,19 +80,19 @@ typedef struct CELT0110Mode CELT0110Mode;
|
|||
@param error Returned error code (if NULL, no error will be returned)
|
||||
@return A newly created mode
|
||||
*/
|
||||
EXPORT CELT0061Mode *celt_0061_mode_create(celt_int32 Fs, int channels, int frame_size, int *error);
|
||||
EXPORT CELT0110Mode *celt_0110_mode_create(celt_int32 Fs, int frame_size, int *error);
|
||||
/*EXPORT*/ CELTMode0061 *celt_mode_create_0061(celt_int32 Fs, int channels, int frame_size, int *error);
|
||||
/*EXPORT*/ CELTMode0110 *celt_mode_create_0110(celt_int32 Fs, int frame_size, int *error);
|
||||
|
||||
/** Destroys a mode struct. Only call this after all encoders and
|
||||
decoders using this mode are destroyed as well.
|
||||
@param mode Mode to be destroyed
|
||||
*/
|
||||
EXPORT void celt_0061_mode_destroy(CELT0061Mode *mode);
|
||||
EXPORT void celt_0110_mode_destroy(CELT0110Mode *mode);
|
||||
/*EXPORT*/ void celt_mode_destroy_0061(CELTMode0061 *mode);
|
||||
/*EXPORT*/ void celt_mode_destroy_0110(CELTMode0110 *mode);
|
||||
|
||||
/** Query information from a mode */
|
||||
EXPORT int celt_0061_mode_info(const CELT0061Mode *mode, int request, celt_int32 *value);
|
||||
EXPORT int celt_0110_mode_info(const CELT0110Mode *mode, int request, celt_int32 *value);
|
||||
/*EXPORT*/ int celt_mode_info_0061(const CELTMode0061 *mode, int request, celt_int32 *value);
|
||||
/*EXPORT*/ int celt_mode_info_0110(const CELTMode0110 *mode, int request, celt_int32 *value);
|
||||
|
||||
|
||||
/* Decoder stuff */
|
||||
|
@ -105,14 +105,14 @@ EXPORT int celt_0110_mode_info(const CELT0110Mode *mode, int request, celt_int32
|
|||
@param error Returns an error code
|
||||
@return Newly created decoder state.
|
||||
*/
|
||||
EXPORT CELT0061Decoder *celt_0061_decoder_create(const CELT0061Mode *mode);
|
||||
EXPORT CELT0110Decoder *celt_0110_decoder_create_custom(const CELT0110Mode *mode, int channels, int *error);
|
||||
/*EXPORT*/ CELTDecoder0061 *celt_decoder_create_0061(const CELTMode0061 *mode);
|
||||
/*EXPORT*/ CELTDecoder0110 *celt_decoder_create_custom_0110(const CELTMode0110 *mode, int channels, int *error);
|
||||
|
||||
/** Destroys a a decoder state.
|
||||
@param st Decoder state to be destroyed
|
||||
*/
|
||||
EXPORT void celt_0061_decoder_destroy(CELT0061Decoder *st);
|
||||
EXPORT void celt_0110_decoder_destroy(CELT0110Decoder *st);
|
||||
/*EXPORT*/ void celt_decoder_destroy_0061(CELTDecoder0061 *st);
|
||||
/*EXPORT*/ void celt_decoder_destroy_0110(CELTDecoder0110 *st);
|
||||
|
||||
/** Decodes a frame of audio.
|
||||
@param st Decoder state
|
||||
|
@ -123,8 +123,8 @@ EXPORT void celt_0110_decoder_destroy(CELT0110Decoder *st);
|
|||
returned here in 16-bit PCM format (native endian).
|
||||
@return Error code.
|
||||
*/
|
||||
EXPORT int celt_0061_decode(CELT0061Decoder *st, const unsigned char *data, int len, celt_int16 *pcm);
|
||||
EXPORT int celt_0110_decode(CELT0110Decoder *st, const unsigned char *data, int len, celt_int16 *pcm, int frame_size);
|
||||
/*EXPORT*/ int celt_decode_0061(CELTDecoder0061 *st, const unsigned char *data, int len, celt_int16 *pcm);
|
||||
/*EXPORT*/ int celt_decode_0110(CELTDecoder0110 *st, const unsigned char *data, int len, celt_int16 *pcm, int frame_size);
|
||||
|
||||
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
/* Copyright (c) 2003-2008 Timothy B. Terriberry
|
||||
Copyright (c) 2008 Xiph.Org Foundation */
|
||||
/*
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*Some common macros for potential platform-specific optimization.*/
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_ecintrin_H)
|
||||
# define _ecintrin_H (1)
|
||||
|
||||
/*Some specific platforms may have optimized intrinsic or inline assembly
|
||||
versions of these functions which can substantially improve performance.
|
||||
We define macros for them to allow easy incorporation of these non-ANSI
|
||||
features.*/
|
||||
|
||||
/*Note that we do not provide a macro for abs(), because it is provided as a
|
||||
library function, which we assume is translated into an intrinsic to avoid
|
||||
the function call overhead and then implemented in the smartest way for the
|
||||
target platform.
|
||||
With modern gcc (4.x), this is true: it uses cmov instructions if the
|
||||
architecture supports it and branchless bit-twiddling if it does not (the
|
||||
speed difference between the two approaches is not measurable).
|
||||
Interestingly, the bit-twiddling method was patented in 2000 (US 6,073,150)
|
||||
by Sun Microsystems, despite prior art dating back to at least 1996:
|
||||
http://web.archive.org/web/19961201174141/www.x86.org/ftp/articles/pentopt/PENTOPT.TXT
|
||||
On gcc 3.x, however, our assumption is not true, as abs() is translated to a
|
||||
conditional jump, which is horrible on deeply piplined architectures (e.g.,
|
||||
all consumer architectures for the past decade or more) when the sign cannot
|
||||
be reliably predicted.*/
|
||||
|
||||
/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
|
||||
given an appropriate architecture, but the branchless bit-twiddling versions
|
||||
are just as fast, and do not require any special target architecture.
|
||||
Earlier gcc versions (3.x) compiled both code to the same assembly
|
||||
instructions, because of the way they represented ((_b)>(_a)) internally.*/
|
||||
#define EC_MAXI(_a,_b) ((_a)-((_a)-(_b)&-((_b)>(_a))))
|
||||
#define EC_MINI(_a,_b) ((_a)+((_b)-(_a)&-((_b)<(_a))))
|
||||
/*This has a chance of compiling branchless, and is just as fast as the
|
||||
bit-twiddling method, which is slightly less portable, since it relies on a
|
||||
sign-extended rightshift, which is not guaranteed by ANSI (but present on
|
||||
every relevant platform).*/
|
||||
#define EC_SIGNI(_a) (((_a)>0)-((_a)<0))
|
||||
/*Slightly more portable than relying on a sign-extended right-shift (which is
|
||||
not guaranteed by ANSI), and just as fast, since gcc (3.x and 4.x both)
|
||||
compile it into the right-shift anyway.*/
|
||||
#define EC_SIGNMASK(_a) (-((_a)<0))
|
||||
/*Clamps an integer into the given range.
|
||||
If _a>_c, then the lower bound _a is respected over the upper bound _c (this
|
||||
behavior is required to meet our documented API behavior).
|
||||
_a: The lower bound.
|
||||
_b: The value to clamp.
|
||||
_c: The upper boud.*/
|
||||
#define EC_CLAMPI(_a,_b,_c) (EC_MAXI(_a,EC_MINI(_b,_c)))
|
||||
|
||||
|
||||
/*Count leading zeros.
|
||||
This macro should only be used for implementing ec_ilog(), if it is defined.
|
||||
All other code should use EC_ILOG() instead.*/
|
||||
#if defined(_MSC_VER)
|
||||
# include <intrin.h>
|
||||
static __inline int ec_bsr(unsigned long _x){
|
||||
unsigned long ret;
|
||||
_BitScanReverse(&ret,_x);
|
||||
return (int)ret;
|
||||
}
|
||||
# define EC_CLZ0 (1)
|
||||
# define EC_CLZ(_x) (-ec_bsr(_x))
|
||||
#elif defined(ENABLE_TI_DSPLIB)
|
||||
# include "dsplib.h"
|
||||
# define EC_CLZ0 (31)
|
||||
# define EC_CLZ(_x) (_lnorm(x))
|
||||
#elif defined(__GNUC_PREREQ)
|
||||
# if __GNUC_PREREQ(3,4)
|
||||
# if INT_MAX>=2147483647
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clz(_x))
|
||||
# elif LONG_MAX>=2147483647L
|
||||
# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT)
|
||||
# define EC_CLZ(_x) (__builtin_clzl(_x))
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(EC_CLZ)
|
||||
/*Note that __builtin_clz is not defined when _x==0, according to the gcc
|
||||
documentation (and that of the BSR instruction that implements it on x86).
|
||||
The majority of the time we can never pass it zero.
|
||||
When we need to, it can be special cased.*/
|
||||
# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
|
||||
#else
|
||||
static int ec_ilog2(celt_uint32 _v){
|
||||
int ret;
|
||||
int m;
|
||||
ret=!!_v;
|
||||
m=!!(_v&0xFFFF0000)<<4;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xFF00)<<3;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xF0)<<2;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
m=!!(_v&0xC)<<1;
|
||||
_v>>=m;
|
||||
ret|=m;
|
||||
ret+=!!(_v&0x2);
|
||||
return ret;
|
||||
}
|
||||
# define EC_ILOG(_x) (ec_ilog2(_x))
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -369,7 +369,7 @@ ffmpeg_codec_data* init_ffmpeg_header_offset_subsong(STREAMFILE* sf, uint8_t* he
|
|||
#if 0
|
||||
/* derive info */
|
||||
data->sampleRate = data->codecCtx->sample_rate;
|
||||
data->channels = data->codecCtx->channels;
|
||||
data->channels = data->codecCtx->ch_layout.nb_channels; //data->codecCtx->channels;
|
||||
data->bitrate = (int)(data->codecCtx->bit_rate);
|
||||
data->blockAlign = data->codecCtx->block_align;
|
||||
data->frameSize = data->codecCtx->frame_size;
|
||||
|
@ -739,7 +739,11 @@ static void samples_dblp_to_s16(sample_t* obuf, double** inbuf, int ichs, int sa
|
|||
}
|
||||
|
||||
static void copy_samples(ffmpeg_codec_data* data, sample_t* outbuf, int samples_to_do) {
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 24, 100)
|
||||
int channels = data->codecCtx->channels;
|
||||
#else
|
||||
int channels = data->codecCtx->ch_layout.nb_channels;
|
||||
#endif
|
||||
int is_planar = av_sample_fmt_is_planar(data->codecCtx->sample_fmt) && (channels > 1);
|
||||
void* ibuf;
|
||||
|
||||
|
@ -976,19 +980,39 @@ void ffmpeg_set_skip_samples(ffmpeg_codec_data* data, int skip_samples) {
|
|||
/* returns channel layout if set */
|
||||
uint32_t ffmpeg_get_channel_layout(ffmpeg_codec_data* data) {
|
||||
if (!data || !data->codecCtx) return 0;
|
||||
return (uint32_t)data->codecCtx->channel_layout; /* uint64 but there ain't so many speaker mappings */
|
||||
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 24, 100)
|
||||
/* uint64 but there aren't so many speaker mappings */
|
||||
return (uint32_t)data->codecCtx->channel_layout;
|
||||
#else
|
||||
/* new API is not very clear so maybe there is a better way */
|
||||
if (data->codecCtx->ch_layout.order == AV_CHANNEL_ORDER_UNSPEC)
|
||||
return 0;
|
||||
if (data->codecCtx->ch_layout.order == AV_CHANNEL_ORDER_NATIVE) {
|
||||
return (uint32_t)data->codecCtx->ch_layout.u.mask;
|
||||
}
|
||||
|
||||
/* other options: not handled for now */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* yet another hack to fix codecs that encode channels in different order and reorder on decoder
|
||||
* but FFmpeg doesn't do it automatically
|
||||
* (maybe should be done via mixing, but could clash with other stuff?) */
|
||||
void ffmpeg_set_channel_remapping(ffmpeg_codec_data* data, int *channel_remap) {
|
||||
int i;
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 24, 100)
|
||||
int channels = data->codecCtx->channels;
|
||||
#else
|
||||
int channels = data->codecCtx->ch_layout.nb_channels;
|
||||
#endif
|
||||
|
||||
if (data->codecCtx->channels > 32)
|
||||
if (channels > 32)
|
||||
return;
|
||||
|
||||
for (i = 0; i < data->codecCtx->channels; i++) {
|
||||
for (i = 0; i < channels; i++) {
|
||||
data->channel_remap[i] = channel_remap[i];
|
||||
}
|
||||
data->channel_remap_set = 1;
|
||||
|
@ -1056,7 +1080,13 @@ int ffmpeg_get_sample_rate(ffmpeg_codec_data* data) {
|
|||
int ffmpeg_get_channels(ffmpeg_codec_data* data) {
|
||||
if (!data || !data->codecCtx)
|
||||
return 0;
|
||||
return data->codecCtx->channels;
|
||||
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(59, 24, 100)
|
||||
int channels = data->codecCtx->channels;
|
||||
#else
|
||||
int channels = data->codecCtx->ch_layout.nb_channels;
|
||||
#endif
|
||||
|
||||
return channels;
|
||||
}
|
||||
|
||||
int ffmpeg_get_subsong_count(ffmpeg_codec_data* data) {
|
||||
|
|
|
@ -778,10 +778,16 @@ static ffmpeg_codec_data* init_ffmpeg_custom_opus_config(STREAMFILE* sf, off_t s
|
|||
ffmpeg_data = init_ffmpeg_offset(temp_sf, 0x00, get_streamfile_size(temp_sf));
|
||||
if (!ffmpeg_data) goto fail;
|
||||
|
||||
/* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay (not in stream->skip_samples)
|
||||
* FFmpeg + opus: *doesn't* skip, also notifies skip in codecCtx->delay, hurray (possibly fixed in recent versions)
|
||||
* FFmpeg + opus is audibly buggy with some low bitrate SSB Ultimate files */
|
||||
//ffmpeg_set_skip_samples(ffmpeg_data, skip);
|
||||
/* FFmpeg + libopus: skips samples, notifies skip in codecCtx->delay/initial_padding (not in stream->skip_samples)
|
||||
* FFmpeg + opus: skip samples but loses them on reset/seek to 0, also notifies skip in codecCtx->delay/initial_padding */
|
||||
{
|
||||
/* quick fix for non-libopus (not sure how to detect better since both share AV_CODEC_ID_OPUS)*/
|
||||
const char* name = ffmpeg_get_codec_name(ffmpeg_data);
|
||||
if (name && (name[0] == 'O' || name[0] == 'o')) { /* "Opus" vs "libopus" */
|
||||
//ffmpeg_set_skip_samples(ffmpeg_data, cfg->skip); /* can't overwrite internal decoder skip */
|
||||
ffmpeg_set_force_seek(ffmpeg_data);
|
||||
}
|
||||
}
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
return ffmpeg_data;
|
||||
|
|
|
@ -189,7 +189,7 @@ fail:
|
|||
|
||||
|
||||
#define AHX_KEY_BUFFER 0x2000
|
||||
#define AHX_KEY_TEST_FRAMES 15 /* wrong keys may work ok in some frames */
|
||||
#define AHX_KEY_TEST_FRAMES 20 /* wrong keys may work ok in some frames */
|
||||
|
||||
/* check if current key ends properly in frame syncs */
|
||||
int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) {
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "../util.h"
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
#define OV_EXCLUDE_STATIC_CALLBACKS
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
#define OGG_DEFAULT_BITSTREAM 0
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
#include "../util.h"
|
||||
|
||||
/* SDX2 - 2:1 Squareroot-delta-exact compression */
|
||||
/* CBD2 - 2:1 Cuberoot-delta-exact compression (from the unreleased 3DO M2) */
|
||||
/* CBD2 - 2:1 Cuberoot-delta-exact compression (from 3DO/Konami M2) */
|
||||
|
||||
/* Original code is implemented with ops in a custom DSP (DSPP) with a variation of FORTH
|
||||
* (rather than tables), in the "3DO M2 Portfolio OS", so could be converted to plain calcs. */
|
||||
|
||||
|
||||
/* for (i=-128;i<128;i++) { squares[i+128] = i<0?(-i*i)*2:(i*i)*2; } */
|
||||
static int16_t squares[256] = {
|
||||
|
@ -34,6 +38,7 @@ static int16_t squares[256] = {
|
|||
};
|
||||
|
||||
/*
|
||||
// original DSP ops, seems equivalent to (i * i * i) / 64
|
||||
for (uint16_t i = 0; i < 0x100; i += 1) {
|
||||
int16_t v = i;
|
||||
v -= 0x80;
|
||||
|
@ -83,7 +88,8 @@ static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int
|
|||
int8_t sample_byte = read_8bit(stream->offset+i,stream->streamfile);
|
||||
int16_t sample;
|
||||
|
||||
if (!(sample_byte & 1)) hist = 0;
|
||||
if (!(sample_byte & 1)) /* even: "exact mode" (value as-is), odd: "delta mode" */
|
||||
hist = 0;
|
||||
sample = hist + table[sample_byte+128];
|
||||
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
|
@ -102,7 +108,8 @@ static void decode_delta_exact_int(VGMSTREAMCHANNEL * stream, sample_t * outbuf,
|
|||
int8_t sample_byte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
|
||||
int16_t sample;
|
||||
|
||||
if (!(sample_byte & 1)) hist = 0;
|
||||
if (!(sample_byte & 1)) /* even: "exact mode" (value as-is), odd: "delta mode" */
|
||||
hist = 0;
|
||||
sample = hist + table[sample_byte+128];
|
||||
|
||||
hist = outbuf[sample_count] = clamp16(sample);
|
||||
|
|
|
@ -70,6 +70,7 @@ static const char* extension_list[] = {
|
|||
"ap",
|
||||
"apc",
|
||||
"as4",
|
||||
"asbin",
|
||||
"asd",
|
||||
"asf",
|
||||
"asr",
|
||||
|
@ -145,6 +146,7 @@ static const char* extension_list[] = {
|
|||
"cpk",
|
||||
"cps",
|
||||
"csa", //txth/reserved [LEGO Racers 2 (PS2)]
|
||||
"csb",
|
||||
"csmp",
|
||||
"cvs", //txth/reserved [Aladdin in Nasira's Revenge (PS1)]
|
||||
"cwav",
|
||||
|
@ -263,6 +265,7 @@ static const char* extension_list[] = {
|
|||
"kces",
|
||||
"kcey", //fake extension/header id for .pcm (renamed, to be removed)
|
||||
"km9",
|
||||
"kma", //txth/reserved [Dynasty Warriors 7: Empires (PS3)]
|
||||
"kmx",
|
||||
"kovs", //fake extension/header id for .kvs
|
||||
"kno",
|
||||
|
@ -285,6 +288,7 @@ static const char* extension_list[] = {
|
|||
"lac3", //fake extension for .ac3, FFmpeg/not parsed
|
||||
"lasf", //fake extension for .asf (various)
|
||||
"lbin", //fake extension for .bin (various)
|
||||
"ldat", //fake extension for .dat
|
||||
"leg",
|
||||
"lep",
|
||||
"lflac", //fake extension for .flac, FFmpeg/not parsed
|
||||
|
@ -1276,8 +1280,6 @@ static const meta_info meta_info_list[] = {
|
|||
{meta_PC_FLX, "Ultima IX .FLX header"},
|
||||
{meta_MOGG, "Harmonix Music Systems MOGG Vorbis"},
|
||||
{meta_OGG_VORBIS, "Ogg Vorbis header"},
|
||||
{meta_OGG_SLI, "Ogg Vorbis header (.sli looping)"},
|
||||
{meta_OPUS_SLI, "Ogg Opus header (.sli looping)"},
|
||||
{meta_OGG_SFL, "Ogg Vorbis header (SFPL looping)"},
|
||||
{meta_OGG_KOVS, "Ogg Vorbis header (KOVS)"},
|
||||
{meta_OGG_encrypted, "Ogg Vorbis header (encrypted)"},
|
||||
|
|
|
@ -8,15 +8,15 @@ void block_update_thp(off_t block_offset, VGMSTREAM* vgmstream) {
|
|||
off_t audio_offset;
|
||||
size_t next_block_size, video_size;
|
||||
|
||||
next_block_size = read_u32be(block_offset + 0x00, sf);
|
||||
/* 0x04: frame size previous */
|
||||
next_block_size = read_u32be(block_offset + 0x00, sf); /* block may have padding, so need to save for next time */
|
||||
/* 0x04: previous frame size */
|
||||
video_size = read_u32be(block_offset + 0x08,sf);
|
||||
/* 0x0c: audio size */
|
||||
|
||||
audio_offset = block_offset + 0x10 + video_size;
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->next_block_offset = block_offset + vgmstream->full_block_size;
|
||||
vgmstream->next_block_offset = block_offset + vgmstream->full_block_size; /* use prev saved data */
|
||||
vgmstream->full_block_size = next_block_size;
|
||||
|
||||
/* block samples can be smaller than block size, normally in the last block,
|
||||
|
@ -27,9 +27,10 @@ void block_update_thp(off_t block_offset, VGMSTREAM* vgmstream) {
|
|||
audio_offset += 0x08;
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
/* always size of 2 channels even in mono [WarioWare Inc. (GC)] */
|
||||
off_t coef_offset = audio_offset + i*0x20;
|
||||
off_t hist_offset = audio_offset + vgmstream->channels*0x20 + i*0x04;
|
||||
off_t data_offset = audio_offset + 2*0x24 + i*vgmstream->current_block_size; /* reserved for 2 even in mono [WarioWare Inc. (GC)] */
|
||||
off_t hist_offset = audio_offset + 2*0x20 + i*0x04;
|
||||
off_t data_offset = audio_offset + 2*0x24 + i*vgmstream->current_block_size;
|
||||
|
||||
for (j = 0; j < 16; j++) {
|
||||
vgmstream->ch[i].adpcm_coef[j] = read_s16be(coef_offset + (j*0x02),sf);
|
||||
|
|
|
@ -133,91 +133,3 @@ fail:
|
|||
free_layout_segmented(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* CRI's UTF wrapper around DSP [Sonic Colors sfx (Wii), NiGHTS: Journey of Dreams sfx (Wii)] */
|
||||
VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
uint8_t loop_flag = 0, channels;
|
||||
uint32_t sample_rate, num_samples, loop_start, loop_end, interleave;
|
||||
uint32_t data_offset, data_size, header_offset, header_size;
|
||||
utf_context* utf = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "@UTF"))
|
||||
goto fail;
|
||||
|
||||
/* .aax: assumed
|
||||
* (extensionless): extracted names inside csb/cpk often don't have extensions */
|
||||
if (!check_extensions(sf, "aax,"))
|
||||
goto fail;
|
||||
|
||||
/* .aax contains a simple UTF table with one row and various columns being header info */
|
||||
{
|
||||
int rows;
|
||||
const char* name;
|
||||
uint32_t table_offset = 0x00;
|
||||
|
||||
|
||||
utf = utf_open(sf, table_offset, &rows, &name);
|
||||
if (!utf) goto fail;
|
||||
|
||||
if (strcmp(name, "ADPCM_WII") != 0)
|
||||
goto fail;
|
||||
|
||||
if (rows != 1)
|
||||
goto fail;
|
||||
|
||||
if (!utf_query_u32(utf, 0, "sfreq", &sample_rate))
|
||||
goto fail;
|
||||
if (!utf_query_u32(utf, 0, "nsmpl", &num_samples))
|
||||
goto fail;
|
||||
if (!utf_query_u8(utf, 0, "nch", &channels))
|
||||
goto fail;
|
||||
if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */
|
||||
goto fail;
|
||||
/* for some reason data is stored before header */
|
||||
if (!utf_query_data(utf, 0, "data", &data_offset, &data_size))
|
||||
goto fail;
|
||||
if (!utf_query_data(utf, 0, "header", &header_offset, &header_size))
|
||||
goto fail;
|
||||
|
||||
if (channels < 1 || channels > 2)
|
||||
goto fail;
|
||||
if (header_size != channels * 0x60)
|
||||
goto fail;
|
||||
|
||||
start_offset = data_offset;
|
||||
interleave = (data_size+7) / 8 * 8 / channels;
|
||||
|
||||
loop_start = read_32bitBE(header_offset + 0x10, sf);
|
||||
loop_end = read_32bitBE(header_offset + 0x14, sf);
|
||||
}
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(loop_end) + 1;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->meta_type = meta_UTF_DSP;
|
||||
|
||||
dsp_read_coefs_be(vgmstream, sf, header_offset+0x1c, 0x60);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -205,6 +205,9 @@ static const adxkey_info adxkey8_list[] = {
|
|||
/* Shoujo Yoshitsune-den Ni - Toki wo Koeru Chigiri (PS2) */
|
||||
{0x62d7,0x483d,0x4fb7, "YOSHI2",0},
|
||||
|
||||
/* Junjou Romantica - Koi no Doki Doki Daisakusen (PS2) (Marvelous) */
|
||||
{0x5827,0x612d,0x5585, "Endress-SETSUNAI!",0},
|
||||
|
||||
};
|
||||
|
||||
static const adxkey_info adxkey9_list[] = {
|
||||
|
|
|
@ -280,10 +280,11 @@ static VGMSTREAM* init_vgmstream_bxwav(STREAMFILE* sf, bxwav_type_t type) {
|
|||
/* 0x0c: ADPCM offset (from channel info offset), 0xFFFFFFFF otherwise */
|
||||
/* 0x10: padding */
|
||||
|
||||
if (read_u16(chnf_offset + 0x00, sf) != 0x1F00)
|
||||
/* 3DS doesn't seem to check this, allow for odd bcwavs from rstmcpp */
|
||||
if ((read_u16(chnf_offset + 0x00, sf) & 0x1F00) != 0x1F00) /* (ex. 0x1F01) */
|
||||
goto fail;
|
||||
chdt_offset = read_u32(chnf_offset + 0x04, sf) + data_offset + 0x08;
|
||||
coef_offset = read_u32(chnf_offset + 0x0c, sf) + chnf_offset;
|
||||
coef_offset = read_u32(chnf_offset + 0x0c, sf) + chnf_offset; /* usually after all channel info but will allow any position */
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -131,6 +131,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||
case 0x0d: /* Polara (Vita), Crypt of the Necrodancer (Vita) */
|
||||
case 0x0e: /* Yakuza 6's Puyo Puyo (PS4) */
|
||||
case 0x0f: /* Ikaruga (PS4) */
|
||||
case 0x10: /* Ginga Force (PS4) */
|
||||
table1_offset = sblk_offset + read_u32(sblk_offset+0x18,sf);
|
||||
table2_offset = sblk_offset + read_u32(sblk_offset+0x1c,sf);
|
||||
table3_offset = sblk_offset + read_u32(sblk_offset+0x2c,sf);
|
||||
|
@ -305,6 +306,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
case 0x10:
|
||||
flags = read_u8 (table3_offset+table3_entry_offset+0x12,sf);
|
||||
stream_offset = read_u32(table3_offset+table3_entry_offset+0x44,sf);
|
||||
stream_size = read_u32(table3_offset+table3_entry_offset+0x48,sf);
|
||||
|
@ -325,6 +327,8 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||
case 0x09:
|
||||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
case 0x10:
|
||||
/* find if this sound has an assigned name in table1 */
|
||||
for (i = 0; i < section_entries; i++) {
|
||||
uint32_t entry_offset = read_u16(table1_offset+(i*table1_entry_size)+table1_suboffset+0x00,sf);
|
||||
|
@ -479,6 +483,7 @@ VGMSTREAM* init_vgmstream_bnk_sony(STREAMFILE* sf) {
|
|||
case 0x0d:
|
||||
case 0x0e:
|
||||
case 0x0f:
|
||||
case 0x10:
|
||||
type = read_u16(start_offset+0x00,sf);
|
||||
if (read_u32(start_offset+0x04,sf) != 0x01) /* type? */
|
||||
goto fail;
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
off_t subfile_offset;
|
||||
size_t subfile_size;
|
||||
uint32_t subfile_offset, subfile_size;
|
||||
utf_context* utf = NULL;
|
||||
utf_context* utf_sdl = NULL;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
|
@ -17,10 +16,10 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) {
|
|||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "csb"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x00,sf, "@UTF"))
|
||||
goto fail;
|
||||
if (!check_extensions(sf, "csb"))
|
||||
goto fail;
|
||||
|
||||
/* .csb is an early, simpler version of .acb+awk (see acb.c) used until ~2013?
|
||||
* Can stream from .cpk but this only loads memory data. */
|
||||
|
@ -115,9 +114,7 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
//;VGM_LOG("CSB: subfile offset=%lx + %x\n", subfile_offset, subfile_size);
|
||||
|
||||
|
||||
//;VGM_LOG("CSB: subfile offset=%x + %x\n", subfile_offset, subfile_size);
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "aax");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
|
@ -128,6 +125,11 @@ VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf) {
|
|||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
|
||||
case 2: /* AHX */
|
||||
vgmstream = init_vgmstream_utf_ahx(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
|
||||
case 4: /* ADPCM_WII */
|
||||
vgmstream = init_vgmstream_utf_dsp(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
@ -153,3 +155,147 @@ fail:
|
|||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* CRI's UTF wrapper around DSP [Sonic Colors (Wii)-sfx, NiGHTS: Journey of Dreams (Wii)-sfx] */
|
||||
VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
uint8_t loop_flag = 0, channels;
|
||||
uint32_t sample_rate, num_samples, loop_start, loop_end, interleave;
|
||||
uint32_t data_offset, data_size, header_offset, header_size;
|
||||
utf_context* utf = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "@UTF"))
|
||||
goto fail;
|
||||
|
||||
/* .aax: assumed
|
||||
* (extensionless): extracted names inside csb/cpk often don't have extensions */
|
||||
if (!check_extensions(sf, "aax,"))
|
||||
goto fail;
|
||||
|
||||
/* contains a simple UTF table with one row and various columns being header info */
|
||||
{
|
||||
int rows;
|
||||
const char* name;
|
||||
uint32_t table_offset = 0x00;
|
||||
|
||||
|
||||
utf = utf_open(sf, table_offset, &rows, &name);
|
||||
if (!utf) goto fail;
|
||||
|
||||
if (strcmp(name, "ADPCM_WII") != 0)
|
||||
goto fail;
|
||||
|
||||
if (rows != 1)
|
||||
goto fail;
|
||||
|
||||
if (!utf_query_u32(utf, 0, "sfreq", &sample_rate))
|
||||
goto fail;
|
||||
if (!utf_query_u32(utf, 0, "nsmpl", &num_samples))
|
||||
goto fail;
|
||||
if (!utf_query_u8(utf, 0, "nch", &channels))
|
||||
goto fail;
|
||||
if (!utf_query_u8(utf, 0, "lpflg", &loop_flag)) /* full loops */
|
||||
goto fail;
|
||||
/* for some reason data is stored before header */
|
||||
if (!utf_query_data(utf, 0, "data", &data_offset, &data_size))
|
||||
goto fail;
|
||||
if (!utf_query_data(utf, 0, "header", &header_offset, &header_size))
|
||||
goto fail;
|
||||
|
||||
if (channels < 1 || channels > 2)
|
||||
goto fail;
|
||||
if (header_size != channels * 0x60)
|
||||
goto fail;
|
||||
|
||||
start_offset = data_offset;
|
||||
interleave = (data_size+7) / 8 * 8 / channels;
|
||||
|
||||
loop_start = read_32bitBE(header_offset + 0x10, sf);
|
||||
loop_end = read_32bitBE(header_offset + 0x14, sf);
|
||||
}
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(loop_start);
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(loop_end) + 1;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
vgmstream->meta_type = meta_UTF_DSP;
|
||||
|
||||
dsp_read_coefs_be(vgmstream, sf, header_offset+0x1c, 0x60);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
utf_close(utf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
utf_close(utf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* CRI's UTF wrapper around AHX [Yakuza: Dead Souls (PS3)-voices] */
|
||||
VGMSTREAM* init_vgmstream_utf_ahx(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
uint32_t subfile_offset, subfile_size;
|
||||
utf_context* utf = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "@UTF"))
|
||||
goto fail;
|
||||
|
||||
/* .aax: assumed
|
||||
* (extensionless): extracted names inside csb/cpk often don't have extensions */
|
||||
if (!check_extensions(sf, "aax,"))
|
||||
goto fail;
|
||||
|
||||
/* contains a simple UTF table with one row and offset+size info */
|
||||
{
|
||||
int rows;
|
||||
const char* name;
|
||||
uint32_t table_offset = 0x00;
|
||||
|
||||
utf = utf_open(sf, table_offset, &rows, &name);
|
||||
if (!utf) goto fail;
|
||||
|
||||
if (strcmp(name, "AHX") != 0)
|
||||
goto fail;
|
||||
|
||||
if (rows != 1)
|
||||
goto fail;
|
||||
|
||||
if (!utf_query_data(utf, 0, "data", &subfile_offset, &subfile_size))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
//;VGM_LOG("UTF_AHX: subfile offset=%x + %x\n", subfile_offset, subfile_size);
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, "ahx");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
vgmstream = init_vgmstream_ahx(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
utf_close(utf);
|
||||
close_streamfile(temp_sf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
utf_close(utf);
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,10 @@ VGMSTREAM* init_vgmstream_fsb_encrypted(STREAMFILE* sf) {
|
|||
uint8_t key[FSB_KEY_MAX];
|
||||
size_t key_size = read_key_file(key, FSB_KEY_MAX, sf);
|
||||
|
||||
test_fsbkey(sf, key, key_size, MODE_FSBS_ALL);
|
||||
if (key_size) {
|
||||
vgmstream = test_fsbkey(sf, key, key_size, MODE_FSBS_ALL);
|
||||
return vgmstream;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,22 +68,22 @@ static VGMSTREAM* test_fsbkey(STREAMFILE* sf, const uint8_t* key, size_t key_siz
|
|||
if (!vc && test_std) {
|
||||
temp_sf = setup_fsb_streamfile(sf, key, key_size, 0);
|
||||
if (!temp_sf) return NULL;
|
||||
//;dump_streamfile(temp_sf, 0);
|
||||
|
||||
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
|
||||
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
|
||||
|
||||
//;if (vgmstream) dump_streamfile(temp_sf, 0);
|
||||
close_streamfile(temp_sf);
|
||||
}
|
||||
|
||||
if (!vc && test_alt) {
|
||||
temp_sf = setup_fsb_streamfile(sf, key, key_size, 1);
|
||||
if (!temp_sf) return NULL;
|
||||
//;dump_streamfile(temp_sf, 1);
|
||||
|
||||
if (!vc && test_fsb4) vc = init_vgmstream_fsb(temp_sf);
|
||||
if (!vc && test_fsb5) vc = init_vgmstream_fsb5(temp_sf);
|
||||
|
||||
//;if (vgmstream) dump_streamfile(temp_sf, 0);
|
||||
close_streamfile(temp_sf);
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,8 @@ static const fsbkey_info fsbkey_list[] = {
|
|||
{ MODE_FSB5_STD, FSBKEY_ADD("4FB8CC894515617939F4E1B7D50972D27213B8E6") }, // Cult of the Lamb Demo (PC)
|
||||
{ MODE_FSB5_STD, FSBKEY_ADD("X3EK%Bbga-%Y9HZZ%gkc*C512*$$DhRxWTGgjUG@=rUD") }, // Signalis (PC)
|
||||
{ MODE_FSB5_STD, FSBKEY_ADD("281ad163160cfc16f9a22c6755a64fad") }, // Ash Echoes beta (Android)
|
||||
|
||||
{ MODE_FSB5_STD, FSBKEY_ADD("Aurogon666") }, // Afterimage demo (PC)
|
||||
{ MODE_FSB5_STD, FSBKEY_ADD("IfYouLikeThosesSoundsWhyNotRenumerateTheir2Authors?") }, // Blanc (PC/Switch)
|
||||
};
|
||||
static const int fsbkey_list_count = sizeof(fsbkey_list) / sizeof(fsbkey_list[0]);
|
||||
|
||||
|
|
|
@ -95,6 +95,8 @@ static const hcakey_info hcakey_list[] = {
|
|||
{9001712656335836006}, // 7CEC81F7C3091366
|
||||
|
||||
// Ikemen Vampire - Ijin-tachi to Koi no Yuuwaku (iOS/Android)
|
||||
// Ikemen Villains (Android)
|
||||
// Ikemen Prince (Android)
|
||||
{45152594117267709}, // 00A06A0B8D0C10FD
|
||||
|
||||
// Super Robot Wars X-Omega (iOS/Android)
|
||||
|
@ -449,6 +451,9 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x3613e2a7fdfc0784}, //music_0110027
|
||||
{0xc239d244b6d3b722}, //music_0110028
|
||||
{0x2575c136a260e723}, //music_0110029
|
||||
{0x22c6b455883b1c28}, //music_0110030
|
||||
{0xff2ae68fa067f80a}, //music_0110031
|
||||
{0x422ca19b0fa5c7c0}, //music_0110032
|
||||
{0xfb647d074e53fab6}, //music_0120001
|
||||
{0xc24049b9f7ed3105}, //music_0120002
|
||||
{0xdc128f2fd48bf4b}, //music_0120003
|
||||
|
@ -487,6 +492,9 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x2822bba0a5c4f18c}, //music_0210015
|
||||
{0xff579d3fcfa8453a}, //music_0210016
|
||||
{0x3caa61e8b958f6d8}, //music_0210017
|
||||
{0xe38b758bcadfc621}, //music_0210018
|
||||
{0x3399e970670db2ba}, //music_0210019
|
||||
{0x1cb76530af356c05}, //music_0210020
|
||||
{0x15bb78c31db0a0b6}, //music_0220001
|
||||
{0x59b1257242c40109}, //music_0220002
|
||||
{0xdb402bd08d522f34}, //music_0220003
|
||||
|
@ -526,6 +534,9 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x22e33db9b5625a96}, //music_0310016
|
||||
{0xb78070802414de7a}, //music_0310017
|
||||
{0x572aeeed86655119}, //music_0310018
|
||||
{0x86ca86794400f49d}, //music_0310019
|
||||
{0x7a2bbc195b9bfac1}, //music_0310020
|
||||
{0x1c1f029bb47594b1}, //music_0310021
|
||||
{0xb921c3992807dadd}, //music_0320001
|
||||
{0x38ad99a045dc971f}, //music_0320002
|
||||
{0xf616642579ba5850}, //music_0320003
|
||||
|
@ -544,6 +555,7 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x2df608ef06aca41c}, //music_0320016
|
||||
{0x641af19c287d4a2e}, //music_0320017
|
||||
{0x82de7b71b30d7bc2}, //music_0320019
|
||||
{0x100b7ca3075996fe}, //music_0320020
|
||||
{0x776c4aded0bca5d1}, //music_0410001
|
||||
{0xb7bff4fbf66be43f}, //music_0410002
|
||||
{0x904f50c5ce8ec6e4}, //music_0410003
|
||||
|
@ -560,6 +572,10 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0xd8cdd53589ad3634}, //music_0410014
|
||||
{0x88007190e0bfa1ce}, //music_0410015
|
||||
{0x6fccdd5c3d0d6e3e}, //music_0410016
|
||||
{0x9d8037d7bfb3fc1d}, //music_0410017
|
||||
{0x685b5601a43b6c60}, //music_0410018
|
||||
{0x75927596a180f3e3}, //music_0410019
|
||||
{0xc3d36676d54255c5}, //music_0410020
|
||||
{0x5d1f3fdbbb036f8d}, //music_0420001
|
||||
{0xc04264e8f34ad5c0}, //music_0420002
|
||||
{0x8f0e96b4f71f724f}, //music_0420003
|
||||
|
@ -597,6 +613,8 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x7878df60f0549c4}, //music_0510017
|
||||
{0x8e5b7068022828e0}, //music_0510018
|
||||
{0xb069a5c5e2d93edf}, //music_0510019
|
||||
{0x30f9dcefa450733a}, //music_0510020
|
||||
{0xf85695960e2dcb7f}, //music_0510021
|
||||
{0x15f82c1617013c36}, //music_0520001
|
||||
{0xc7da8e6f0e2fe399}, //music_0520002
|
||||
{0xe350bffcdc9cb686}, //music_0520003
|
||||
|
@ -633,6 +651,10 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x3aa02e0a37543b5c}, //music_0610017
|
||||
{0xc451f1deddae08ca}, //music_0610018
|
||||
{0xc0fa6669d9904919}, //music_0610019
|
||||
{0x4ad7fd8dafaa58a9}, //music_0610020
|
||||
{0x7aece54359beac21}, //music_0610021
|
||||
{0x7c9332be25e5c95a}, //music_0610022
|
||||
{0x415eef25f84e8c2e}, //music_0610023
|
||||
{0x8258ddd6a1d0849b}, //music_0620001
|
||||
{0x1dd21a1244ca12f1}, //music_0620002
|
||||
{0xfdec74b23d8b494b}, //music_0620003
|
||||
|
@ -652,7 +674,15 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x5c1195d8afcb1901}, //music_0620017
|
||||
{0x1ad8db767d9ba4a7}, //music_0620018
|
||||
{0x9bc820aa161b0f08}, //music_0620019
|
||||
{0xd1df27a57399613e}, //music_0810001
|
||||
{0xd37ec4cb304e16ae}, //music_0810002
|
||||
{0x1e99d14d97ab82c5}, //music_0820001
|
||||
{0x5bf7cefecda8bcb2}, //music_0820002
|
||||
{0x9cf7ab0ccafa374e}, //music_0820003
|
||||
{0x972b52f3dfaa387a}, //music_0910001
|
||||
{0x407a4b6c3dcf2509}, //music_0910002
|
||||
{0x4683c57919dbdeee}, //music_0920001
|
||||
{0x126d0d20ad7f0401}, //music_0920002
|
||||
{0x2a47feac8dc3ca9c}, //music_3010001
|
||||
{0x9ebbaf63ffe9d9ef}, //music_3010002
|
||||
{0xe553dba6592293d8}, //music_3010003
|
||||
|
@ -669,6 +699,11 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0xef257f41a265a0af}, //music_3010015
|
||||
{0x5e23d8a2488bc715}, //music_3010016
|
||||
{0x198cc607e20dd264}, //music_3010017
|
||||
{0x31a9ab25b5dff424}, //music_3010018
|
||||
{0x17f53cfa841f41b5}, //music_3010020
|
||||
{0x4992a33be3ba81dd}, //music_3010021
|
||||
{0x86d0ab836f09a599}, //music_3010022
|
||||
{0x157f20b466d75228}, //music_3010024
|
||||
{0xfd3ea450350d666f}, //music_3020001
|
||||
{0x5e91a3790c32e2b3}, //music_3020002
|
||||
{0x358adfd1bbd3a95e}, //music_3020003
|
||||
|
@ -683,6 +718,12 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x98c7a1d1c45df640}, //music_3020013
|
||||
{0x3d01826fe053ddda}, //music_3020014
|
||||
{0xa6a6426caed68f7c}, //music_3020015
|
||||
{0x34cc16f635101f02}, //music_3020016
|
||||
{0x4429ed54ca45a36d}, //music_3020018
|
||||
{0xcc935f3ebbb7bb94}, //music_3020019
|
||||
{0x4a1d57f0db140c12}, //music_3020020
|
||||
{0x8ddea25a12f93099}, //music_3020022
|
||||
{0xf754248dcd46287e}, //music_3020023
|
||||
{0xdfad847a86a126bb}, //music_5030001
|
||||
{0x711ef85045b8c26e}, //music_5030002
|
||||
{0xff7640b46d72b337}, //music_5030003
|
||||
|
@ -782,6 +823,8 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0xc3a72539b831ea6e}, //music_5030097
|
||||
{0x8bc6b7b7a2d2bba3}, //music_5030098
|
||||
{0xdbb0f41e90b30452}, //music_5030099
|
||||
{0x2eb141954bb3bd25}, //music_5030101
|
||||
{0xaee2837e71b2bb97}, //music_5030102
|
||||
{0x444dda6d55d76095}, //music_5040001
|
||||
{0xcbf4f1324081e0a6}, //music_5040002
|
||||
{0xf1db3c1d9542063a}, //music_5040003
|
||||
|
@ -960,12 +1003,14 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0x6f321adde08396e3}, //music_5050163
|
||||
{0x58afa6381eeb1425}, //music_5050164
|
||||
{0x751daf7d1a5401cb}, //music_5050165
|
||||
{0xff2ea77b81c3ff6}, //music_5050166
|
||||
{0xbd6b66823f854f68}, //music_5050167
|
||||
{0xceb902b93eba45d8}, //music_5050168
|
||||
{0x2550e145b93723ae}, //music_5050169
|
||||
{0xb512188a55b8b698}, //music_5050170
|
||||
{0x26e5bf2c66a9898d}, //music_5050171
|
||||
{0xd93d0a1764e85d4d}, //music_5050176
|
||||
{0xff8c5c13833b1049}, //music_5050177
|
||||
{0x59efd868058a402e}, //music_5050178
|
||||
{0x93075c0fbb31f463}, //music_5050179
|
||||
{0xdedb6ae518faac3d}, //music_5050180
|
||||
|
@ -975,9 +1020,32 @@ static const hcakey_info hcakey_list[] = {
|
|||
{0xbd2f4b5ab481d300}, //music_5050184
|
||||
{0x1a253c2f40a38917}, //music_5050185
|
||||
{0xc735e9f28243ea8a}, //music_5050186
|
||||
{0x8137f876a1a8850b}, //music_5050187
|
||||
{0x82bd2fef6ad49c01}, //music_5050188
|
||||
{0xe77f67dd5b7aed71}, //music_5050189
|
||||
{0x2896fe0212b06d81}, //music_5050190
|
||||
{0xe60abdb973ad274a}, //music_5050191
|
||||
{0xe84e1005c5eeab22}, //music_5050192
|
||||
{0x1374b00b87c43440}, //music_5050193
|
||||
{0xf9b45750656b28bd}, //music_5050194
|
||||
{0x32f55efe2bd0a4fd}, //music_5050195
|
||||
{0x9092a8ef4ebacb7f}, //music_5050196
|
||||
{0x39a04e2ebc026177}, //music_5050197
|
||||
{0x1c848089b2d1a7b6}, //music_5050198
|
||||
{0x24feeee9ce287093}, //music_5050199
|
||||
{0x4226eb6f52ad4637}, //music_5050200
|
||||
{0x59ab358c5cded7c4}, //music_5050201
|
||||
{0x29ca209dae13020a}, //music_5050202
|
||||
{0x7fe1bc7cbda4a457}, //music_5050203
|
||||
{0x928964b93fce5bc9}, //music_5050204
|
||||
{0x58a46c0179f0d6ff}, //music_5050205
|
||||
{0x929ca6a5e8e0445}, //music_5050206
|
||||
{0xf0de6097ea78513c}, //music_5050207
|
||||
{0xcde0de0e1216bdea}, //music_5050208
|
||||
{0x52c250eade92393b}, //music_9010001
|
||||
{0xf66e6bb5b0599b07}, //music_9010002
|
||||
{0x8582b5a60dbbf948}, //music_9010003
|
||||
{0x5bb84b8a5677046f}, //music_9010004
|
||||
{0xfea0d6adff136868}, //music_9050001
|
||||
{0x19480b946279507a}, //music_9050002
|
||||
|
||||
|
@ -1093,16 +1161,29 @@ static const hcakey_info hcakey_list[] = {
|
|||
{97648135}, // 0000000005d1fe07
|
||||
|
||||
// CHUNITHM International Version (AC)
|
||||
{33426922444908636}, // 0076C19BDE43685C
|
||||
{33426922444908636}, // 0076C19BDE43685C
|
||||
|
||||
// Star Ocean: The Divine Force (PC)
|
||||
{68308868861462528}, // 00f2ae8de77f0800
|
||||
{68308868861462528}, // 00f2ae8de77f0800
|
||||
|
||||
// Sin Chronicle (Android)
|
||||
{4385672148314579020}, // 3CDD0995259D604C
|
||||
{4385672148314579020}, // 3CDD0995259D604C
|
||||
|
||||
// The Eminence in Shadow: Master of Garden (Android)
|
||||
{8115775984160473168}, // 70A1074224880050
|
||||
{8115775984160473168}, // 70A1074224880050
|
||||
|
||||
// Punishing: Gray Raven (Android)-newer assets
|
||||
{62855594017927612}, // 00DF4ED46995B1BC
|
||||
|
||||
// Dragon Quest The Adventure of Dai: A Hero's Bonds (Android)
|
||||
{503876638109847402}, // 06FE2121F927CF6A (in criware decryptor init code, xor of 2 strings)
|
||||
|
||||
// Love Live! School Idol Festival 2 MIRACLE LIVE (Android)
|
||||
{5067530812966687744}, // 46537c6ceb39d400
|
||||
|
||||
// 404 Game RE:SET Prologue Demo (Android)
|
||||
{21588207721978971}, // 004CB25C4C9B1C5B
|
||||
|
||||
};
|
||||
|
||||
#endif/*_HCA_KEYS_H_*/
|
||||
|
|
|
@ -6,23 +6,24 @@
|
|||
/* KTSC - Koei Tecmo KTSR container */
|
||||
VGMSTREAM* init_vgmstream_ktsc(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE *temp_sf = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int target_subsong = sf->stream_index, total_subsongs;
|
||||
off_t offset, subfile_offset;
|
||||
size_t subfile_size;
|
||||
uint32_t offset, subfile_offset, subfile_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .ktsl2asbin: common [Atelier Ryza (PC)] */
|
||||
if (!check_extensions(sf, "ktsl2asbin"))
|
||||
if (!is_id32be(0x00, sf, "KTSC"))
|
||||
goto fail;
|
||||
if (read_u32be(0x04, sf) != 0x01000001) /* version? */
|
||||
goto fail;
|
||||
|
||||
/* .ktsl2asbin: common [Atelier Ryza (PC)]
|
||||
* .asbin: Warriors Orochi 4 (PC) (assumed) */
|
||||
if (!check_extensions(sf, "ktsl2asbin,asbin"))
|
||||
goto fail;
|
||||
|
||||
/* KTSC is a container of KTSRs, but can't be extracted easily as they use absolute pointers to the
|
||||
* same stream companion file. KTSRs may have subsongs, but only seem to have 1, so use KTSC's subsongs. */
|
||||
if (read_u32be(0x00, sf) != 0x4B545343) /* "KTSC" */
|
||||
goto fail;
|
||||
if (read_u32be(0x04, sf) != 0x01000001) /* version? */
|
||||
goto fail;
|
||||
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
total_subsongs = read_u32le(0x08, sf);
|
||||
|
|
|
@ -49,8 +49,9 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
|||
goto fail;
|
||||
if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */
|
||||
goto fail;
|
||||
/* .ktsl2asbin: common [Atelier Ryza (PC/Switch), Nioh (PC)] */
|
||||
if (!check_extensions(sf, "ktsl2asbin"))
|
||||
/* .ktsl2asbin: common [Atelier Ryza (PC/Switch), Nioh (PC)]
|
||||
* .asbin: Warriors Orochi 4 (PC) */
|
||||
if (!check_extensions(sf, "ktsl2asbin,asbin"))
|
||||
goto fail;
|
||||
|
||||
/* KTSR can be a memory file (ktsl2asbin), streams (ktsl2stbin) and global config (ktsl2gcbin)
|
||||
|
@ -65,9 +66,10 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
|||
|
||||
/* open companion body */
|
||||
if (ktsr.is_external) {
|
||||
sf_b = open_streamfile_by_ext(sf, "ktsl2stbin");
|
||||
const char* companion_ext = check_extensions(sf, "asbin") ? "stbin" : "ktsl2stbin";
|
||||
sf_b = open_streamfile_by_ext(sf, companion_ext);
|
||||
if (!sf_b) {
|
||||
vgm_logi("KTSR: companion file '*.ktsl2stbin' not found\n");
|
||||
vgm_logi("KTSR: companion file '*.%s' not found\n", companion_ext);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -153,7 +153,7 @@ static VGMSTREAM* init_vgmstream_koei_wavebank(kwb_header* kwb, STREAMFILE* sf_h
|
|||
init_vgmstream = init_vgmstream_dsp_apex;
|
||||
}
|
||||
else {
|
||||
vgm_logi("KWB: unknown type %x at %x\n", id, kwb->stream_offset);
|
||||
vgm_logi("KWB: unknown type id=%x at offset=%x\n", id, kwb->stream_offset);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -675,18 +675,18 @@ static int parse_type_msfbank(kwb_header* kwb, off_t offset, STREAMFILE* sf) {
|
|||
// return 0;
|
||||
}
|
||||
|
||||
static int parse_type_xwsfile(kwb_header* kwb, off_t offset, STREAMFILE* sf) {
|
||||
off_t table1_offset, table2_offset;
|
||||
static int parse_type_xwsfile(kwb_header* kwb, uint32_t offset, STREAMFILE* sf) {
|
||||
uint32_t table1_offset, table2_offset;
|
||||
int i, chunks, chunks2;
|
||||
uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
if (!(is_id32be(offset + 0x00, sf, "XWSF") && is_id32be(offset + 0x04, sf, "ILE\0")) &&
|
||||
!(is_id32be(offset + 0x00, sf, "tdpa") && is_id32be(offset + 0x04, sf, "ck\0\0")))
|
||||
if (!(is_id64be(offset + 0x00, sf, "XWSFILE\0")) &&
|
||||
!(is_id64be(offset + 0x00, sf, "tdpack\0\0")))
|
||||
goto fail;
|
||||
|
||||
kwb->big_endian = read_u8(offset + 0x08, sf) == 0xFF;
|
||||
/* 0x0a: version? (0100: NG2/NG3 PS3, 0101: DoA LR PC) */
|
||||
/* 0x0a: version? (0100: NG2/NG3 PS3, 0101: DoA LR PC, NG2/3 PC) */
|
||||
|
||||
read_u32 = kwb->big_endian ? read_u32be : read_u32le;
|
||||
|
||||
|
@ -706,52 +706,56 @@ static int parse_type_xwsfile(kwb_header* kwb, off_t offset, STREAMFILE* sf) {
|
|||
|
||||
i = 0;
|
||||
while (i < chunks) {
|
||||
uint32_t entry_type, head_offset, body_offset, head_size;
|
||||
uint32_t entry_type, head_offset, head_size;
|
||||
//;VGM_LOG("XWS: entry %i/%i\n", i, chunks);
|
||||
|
||||
/* NG2/NG3 PS3 have table1+2, DoA LR PC removes table2 and includes body offset in entries */
|
||||
/* NG2/NG3 PS3/PC have table1+2, DoA LR PC doesn't (not very useful) */
|
||||
if (table2_offset) {
|
||||
head_offset = read_u32(offset + table1_offset + i * 0x04 + 0x00, sf);
|
||||
head_size = read_u32(offset + table2_offset + i * 0x04 + 0x00, sf);
|
||||
body_offset = head_offset;
|
||||
i += 1;
|
||||
|
||||
/* sometimes has file end offset as entry with no size*/
|
||||
if (!head_size)
|
||||
head_offset = read_u32(offset + table1_offset + i * 0x04, sf);
|
||||
head_size = read_u32(offset + table2_offset + i * 0x04, sf);
|
||||
if (!head_size) { /* sometimes has file end offset as entry with no size (NG PS3)*/
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
head_offset = read_u32(offset + table1_offset + i * 0x04 + 0x00, sf);
|
||||
body_offset = read_u32(offset + table1_offset + i * 0x04 + 0x04, sf);
|
||||
i += 2;
|
||||
head_offset = read_u32(offset + table1_offset + i * 0x04, sf);
|
||||
}
|
||||
|
||||
if (!head_offset) /* just in case */
|
||||
if (!head_offset) { /* just in case */
|
||||
i += 1;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
head_offset += offset;
|
||||
body_offset += offset;
|
||||
entry_type = read_u32be(head_offset + 0x00, sf);
|
||||
//;VGM_LOG("XWS: head=%x, body=%x\n", head_offset, body_offset);
|
||||
//;VGM_LOG("XWS: head=%x\n", head_offset);
|
||||
|
||||
if (entry_type == get_id32be("XWSF")) { /* + "ILE\0" */
|
||||
i += 1;
|
||||
if (!parse_type_xwsfile(kwb, head_offset, sf))
|
||||
goto fail;
|
||||
}
|
||||
else if (entry_type == get_id32be("CUEB") || entry_type < 0x100) {
|
||||
; /* CUE-like info (may start with 0 or a low number instead) */
|
||||
i += 1;
|
||||
/* CUE-like info (may start with 0 or a low number instead) */
|
||||
}
|
||||
else if (entry_type == get_id32be("MSFB")) { /* + "ANK\0" */
|
||||
i += 1;
|
||||
if (!parse_type_msfbank(kwb, head_offset, sf))
|
||||
goto fail;
|
||||
}
|
||||
else if (entry_type == get_id32be("KWB2")) {
|
||||
/* NG2/3 PC, DoA LR PC goes head,body,... */
|
||||
uint32_t body_offset = read_u32(offset + table1_offset + i * 0x04 + 0x04, sf);
|
||||
body_offset += offset;
|
||||
i += 2;
|
||||
|
||||
if (!parse_type_kwb2(kwb, head_offset, body_offset, sf))
|
||||
goto fail;
|
||||
}
|
||||
else {
|
||||
vgm_logi("XWS: unknown type %x at head=%x, body=%x\n", entry_type, head_offset, body_offset);
|
||||
vgm_logi("XWS: unknown chunk %i (%x) with head=%x at %x\n", i, entry_type, head_offset, offset);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,7 +160,7 @@ VGMSTREAM * init_vgmstream_mp4_aac(STREAMFILE * streamFile);
|
|||
VGMSTREAM * init_vgmstream_mp4_aac_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
|
||||
#endif
|
||||
|
||||
VGMSTREAM * init_vgmstream_sli_ogg(STREAMFILE * streamFile);
|
||||
VGMSTREAM* init_vgmstream_sli_loops(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM * init_vgmstream_sfl_ogg(STREAMFILE * streamFile);
|
||||
|
||||
|
@ -359,8 +359,6 @@ VGMSTREAM * init_vgmstream_wii_sng(STREAMFILE *streamFile);
|
|||
|
||||
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ngc_ffcc_str(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_sat_baka(STREAMFILE *streamFile);
|
||||
|
@ -880,7 +878,9 @@ VGMSTREAM* init_vgmstream_xssb(STREAMFILE *sf);
|
|||
|
||||
VGMSTREAM* init_vgmstream_xma_ue3(STREAMFILE *sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_csb(STREAMFILE *sf);
|
||||
VGMSTREAM* init_vgmstream_csb(STREAMFILE* sf);
|
||||
VGMSTREAM* init_vgmstream_utf_dsp(STREAMFILE* sf);
|
||||
VGMSTREAM* init_vgmstream_utf_ahx(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM *init_vgmstream_fwse(STREAMFILE *streamFile);
|
||||
|
||||
|
|
|
@ -519,7 +519,8 @@ static int parse_musx(STREAMFILE* sf, musx_header* musx) {
|
|||
case 0x44415434: /* "DAT4" */
|
||||
case 0x44415435: /* "DAT5" */
|
||||
case 0x44415438: /* "DAT8" */
|
||||
/* found on PS3/Wii (but not always?) */
|
||||
case 0x44415439: /* "DAT9" [Disney Infinity (X360)] */
|
||||
/* found on PS3/Wii/X360 (but not always?) */
|
||||
musx->stream_size = read_u32le(0x44, sf);
|
||||
musx->channels = read_u32le(0x48, sf);
|
||||
musx->sample_rate = read_u32le(0x4c, sf);
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
typedef enum { IDSP, OPUS, RIFF, } nus3audio_codec;
|
||||
typedef enum { IDSP, OPUS, RIFF, BNSF, } nus3audio_codec;
|
||||
|
||||
/* .nus3audio - Namco's newest newest audio container [Super Smash Bros. Ultimate (Switch), Mobile Suit Gundam: Extreme Vs. Maxi Boost ON (PS4)] */
|
||||
VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
off_t subfile_offset = 0, name_offset = 0;
|
||||
size_t subfile_size = 0;
|
||||
uint32_t subfile_offset = 0, subfile_size = 0, name_offset = 0;
|
||||
nus3audio_codec codec;
|
||||
const char* fake_ext = NULL;
|
||||
int total_subsongs, target_subsong = sf->stream_index, found = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "nus3audio"))
|
||||
goto fail;
|
||||
if (read_u32be(0x00,sf) != 0x4E555333) /* "NUS3" */
|
||||
if (!is_id32be(0x00,sf, "NUS3"))
|
||||
goto fail;
|
||||
if (read_u32le(0x04,sf) + 0x08 != get_streamfile_size(sf))
|
||||
goto fail;
|
||||
if (read_u32be(0x08,sf) != 0x41554449) /* "AUDI" */
|
||||
if (!is_id32be(0x08,sf, "AUDI"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "nus3audio"))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* parse existing chunks */
|
||||
{
|
||||
off_t offset = 0x0c;
|
||||
size_t file_size = get_streamfile_size(sf);
|
||||
uint32_t offset = 0x0c;
|
||||
uint32_t file_size = get_streamfile_size(sf);
|
||||
uint32_t codec_id = 0;
|
||||
|
||||
total_subsongs = 0;
|
||||
|
||||
while (offset < file_size) {
|
||||
uint32_t chunk_id = read_u32be(offset+0x00, sf);
|
||||
size_t chunk_size = read_u32le(offset+0x04, sf);
|
||||
uint32_t chunk_type = read_u32be(offset+0x00, sf);
|
||||
uint32_t chunk_size = read_u32le(offset+0x04, sf);
|
||||
|
||||
switch(chunk_id) {
|
||||
switch(chunk_type) {
|
||||
case 0x494E4458: /* "INDX": audio index */
|
||||
total_subsongs = read_u32le(offset+0x08 + 0x00,sf);
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
|
@ -70,8 +70,8 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
|||
goto fail;
|
||||
}
|
||||
|
||||
/* handle dummy entries, ex. Gundam EvM (PS4) */
|
||||
if (subfile_offset == 0 && subfile_size == 0) {
|
||||
/* handle dummy entries (offset may be 0 or first entry), ex. Gundam EvM (PS4) */
|
||||
if (subfile_size == 0) {
|
||||
vgmstream = init_vgmstream_silence(0, 0, 0);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
|
@ -96,8 +96,12 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
|||
codec = RIFF;
|
||||
fake_ext = "wav";
|
||||
break;
|
||||
case 0x424E5346: /* "BNSF" [gundam Extreme Vs 2 (AC)-multichannel] */
|
||||
codec = BNSF;
|
||||
fake_ext = "bnsf";
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("NUS3AUDIO: unknown codec %x\n", codec_id);
|
||||
vgm_logi("NUS3AUDIO: unknown codec (report)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
@ -120,6 +124,10 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
|||
vgmstream = init_vgmstream_riff(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case BNSF:
|
||||
vgmstream = init_vgmstream_bnsf(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
@ -136,5 +144,3 @@ fail:
|
|||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ VGMSTREAM* init_vgmstream_mic_koei(STREAMFILE* sf) {
|
|||
channels = read_u32le(0x08,sf);
|
||||
if (channels > 4) goto fail; /* 1/2/4 are known */
|
||||
interleave = read_u32le(0x0c,sf);
|
||||
if (interleave != 0x10) goto fail;
|
||||
if (interleave != 0x10 && interleave != 0x20) goto fail;
|
||||
|
||||
loop_end = read_s32le(0x10,sf);
|
||||
loop_start = read_s32le(0x14,sf);
|
||||
|
|
|
@ -1,28 +1,150 @@
|
|||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* RFTM - Retro Studios format [Metroid Prime Remastered] */
|
||||
static VGMSTREAM* init_vgmstream_rfrm_mpr(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t fmta_offset = 0, data_offset = 0, ras3_offset = 0, header_offset, start_offset;
|
||||
size_t data_size = 0, interleave;
|
||||
int loop_flag, channels;
|
||||
int loop_start, loop_end, padding;
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "RFRM"))
|
||||
goto fail;
|
||||
/* 0x08: file size but not exact */
|
||||
if (!is_id32be(0x14, sf, "CSMP"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "csmp"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitLE(0x18,sf) != 0x1F) /* assumed, also at 0x1c */
|
||||
goto fail;
|
||||
|
||||
|
||||
/* parse chunks (always BE) */
|
||||
{
|
||||
off_t chunk_offset = 0x20;
|
||||
off_t file_size = get_streamfile_size(sf);
|
||||
|
||||
while (chunk_offset < file_size) {
|
||||
uint32_t chunk_type = read_32bitBE(chunk_offset + 0x00,sf);
|
||||
size_t chunk_size = read_32bitLE(chunk_offset + 0x08,sf);
|
||||
|
||||
switch(chunk_type) {
|
||||
case 0x464D5441: /* "FMTA" */
|
||||
fmta_offset = chunk_offset + 0x18;
|
||||
chunk_offset += 5 + 0x18 + chunk_size;
|
||||
break;
|
||||
case 0x44415441: /* "DATA" */
|
||||
data_offset = chunk_offset + 0x18;
|
||||
data_size = read_32bitLE(chunk_offset + 0x04, sf);
|
||||
/* we're done here, DATA is the last chunk */
|
||||
chunk_offset = file_size;
|
||||
break;
|
||||
case 0x52415333: /* "RAS3" */
|
||||
ras3_offset = chunk_offset + 0x18;
|
||||
chunk_offset += 60;
|
||||
break;
|
||||
case 0x43524D53: /* CRMS */
|
||||
chunk_offset += 9 + 0x18 + chunk_size + read_32bitLE(chunk_offset + 0x18 + chunk_size + 5, sf);
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fmta_offset || !data_offset || !data_size)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
/* parse FMTA / DATA (fully interleaved standard DSPs) */
|
||||
channels = read_8bit(fmta_offset + 0x00, sf);
|
||||
if (channels == 0) goto fail; /* div by zero */
|
||||
/* FMTA 0x08: channel mapping */
|
||||
|
||||
header_offset = data_offset;
|
||||
start_offset = header_offset + 0x80 * channels;
|
||||
loop_flag = read_16bitLE(header_offset + 0x0C, sf);
|
||||
interleave = data_size / channels;
|
||||
|
||||
if (ras3_offset) {
|
||||
int block_size = read_32bitLE(ras3_offset + 0x00, sf);
|
||||
int block_samples = read_32bitLE(ras3_offset + 0x8, sf);
|
||||
int loop_start_block = read_32bitLE(ras3_offset + 0x14, sf);
|
||||
int loop_start_sample = read_32bitLE(ras3_offset + 0x18, sf);
|
||||
int loop_end_block = read_32bitLE(ras3_offset + 0x1C, sf);
|
||||
int loop_end_sample = read_32bitLE(ras3_offset + 0x20, sf);
|
||||
padding = read_32bitLE(ras3_offset + 0x0C, sf);
|
||||
|
||||
loop_start = loop_start_block * block_samples + loop_start_sample - padding;
|
||||
loop_end = loop_end_block * block_samples + loop_end_sample - padding;
|
||||
if ((loop_start || loop_end) && (loop_start < loop_end))
|
||||
loop_flag = 1;
|
||||
|
||||
interleave = block_size / channels;
|
||||
} else {
|
||||
loop_start = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x10, sf));
|
||||
loop_end = dsp_nibbles_to_samples(read_32bitLE(header_offset + 0x14, sf)) + 1;
|
||||
}
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_RFRM;
|
||||
vgmstream->sample_rate = read_32bitLE(header_offset + 0x08, sf);
|
||||
vgmstream->num_samples = read_32bitLE(header_offset + 0x00, sf);
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
if (ras3_offset) {
|
||||
int padding_bytes = padding / 14 * 8; /* round to frames */
|
||||
vgmstream->interleave_first_block_size = interleave - padding_bytes;
|
||||
vgmstream->interleave_first_skip = padding_bytes;
|
||||
start_offset += padding_bytes;
|
||||
}
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
dsp_read_coefs(vgmstream, sf, header_offset + 0x1C, 0x80, 0);
|
||||
dsp_read_hist (vgmstream, sf, header_offset + 0x40, 0x80, 0);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* RFTM - Retro Studios format [Donkey Kong Country Tropical Freeze (WiiU/Switch)] */
|
||||
VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
|
||||
VGMSTREAM* init_vgmstream_rfrm(STREAMFILE* sf) {
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
off_t fmta_offset = 0, data_offset = 0, header_offset, start_offset;
|
||||
size_t data_size = 0, interleave;
|
||||
int loop_flag, channel_count, version;
|
||||
int loop_flag, channels, version;
|
||||
int big_endian;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "csmp"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00, streamFile) != 0x5246524D) /* "RFRM" */
|
||||
if (!is_id32be(0x00, sf, "RFRM"))
|
||||
goto fail;
|
||||
/* 0x08: file size but not exact */
|
||||
if (read_32bitBE(0x14, streamFile) != 0x43534D50) /* "CSMP" */
|
||||
if (!is_id32be(0x14, sf, "CSMP"))
|
||||
goto fail;
|
||||
version = read_32bitBE(0x18,streamFile); /* assumed, also at 0x1c */
|
||||
|
||||
if (!check_extensions(sf, "csmp"))
|
||||
goto fail;
|
||||
|
||||
version = read_32bitBE(0x18,sf); /* assumed, also at 0x1c */
|
||||
if (version == 0x0a) { /* Wii U */
|
||||
read_32bit = read_32bitBE;
|
||||
read_16bit = read_16bitBE;
|
||||
|
@ -33,6 +155,9 @@ VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
|
|||
read_16bit = read_16bitLE;
|
||||
big_endian = 0;
|
||||
}
|
||||
else if (version == 0x1F000000) { /* Metroid Prime Remastered */
|
||||
return init_vgmstream_rfrm_mpr(sf);
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -41,11 +166,11 @@ VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
|
|||
/* parse chunks (always BE) */
|
||||
{
|
||||
off_t chunk_offset = 0x20;
|
||||
off_t file_size = get_streamfile_size(streamFile);
|
||||
off_t file_size = get_streamfile_size(sf);
|
||||
|
||||
while (chunk_offset < file_size) {
|
||||
uint32_t chunk_type = read_32bitBE(chunk_offset+0x00,streamFile);
|
||||
size_t chunk_size = read_32bitBE(chunk_offset+0x08,streamFile); /* maybe 64b from 0x04? */
|
||||
uint32_t chunk_type = read_32bitBE(chunk_offset+0x00,sf);
|
||||
size_t chunk_size = read_32bitBE(chunk_offset+0x08,sf); /* maybe 64b from 0x04? */
|
||||
|
||||
switch(chunk_type) {
|
||||
case 0x464D5441: /* "FMTA" */
|
||||
|
@ -68,7 +193,7 @@ VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
|
|||
|
||||
|
||||
/* parse FMTA / DATA (fully interleaved standard DSPs) */
|
||||
channel_count = read_8bit(fmta_offset+0x00, streamFile);
|
||||
channels = read_8bit(fmta_offset+0x00, sf);
|
||||
/* FMTA 0x08: channel mapping */
|
||||
|
||||
header_offset = data_offset;
|
||||
|
@ -78,29 +203,29 @@ VGMSTREAM *init_vgmstream_rfrm(STREAMFILE *streamFile) {
|
|||
data_size -= align;
|
||||
}
|
||||
start_offset = header_offset + 0x60;
|
||||
loop_flag = read_16bit(header_offset + 0x0C, streamFile);
|
||||
interleave = data_size / channel_count;
|
||||
loop_flag = read_16bit(header_offset + 0x0C, sf);
|
||||
interleave = data_size / channels;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_RFRM;
|
||||
vgmstream->sample_rate = read_32bit(header_offset + 0x08, streamFile);
|
||||
vgmstream->num_samples = read_32bit(header_offset + 0x00, streamFile);
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x10, streamFile));
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x14, streamFile)) + 1;
|
||||
vgmstream->sample_rate = read_32bit(header_offset + 0x08, sf);
|
||||
vgmstream->num_samples = read_32bit(header_offset + 0x00, sf);
|
||||
vgmstream->loop_start_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x10, sf));
|
||||
vgmstream->loop_end_sample = dsp_nibbles_to_samples(read_32bit(header_offset + 0x14, sf)) + 1;
|
||||
if (vgmstream->loop_end_sample > vgmstream->num_samples) /* ? */
|
||||
vgmstream->loop_end_sample = vgmstream->num_samples;
|
||||
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
dsp_read_coefs(vgmstream, streamFile, header_offset + 0x1C, interleave, big_endian);
|
||||
dsp_read_hist (vgmstream, streamFile, header_offset + 0x40, interleave, big_endian);
|
||||
dsp_read_coefs(vgmstream, sf, header_offset + 0x1C, interleave, big_endian);
|
||||
dsp_read_hist (vgmstream, sf, header_offset + 0x40, interleave, big_endian);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream, streamFile, start_offset))
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
|
|
|
@ -378,8 +378,9 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
|||
* .p1d: Farming Simulator 15 (Vita)[ATRAC9]
|
||||
* .xms: Ty the Tasmanian Tiger (Xbox)
|
||||
* .mus: Burnout Legends/Dominator (PSP)
|
||||
* .dat/ldat: RollerCoaster Tycoon 1/2 (PC)
|
||||
*/
|
||||
if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus")) {
|
||||
if (!check_extensions(sf, "wav,lwav,xwav,mwv,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw,wd,,sbv,wvx,str,at3,rws,aud,at9,ckd,saf,ima,nsa,pcm,xvag,ogg,logg,p1d,xms,mus,dat,ldat")) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
|
|
@ -126,6 +126,17 @@ VGMSTREAM* init_vgmstream_sdrh_new(STREAMFILE* sf) {
|
|||
|
||||
break;
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
case 5: { /* No More Heroes (PS3) (rare, BAITO_GOMIHORI.XSE) */
|
||||
mpeg_custom_config cfg = {0};
|
||||
cfg.data_size = stream_size;
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_STANDARD, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
case 1: { /* Mindjack (X360), Moon Diver (X360) */
|
||||
int block_size = 0x10000; /* XWAV new default */
|
||||
|
@ -145,10 +156,15 @@ VGMSTREAM* init_vgmstream_sdrh_new(STREAMFILE* sf) {
|
|||
break;
|
||||
}
|
||||
|
||||
case 7: { /* Mindjack (PS3) */
|
||||
case 6: /* No More Heroes (PS3) */
|
||||
case 7: /* No More Heroes (PS3), Mindjack (PS3) */
|
||||
case 8: { /* No More Heroes (PS3) */
|
||||
int block_align, encoder_delay;
|
||||
|
||||
block_align = 0x98 * vgmstream->channels;
|
||||
/* fixed for all rates? doesn't happen with other codecs, some files are 48000 already */
|
||||
vgmstream->sample_rate = 48000;
|
||||
|
||||
block_align = (codec == 8 ? 0xC0 : codec == 0x07 ? 0x98 : 0x60) * vgmstream->channels;
|
||||
encoder_delay = 1024 + 69*2; /* observed default, but seems files run out of space */
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset, stream_size, vgmstream->num_samples, vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||
|
|
|
@ -1,105 +1,53 @@
|
|||
#include "meta.h"
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
static bool get_loops(STREAMFILE* sf, int32_t* p_loop_start, int32_t* p_loop_end);
|
||||
|
||||
/* .sli+ogg/opus - KiriKiri engine / WaveLoopManager loop points loader [Fate/Stay Night (PC), World End Economica (PC)] */
|
||||
VGMSTREAM* init_vgmstream_sli_ogg(STREAMFILE* sf) {
|
||||
/* .sli+ogg/opus/wav - KiriKiri engine / WaveLoopManager loop points loader [Fate/Stay Night (PC), World End Economica (PC)] */
|
||||
VGMSTREAM* init_vgmstream_sli_loops(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* sf_data = NULL;
|
||||
int32_t loop_start = -1, loop_length = -1;
|
||||
int32_t loop_from = -1, loop_to = -1;
|
||||
int32_t loop_start = 0, loop_end = 0;
|
||||
VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL;
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "sli"))
|
||||
goto fail;
|
||||
|
||||
{
|
||||
/* try with file.ogg/opus.sli=header and file.ogg/opus=data */
|
||||
/* try with file.ogg/opus/wav.sli=header and file.ogg/opus/wav=data */
|
||||
char basename[PATH_LIMIT];
|
||||
get_streamfile_basename(sf,basename,PATH_LIMIT);
|
||||
sf_data = open_streamfile_by_filename(sf, basename);
|
||||
if (!sf_data) goto fail;
|
||||
}
|
||||
|
||||
if (!is_id32be(0x00, sf_data, "OggS"))
|
||||
goto fail;
|
||||
|
||||
/* let the real initer do the parsing */
|
||||
if (is_id32be(0x1c, sf_data, "Opus")) { /* Sabbat of the Witch (PC) */
|
||||
vgmstream = init_vgmstream_ogg_opus(sf_data);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
/* somehow sli+opus use 0 encoder delay in the OpusHead (to simplify looping?) */
|
||||
vgmstream->meta_type = meta_OPUS_SLI;
|
||||
}
|
||||
else { /* Fate/Stay Night (PC) */
|
||||
vgmstream = init_vgmstream_ogg_vorbis(sf_data);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_OGG_SLI;
|
||||
}
|
||||
|
||||
|
||||
/* find loop text */
|
||||
{
|
||||
char line[PATH_LIMIT];
|
||||
size_t bytes_read;
|
||||
off_t sli_offset;
|
||||
int line_ok;
|
||||
|
||||
sli_offset = 0;
|
||||
while ((loop_start == -1 || loop_length == -1) && sli_offset < get_streamfile_size(sf)) {
|
||||
char *endptr, *foundptr;
|
||||
|
||||
bytes_read = read_line(line, sizeof(line), sli_offset, sf, &line_ok);
|
||||
if (!line_ok) goto fail;
|
||||
sli_offset += bytes_read;
|
||||
/* files may be padded with 0s */
|
||||
|
||||
/* comments in v2.0 [Sabbath of the Witch (PC), KARAKARA (PC)] */
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if (memcmp("LoopStart=", line,10) == 0 && line[10] != '\0') {
|
||||
loop_start = strtol(line + 10, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
loop_start = -1; /* if it didn't parse cleanly */
|
||||
}
|
||||
}
|
||||
else if (memcmp("LoopLength=", line, 11) == 0 && line[11] != '\0') {
|
||||
loop_length = strtol(line + 11, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
loop_length = -1; /* if it didn't parse cleanly */
|
||||
}
|
||||
}
|
||||
|
||||
/* a completely different format ("#2.00"?), can be handled similarly */
|
||||
if ((foundptr = strstr(line,"To=")) != NULL && isdigit(foundptr[3])) {
|
||||
loop_to = strtol(foundptr + 3, &endptr, 10);
|
||||
if (*endptr != ';') {
|
||||
loop_to = -1;
|
||||
}
|
||||
}
|
||||
if ((foundptr = strstr(line,"From=")) != NULL && isdigit(foundptr[5])) {
|
||||
loop_from = strtol(foundptr + 5, &endptr, 10);
|
||||
if (*endptr != ';') {
|
||||
loop_from = -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_id32be(0x00, sf_data, "OggS")) {
|
||||
if (is_id32be(0x1c, sf_data, "Opus")) { /* Sabbat of the Witch (PC) */
|
||||
init_vgmstream = init_vgmstream_ogg_opus;
|
||||
/* somehow sli+opus use 0 encoder delay in the OpusHead (to simplify looping?) */
|
||||
}
|
||||
else { /* Fate/Stay Night (PC) */
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
}
|
||||
}
|
||||
|
||||
if (loop_start != -1 && loop_length != -1) { /* v1 */
|
||||
vgmstream_force_loop(vgmstream, 1, loop_start, loop_start + loop_length);
|
||||
}
|
||||
else if (loop_from != -1 && loop_to != -1) { /* v2 */
|
||||
vgmstream_force_loop(vgmstream, 1, loop_to, loop_from);
|
||||
else if (is_id32be(0x00, sf_data, "RIFF")) {
|
||||
/* Perfect Cherry Blossom Trial+ (PC) (RIFF created by extractor?) */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
}
|
||||
else {
|
||||
goto fail; /* if there's no loop points the .sli wasn't valid */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vgmstream = init_vgmstream(sf_data);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
if (!get_loops(sf, &loop_start, &loop_end))
|
||||
goto fail;
|
||||
|
||||
vgmstream_force_loop(vgmstream, 1, loop_start, loop_end);
|
||||
|
||||
close_streamfile(sf_data);
|
||||
return vgmstream;
|
||||
|
||||
|
@ -108,3 +56,71 @@ fail:
|
|||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool get_loops(STREAMFILE* sf, int32_t* p_loop_start, int32_t* p_loop_end) {
|
||||
int32_t loop_start = -1, loop_length = -1;
|
||||
int32_t loop_from = -1, loop_to = -1;
|
||||
|
||||
char line[PATH_LIMIT];
|
||||
size_t bytes_read;
|
||||
off_t sli_offset;
|
||||
int line_ok;
|
||||
|
||||
sli_offset = 0;
|
||||
while ((loop_start == -1 || loop_length == -1) && sli_offset < get_streamfile_size(sf)) {
|
||||
char *endptr, *foundptr;
|
||||
|
||||
bytes_read = read_line(line, sizeof(line), sli_offset, sf, &line_ok);
|
||||
if (!line_ok) goto fail;
|
||||
sli_offset += bytes_read;
|
||||
/* files may be padded with 0s */
|
||||
|
||||
/* comments in v2.0 [Sabbath of the Witch (PC), KARAKARA (PC)] */
|
||||
if (line[0] == '#')
|
||||
continue;
|
||||
|
||||
if (memcmp("LoopStart=", line,10) == 0 && line[10] != '\0') {
|
||||
loop_start = strtol(line + 10, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
loop_start = -1; /* if it didn't parse cleanly */
|
||||
}
|
||||
}
|
||||
else if (memcmp("LoopLength=", line, 11) == 0 && line[11] != '\0') {
|
||||
loop_length = strtol(line + 11, &endptr, 10);
|
||||
if (*endptr != '\0') {
|
||||
loop_length = -1; /* if it didn't parse cleanly */
|
||||
}
|
||||
}
|
||||
|
||||
/* a completely different format ("#2.00"?), can be handled similarly */
|
||||
if ((foundptr = strstr(line,"To=")) != NULL && isdigit(foundptr[3])) {
|
||||
loop_to = strtol(foundptr + 3, &endptr, 10);
|
||||
if (*endptr != ';') {
|
||||
loop_to = -1;
|
||||
}
|
||||
}
|
||||
if ((foundptr = strstr(line,"From=")) != NULL && isdigit(foundptr[5])) {
|
||||
loop_from = strtol(foundptr + 5, &endptr, 10);
|
||||
if (*endptr != ';') {
|
||||
loop_from = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (loop_start != -1 && loop_length != -1) { /* v1 */
|
||||
*p_loop_start = loop_start;
|
||||
*p_loop_end = loop_start + loop_length;
|
||||
}
|
||||
else if (loop_from != -1 && loop_to != -1) { /* v2 */
|
||||
*p_loop_start = loop_to;
|
||||
*p_loop_end = loop_from;
|
||||
}
|
||||
else {
|
||||
goto fail; /* if there's no loop points the .sli wasn't valid */
|
||||
}
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,8 @@ VGMSTREAM* init_vgmstream_swav(STREAMFILE* sf) {
|
|||
if (!is_id32be(0x00,sf, "SWAV"))
|
||||
goto fail;
|
||||
|
||||
/* .swav: standard
|
||||
* .adpcm: Merlin - A Servant of Two Masters (DS) */
|
||||
/* .swav: standard [found inside .sdat but SDK can create them]
|
||||
* .adpcm: Merlin - A Servant of Two Masters (DS) [external] */
|
||||
if (!check_extensions(sf, "swav,adpcm"))
|
||||
goto fail;
|
||||
|
||||
|
|
|
@ -56,6 +56,10 @@ VGMSTREAM* init_vgmstream_ubi_ckd(STREAMFILE* sf) {
|
|||
} else if (find_chunk_be(sf, 0x6461744C,first_offset,0, &chunk_offset,&chunk_size)) { /* "datL" */
|
||||
/* mono "datL" or full interleave with a "datR" after the "datL" (no check, pretend it exists) */
|
||||
start_offset = chunk_offset;
|
||||
|
||||
/* chunks follow RIFF's spec of "odd sizes treated as even" [Rayman Origins (Wii)-420_hud~sfx_endofmap_discoloop.wav.ckd] */
|
||||
if (chunk_size % 0x02 != 0)
|
||||
chunk_size += 0x01;
|
||||
data_size = chunk_size * channels;
|
||||
interleave = (0x4+0x4) + chunk_size; /* don't forget to skip the "datR"+size chunk */
|
||||
} else {
|
||||
|
|
|
@ -250,8 +250,8 @@ static int parse_header(ubi_hx_header* hx, STREAMFILE* sf, uint32_t offset, uint
|
|||
read_u32_t read_u32 = hx->big_endian ? read_u32be : read_u32le;
|
||||
read_s32_t read_s32 = hx->big_endian ? read_s32be : read_s32le;
|
||||
read_u16_t read_u16 = hx->big_endian ? read_u16be : read_u16le;
|
||||
off_t riff_offset, riff_size, chunk_offset, stream_adjust = 0, resource_size;
|
||||
size_t chunk_size;
|
||||
uint32_t riff_offset, riff_size, stream_adjust = 0, resource_size, chunk_size;
|
||||
off_t chunk_offset;
|
||||
int cue_flag = 0;
|
||||
|
||||
//todo cleanup/unify common readings
|
||||
|
@ -339,7 +339,7 @@ static int parse_header(ubi_hx_header* hx, STREAMFILE* sf, uint32_t offset, uint
|
|||
break;
|
||||
|
||||
default:
|
||||
VGM_LOG("ubi hx: unknown stream mode %x\n", hx->stream_mode);
|
||||
VGM_LOG("ubi hx: unknown wave mode %x\n", hx->stream_mode);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
@ -423,14 +423,28 @@ static int parse_header(ubi_hx_header* hx, STREAMFILE* sf, uint32_t offset, uint
|
|||
if ((strcmp(hx->class_name, "CXBoxStaticHWWaveFileIdObj") == 0 ||
|
||||
strcmp(hx->class_name, "CXBoxStreamHWWaveFileIdObj") == 0) && !hx->big_endian) {
|
||||
/* micro header: some mix of channels + block size + sample rate + flags, unsure of which bits */
|
||||
hx->codec = XIMA;
|
||||
|
||||
/* 0x00: ? */
|
||||
hx->channels = read_u8(offset + 0x01, sf); /* upper 2 bits? */
|
||||
switch(hx->channels) {
|
||||
case 0x48: hx->channels = 1; break;
|
||||
case 0x90: hx->channels = 2; break;
|
||||
uint8_t flags = read_u8(offset + 0x01, sf);
|
||||
switch(flags) {
|
||||
case 0x05: // b00000101 /* XIII (Xbox)-beta 2002-12 */
|
||||
hx->channels = 1;
|
||||
hx->codec = PCM;
|
||||
break;
|
||||
case 0x09: // b00001001 /* XIII (Xbox)-beta 2002-12 */
|
||||
hx->channels = 2;
|
||||
hx->codec = PCM;
|
||||
break;
|
||||
case 0x48: // b01001000
|
||||
hx->channels = 1;
|
||||
hx->codec = XIMA;
|
||||
break;
|
||||
case 0x90: // b10010000
|
||||
hx->channels = 2;
|
||||
hx->codec = XIMA;
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("ubi hx: channel type %x\n", hx->channels);
|
||||
VGM_LOG("ubi hx: channel flags %x\n", flags);
|
||||
goto fail;
|
||||
}
|
||||
hx->sample_rate = (read_u16(offset + 0x02, sf) & 0x7FFFu) << 1u; /* ??? */
|
||||
|
@ -473,6 +487,7 @@ static int parse_header(ubi_hx_header* hx, STREAMFILE* sf, uint32_t offset, uint
|
|||
|
||||
switch(hx->stream_mode) {
|
||||
case 0x00: /* static (smaller internal file) [XIII (Xbox)] */
|
||||
case 0x02: /* static (smaller internal file) [XIII-beta (Xbox)] */
|
||||
hx->stream_offset += offset;
|
||||
break;
|
||||
|
||||
|
|
|
@ -16,8 +16,9 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) {
|
|||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "VAW3") && /* Happy Feet Two (3DS) */
|
||||
read_u32le(0x00,sf) != 0xE5B7ECFE && /* common (LE) */
|
||||
read_u32be(0x00,sf) != 0xE5B7ECFE) /* used? */
|
||||
read_u32le(0x00,sf) != 0xE5B7ECFE && /* common LE (hashed something?) */
|
||||
read_u32be(0x00,sf) != 0xE5B7ECFE &&
|
||||
read_u32be(0x00,sf) != 0xC9FB0C03) /* NDS [Lalaloopsy, Adventure Time: HIKWYSOG (DS)] */
|
||||
goto fail;
|
||||
/* 0x04: version? common=0, VAW3=2 */
|
||||
|
||||
|
@ -51,15 +52,15 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) {
|
|||
|
||||
start_offset = read_u32(0x20, sf);
|
||||
interleave = read_u32(0x24, sf); /* typically half data_size */
|
||||
extradata_offset = read_u32(0x28, sf); /* OR: extradata size (always 0x2c) */
|
||||
extradata_offset = read_u32(0x28, sf); /* always 0x2c */
|
||||
|
||||
loop_flag = (loop_start > 0);
|
||||
/* some songs (ex. Adventure Time's m_candykingdom_overworld.wave) do full loops, but there is no way
|
||||
* to tell them apart from sfx/voices, so we try to detect if it's long enough. */
|
||||
if(!loop_flag
|
||||
&& loop_start == 0 && loop_end == num_samples /* full loop */
|
||||
&& channels > 1
|
||||
&& num_samples > 20*sample_rate) { /* in seconds */
|
||||
&& (channels > 1 || (channels == 1 && start_offset <= 0x40))
|
||||
&& num_samples > 30*sample_rate) { /* in seconds */
|
||||
loop_flag = 1;
|
||||
}
|
||||
|
||||
|
@ -75,22 +76,37 @@ VGMSTREAM* init_vgmstream_wave(STREAMFILE* sf) {
|
|||
|
||||
vgmstream->meta_type = meta_WAVE;
|
||||
|
||||
/* not sure if there are other codecs but anyway */
|
||||
/* not sure if there are other codecs but anyway (based also see wave-segmented) */
|
||||
switch(codec) {
|
||||
case 0x02:
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
/* DS games use IMA, no apparent flag (could also test ID) */
|
||||
if (start_offset <= 0x40) {
|
||||
vgmstream->coding_type = coding_IMA_int;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
/* ADPCM setup: 0x20 coefs + 0x06 initial ps/hist1/hist2 + 0x06 loop ps/hist1/hist2, per channel */
|
||||
dsp_read_coefs(vgmstream, sf, extradata_offset+0x00, 0x2c, big_endian);
|
||||
dsp_read_hist(vgmstream, sf, extradata_offset+0x22, 0x2c, big_endian);
|
||||
/* extradata:
|
||||
* 0x00: base hist? (only seen 0)
|
||||
* 0x02: base step? (only seen 0)
|
||||
* 0x04: loop hist?
|
||||
* 0x06: loop step?
|
||||
*/
|
||||
}
|
||||
else {
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = interleave;
|
||||
|
||||
/* ADPCM setup: 0x20 coefs + 0x06 initial ps/hist1/hist2 + 0x06 loop ps/hist1/hist2, per channel */
|
||||
dsp_read_coefs(vgmstream, sf, extradata_offset+0x00, 0x2c, big_endian);
|
||||
dsp_read_hist(vgmstream, sf, extradata_offset+0x22, 0x2c, big_endian);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
|
|
|
@ -91,15 +91,21 @@ VGMSTREAM* init_vgmstream_xwav_new(STREAMFILE* sf) {
|
|||
break;
|
||||
}
|
||||
|
||||
case 7: { /* Moon Diver (PS3) */
|
||||
case 6: /* (used? same as SDRH) */
|
||||
case 7: /* Moon Diver (PS3) */
|
||||
case 8: { /* No More Heroes (PS3) */
|
||||
int block_align, encoder_delay;
|
||||
|
||||
data_size = read_u32be(0x54,sf);
|
||||
block_align = 0x98 * vgmstream->channels;
|
||||
/* fixed for all rates? doesn't happen with other codecs, some files are 48000 already */
|
||||
vgmstream->sample_rate = 48000;
|
||||
|
||||
block_align = (codec == 8 ? 0xC0 : codec == 0x07 ? 0x98 : 0x60) * vgmstream->channels;
|
||||
encoder_delay = 1024 + 69*2; /* observed default, matches XMA (needed as many files start with garbage) */
|
||||
|
||||
data_size = read_u32be(0x54,sf);
|
||||
vgmstream->num_samples = atrac3_bytes_to_samples(data_size, block_align) - encoder_delay; /* original samples break looping in some files otherwise */
|
||||
|
||||
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset,data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||
vgmstream->codec_data = init_ffmpeg_atrac3_raw(sf, start_offset, data_size, vgmstream->num_samples,vgmstream->channels,vgmstream->sample_rate, block_align, encoder_delay);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
|
|
@ -32,24 +32,24 @@ typedef struct {
|
|||
int version;
|
||||
|
||||
/* segments */
|
||||
off_t base_offset;
|
||||
size_t base_size;
|
||||
off_t entry_offset;
|
||||
size_t entry_size;
|
||||
off_t names_offset;
|
||||
size_t names_size;
|
||||
size_t names_entry_size;
|
||||
off_t extra_offset;
|
||||
size_t extra_size;
|
||||
off_t data_offset;
|
||||
size_t data_size;
|
||||
uint32_t base_offset;
|
||||
uint32_t base_size;
|
||||
uint32_t entry_offset;
|
||||
uint32_t entry_size;
|
||||
uint32_t names_offset;
|
||||
uint32_t names_size;
|
||||
uint32_t names_entry_size;
|
||||
uint32_t extra_offset;
|
||||
uint32_t extra_size;
|
||||
uint32_t data_offset;
|
||||
uint32_t data_size;
|
||||
|
||||
off_t stream_offset;
|
||||
size_t stream_size;
|
||||
uint32_t stream_offset;
|
||||
uint32_t stream_size;
|
||||
|
||||
uint32_t base_flags;
|
||||
size_t entry_elem_size;
|
||||
size_t entry_alignment;
|
||||
uint32_t entry_elem_size;
|
||||
uint32_t entry_alignment;
|
||||
int total_subsongs;
|
||||
|
||||
uint32_t entry_flags;
|
||||
|
@ -97,7 +97,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
|
|||
* .xna: Touhou Makukasai ~ Fantasy Danmaku Festival (PC)
|
||||
* (extensionless): Ikaruga (X360/PC), Grabbed by the Ghoulies (Xbox)
|
||||
* .bd: Fatal Frame 2 (Xbox) */
|
||||
if (!check_extensions(sf,"xwb,xna,bd"))
|
||||
if (!check_extensions(sf,"xwb,xna,bd,"))
|
||||
goto fail;
|
||||
|
||||
xwb.little_endian = is_id32be(0x00,sf, "WBND"); /* Xbox/PC */
|
||||
|
@ -362,6 +362,11 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
|
|||
/* Stardew Valley (Vita), Owlboy (PS4): standard RIFF with ATRAC9 */
|
||||
xwb.codec = ATRAC9_RIFF;
|
||||
}
|
||||
else if (xwb.version == XACT1_1_MAX && xwb.codec == WMA
|
||||
&& read_u32be(xwb.stream_offset, sf) != 0x3026B275) { /* WMA/asf tag */
|
||||
/* Jumper: Griffin's Story (X360): partial hijack (LE on X360 and early version + XMA2) */
|
||||
xwb.codec = XMA2;
|
||||
}
|
||||
|
||||
|
||||
/* test loop after the above fixes */
|
||||
|
|
|
@ -31,8 +31,11 @@ VGMSTREAM* init_vgmstream_xwma(STREAMFILE* sf) {
|
|||
if (!is_id32be(0x08,sf, "XWMA"))
|
||||
goto fail;
|
||||
/* .xwma: standard
|
||||
* .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC) */
|
||||
if (!check_extensions(sf, "xwma,xwm"))
|
||||
* .xwm: The Elder Scrolls: Skyrim (PC), Blade Arcus from Shining (PC)
|
||||
* .xma: Castle Crashers (PC)
|
||||
* .wma/lwma: BattleBlock Theater (PC)
|
||||
*/
|
||||
if (!check_extensions(sf, "xwma,xwm,xma,wma,lwma"))
|
||||
goto fail;
|
||||
|
||||
{
|
||||
|
|
|
@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||
init_vgmstream_bigrp,
|
||||
init_vgmstream_sscf_encrypted,
|
||||
init_vgmstream_s_p_sth,
|
||||
init_vgmstream_utf_ahx,
|
||||
|
||||
/* lower priority metas (no clean header identity, somewhat ambiguous, or need extension/companion file to identify) */
|
||||
init_vgmstream_scd_pcm,
|
||||
|
@ -536,7 +537,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||
init_vgmstream_mic_koei,
|
||||
init_vgmstream_seb,
|
||||
init_vgmstream_ps2_pnb,
|
||||
init_vgmstream_sli_ogg,
|
||||
init_vgmstream_sli_loops,
|
||||
init_vgmstream_tgc,
|
||||
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
|
|
|
@ -397,6 +397,7 @@
|
|||
<string>ap</string>
|
||||
<string>apc</string>
|
||||
<string>as4</string>
|
||||
<string>asbin</string>
|
||||
<string>asd</string>
|
||||
<string>asf</string>
|
||||
<string>asr</string>
|
||||
|
@ -423,6 +424,7 @@
|
|||
<string>bar</string>
|
||||
<string>bcstm</string>
|
||||
<string>bcwav</string>
|
||||
<string>bcv</string>
|
||||
<string>bd3</string>
|
||||
<string>bdsp</string>
|
||||
<string>bfstm</string>
|
||||
|
@ -435,6 +437,7 @@
|
|||
<string>bik</string>
|
||||
<string>bika</string>
|
||||
<string>bik2</string>
|
||||
<string>binka</string>
|
||||
<string>bk2</string>
|
||||
<string>bkr</string>
|
||||
<string>blk</string>
|
||||
|
@ -456,7 +459,6 @@
|
|||
<string>cads</string>
|
||||
<string>caf</string>
|
||||
<string>cbd2</string>
|
||||
<string>ccc</string>
|
||||
<string>cd</string>
|
||||
<string>cfn</string>
|
||||
<string>chd</string>
|
||||
|
@ -468,6 +470,7 @@
|
|||
<string>cpk</string>
|
||||
<string>cps</string>
|
||||
<string>csa</string>
|
||||
<string>csb</string>
|
||||
<string>csmp</string>
|
||||
<string>cvs</string>
|
||||
<string>cwav</string>
|
||||
|
@ -504,6 +507,7 @@
|
|||
<string>exa</string>
|
||||
<string>ezw</string>
|
||||
<string>fag</string>
|
||||
<string>fcb</string>
|
||||
<string>fda</string>
|
||||
<string>ffw</string>
|
||||
<string>filp</string>
|
||||
|
@ -575,6 +579,7 @@
|
|||
<string>kces</string>
|
||||
<string>kcey</string>
|
||||
<string>km9</string>
|
||||
<string>kma</string>
|
||||
<string>kmx</string>
|
||||
<string>kovs</string>
|
||||
<string>kno</string>
|
||||
|
@ -596,6 +601,7 @@
|
|||
<string>lac3</string>
|
||||
<string>lasf</string>
|
||||
<string>lbin</string>
|
||||
<string>ldat</string>
|
||||
<string>leg</string>
|
||||
<string>lep</string>
|
||||
<string>lflac</string>
|
||||
|
@ -737,7 +743,6 @@
|
|||
<string>rws</string>
|
||||
<string>rwsd</string>
|
||||
<string>rwx</string>
|
||||
<string>rxw</string>
|
||||
<string>rxx</string>
|
||||
<string>s14</string>
|
||||
<string>s3s</string>
|
||||
|
@ -796,6 +801,7 @@
|
|||
<string>smp</string>
|
||||
<string>smpl</string>
|
||||
<string>smv</string>
|
||||
<string>snb</string>
|
||||
<string>snd</string>
|
||||
<string>snds</string>
|
||||
<string>sng</string>
|
||||
|
|
Loading…
Reference in New Issue