mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-15 02:57:38 +01:00
commit
4aed59b945
94
README.md
94
README.md
@ -121,39 +121,80 @@ standard, whose docs discuss extending M3U with arbitrary tags.
|
||||
|
||||
|
||||
## Special cases
|
||||
vgmstream aims to support most file formats as-is, but some files require extra
|
||||
vgmstream aims to support most audio formats as-is, but some files require extra
|
||||
handling.
|
||||
|
||||
### Renamed files
|
||||
A few extensions that vgmstream supports clash with common ones. Since players
|
||||
like foobar or Winamp don't react well to that, they may be renamed for
|
||||
vgmstream (mainly to get looping in some cases).
|
||||
- .aac to .laac
|
||||
- .ac3 to .lac3
|
||||
- .aif to .aiffl or .aifcl
|
||||
- .asf to .sng (EA formats)
|
||||
- .flac to .lflac
|
||||
- .mp4 to .lmp4
|
||||
- .ogg to .logg
|
||||
- .opus to .lopus
|
||||
- .stm to .lstm
|
||||
- .wav to .lwav
|
||||
like foobar or Winamp don't react well to that, they may be renamed to make
|
||||
them playable through vgmstream.
|
||||
- .aac to .laac (tri-Ace games)
|
||||
- .ac3 to .lac3 (standard AC3)
|
||||
- .aif to .aiffl or .aifcl (standard Mac AIF)
|
||||
- .asf to .sng (EA games)
|
||||
- .flac to .lflac (standard FLAC)
|
||||
- .mp2 to .lmp2 (standard MP2)
|
||||
- .mp3 to .lmp3 (standard MP3)
|
||||
- .mp4 to .lmp4 (standard M4A)
|
||||
- .mpc to .lmpc (standard MPC)
|
||||
- .ogg to .logg (standard OGG)
|
||||
- .opus to .lopus (standard OPUS or Switch OPUS)
|
||||
- .stm to .lstm (Rockstar STM)
|
||||
- .wav to .lwav (standard WAV)
|
||||
- .wma to .lwma (standard WMA)
|
||||
- .(any) to .vgmstream (FFmpeg formats or TXTH)
|
||||
Command line tools don't have this restriction and will accept the original
|
||||
filename.
|
||||
|
||||
When extracting from a bigfile sometimes internal files don't have an actual
|
||||
The main advantage to rename them is that vgmstream may use the file's
|
||||
internal loop info, or apply subtle fixes, but is also limited in some ways
|
||||
(like standard/player's tagging).
|
||||
|
||||
.vgmstream is a catch-all extension that may work as a last resort to make
|
||||
a file playable.
|
||||
|
||||
When extracting from a bigfile, sometimes internal files don't have an actual
|
||||
name+extension. Those should be renamed to its proper/common extension, as the
|
||||
extractor program may guess wrong (like .wav instead of .at3 or .wem). If
|
||||
there is no known extension usually the header id is used instead.
|
||||
there is no known extension, usually the header id string may be used instead.
|
||||
|
||||
### Loop assists
|
||||
Note that vgmstream also accepts certain extension-less files too.
|
||||
|
||||
### Demuxed videos
|
||||
vgmstream also supports audio from videos, but usually must be demuxed (extracted
|
||||
without modification) first, since vgmstream doesn't attempt to support them.
|
||||
|
||||
The easiest way to do this is using VGMToolBox's "Video Demultiplexer" option
|
||||
for common game video formats (.bik, .vp6, .pss, .pam, .pmf, .usm, .xmv, etc).
|
||||
|
||||
For standard videos formats (.avi, .mp4, .webm, .m2v, .ogv, etc) not supported
|
||||
by VGMToolBox FFmpeg binary may work:
|
||||
- `ffmpeg.exe -i (input file) -vn -acodec copy (output file)`
|
||||
Output extension may need to be adjusted to some appropriate audio file depending
|
||||
on the audio codec used. ffprobe.exe can list this codec, though the correct audio
|
||||
extension depends on the video itself (like .avi to .wav/mp2/mp3 or .ogv to .ogg).
|
||||
|
||||
Some games use custom video formats, demuxer scripts in .bms format may be found
|
||||
on the internet.
|
||||
|
||||
### Companion files
|
||||
Some formats have companion files with external looping info, and should be
|
||||
left together.
|
||||
- .mus (playlist for .acm)
|
||||
- .pos (loop info for .wav: 32 bit LE loop start sample + loop end sample)
|
||||
- .sli (loop info for .ogg)
|
||||
- .sfl (loop info for .ogg)
|
||||
- .vgmstream + .pos (FFmpeg formats + loop assist)
|
||||
- .pos (loop info for .wav, and sometimes .ogg)
|
||||
- .ogg.sli or .sli (loop info for .ogg)
|
||||
- .ogg.sfl (loop info for .ogg)
|
||||
- .vgmstream.pos (loop info for FFmpeg formats)
|
||||
- also possible for certain extensions like .lflac.pos
|
||||
|
||||
Similarly some formats split header and/or data in separate files (.sgh+sgd,
|
||||
.wav.str+.wav, (file)_L.dsp+(file)_R.dsp, etc). vgmstream will also detect
|
||||
and use those as needed and must be tegether, even if only one of the two
|
||||
will be used to play.
|
||||
|
||||
.pos is a small file with 32 bit little endian values: loop start sample
|
||||
and loop end sample. For FFmpeg formats (.vgmstream.pos) it may optionally
|
||||
have total samples after those.
|
||||
|
||||
### Decryption keys
|
||||
Certain formats have encrypted data, and need a key to decrypt. vgmstream
|
||||
@ -162,7 +203,7 @@ a companion file:
|
||||
- .adx: .adxkey (derived 6 byte key, in start/mult/add format)
|
||||
- .ahx: .ahxkey (derived 6 byte key, in start/mult/add format)
|
||||
- .hca: .hcakey (8 byte decryption key, a 64-bit number)
|
||||
- May be followed by 2 byte AWB derivation value for newer HCA
|
||||
- May be followed by 2 byte AWB scramble key for newer HCA
|
||||
- .fsb: .fsbkey (decryption key, in hex)
|
||||
|
||||
The key file can be ".(ext)key" (for the whole folder), or "(name).(ext)key"
|
||||
@ -182,11 +223,14 @@ Programs like VGMToolbox can help to create GENH.
|
||||
".txth" or ".(ext).txth" (for the whole folder), or "(name.ext).txth" (for a
|
||||
single file). Contains dynamic text commands to read data from the original
|
||||
file, or static values.
|
||||
|
||||
|
||||
**TXTP**: a text playlist that works as a single song. Can contain a list of
|
||||
filenames to play as one (ex. "intro.vag" "loop.vag"), name with subsong index
|
||||
(ex. bgm.sxd#10), or mask channels to only play some (ex. "song.adx#c1,2").
|
||||
|
||||
Creation of those files is meant for advanced users, docs can be found in
|
||||
vgmstream source.
|
||||
|
||||
|
||||
## Supported codec types
|
||||
Quick list of codecs vgmstream supports, including many obscure ones that
|
||||
@ -241,7 +285,7 @@ are used in few games.
|
||||
- AAC
|
||||
- Bink
|
||||
- AC3/SPDIF
|
||||
- Xiph Opus (Ogg, Switch, EA, UE4)
|
||||
- Xiph Opus (Ogg, Switch, EA, UE4, Exient)
|
||||
- Xiph CELT (FSB)
|
||||
- Musepack
|
||||
- FLAC
|
||||
@ -250,7 +294,7 @@ are used in few games.
|
||||
Note that vgmstream doesn't (can't) reproduce in-game music 1:1, as internal
|
||||
resampling, filters, volume, etc, are not replicated. Some codecs are not
|
||||
fully accurate compared to the games due to minor bugs, but in most cases
|
||||
it isn't audible.
|
||||
it isn't audible.
|
||||
|
||||
|
||||
## Supported file types
|
||||
@ -494,6 +538,6 @@ This list is not complete and many other files are supported.
|
||||
- .ahxkey (decryption key for .ahx, in start/mult/add format)
|
||||
- .hcakey (decryption key for .hca, in HCA Decoder format)
|
||||
- .fsbkey (decryption key for .fsb, in hex)
|
||||
- .vgmstream + .pos (FFmpeg formats + loop assist)
|
||||
- .vgmstream + .vgmstream.pos (FFmpeg formats + loop assist)
|
||||
|
||||
Enjoy! *hcs*
|
||||
|
@ -288,7 +288,6 @@ size_t switch_opus_get_samples(off_t offset, size_t data_size, STREAMFILE *strea
|
||||
size_t switch_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
|
||||
size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
|
||||
size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
|
||||
size_t x_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -594,9 +594,6 @@ size_t ue4_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) {
|
||||
size_t ea_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) {
|
||||
return custom_opus_get_encoder_delay(offset, streamFile, OPUS_EA);
|
||||
}
|
||||
size_t x_opus_get_encoder_delay(off_t offset, STREAMFILE *streamFile) {
|
||||
return custom_opus_get_encoder_delay(offset, streamFile, OPUS_X);
|
||||
}
|
||||
|
||||
|
||||
static size_t get_xopus_packet_size(int packet, STREAMFILE * streamfile) {
|
||||
|
@ -1,11 +1,13 @@
|
||||
#include "vgmstream.h"
|
||||
|
||||
|
||||
/* defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
|
||||
/* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
|
||||
* to inform plugins that need it. Common extensions are commented out to avoid stealing them. */
|
||||
|
||||
/* some extensions require external libraries and could be #ifdef, not really needed */
|
||||
/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */
|
||||
/* Some extensions require external libraries and could be #ifdef, not worth. */
|
||||
|
||||
/* Formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension isn't
|
||||
* parsed by vgmstream and typically won't not be fully accurate. May have a .ext.pos pair for fun. */
|
||||
|
||||
|
||||
static const char* extension_list[] = {
|
||||
@ -16,20 +18,21 @@ static const char* extension_list[] = {
|
||||
"2pfs",
|
||||
"800",
|
||||
|
||||
//"aac", //common, also tri-Ace's
|
||||
"aa3", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||
//"aac", //common
|
||||
"aa3", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||
"aaap",
|
||||
"aax",
|
||||
"abk",
|
||||
//"ac3", //FFmpeg, not parsed //common?
|
||||
"ace", //fake, for tri-Ace's formats (to be removed)
|
||||
//"ac3", //common, FFmpeg/not parsed (AC3)
|
||||
"ace", //fake extension for tri-Ace's .aac (renamed, to be removed)
|
||||
"acm",
|
||||
"ad", //txth/reserved [Xenosaga Freaks (PS2)]
|
||||
"adc", //txth/reserved [Tomb Raider The Last Revelation(DC), Tomb Raider Chronicles(DC)]
|
||||
"adc", //txth/reserved [Tomb Raider The Last Revelation (DC), Tomb Raider Chronicles (DC)]
|
||||
"adm",
|
||||
"adp",
|
||||
"adpcm",
|
||||
"ads",
|
||||
"adw",
|
||||
"adx",
|
||||
"afc",
|
||||
"agsc",
|
||||
@ -38,13 +41,13 @@ static const char* extension_list[] = {
|
||||
"ai",
|
||||
//"aif", //common
|
||||
"aifc", //common?
|
||||
"aifcl", //fake extension, for AIF???
|
||||
"aifcl", //fake extension for .aif???
|
||||
//"aiff", //common
|
||||
"aiffl", //fake extension, for AIF???
|
||||
"aiffl", //fake extension for .aif???
|
||||
"aix",
|
||||
"akb",
|
||||
"al2",
|
||||
"amts", //fake extension/header id for .stm (to be removed)
|
||||
"amts", //fake extension/header id for .stm (renamed? to be removed?)
|
||||
"ao",
|
||||
"apc",
|
||||
"as4",
|
||||
@ -73,7 +76,7 @@ static const char* extension_list[] = {
|
||||
"bdsp",
|
||||
"bfstm",
|
||||
"bfwav",
|
||||
"bfwavnsmbu",
|
||||
"bfwavnsmbu", //fake extension for New Super Smash Bros U (renamed to fix bug)
|
||||
"bg00",
|
||||
"bgm",
|
||||
"bgw",
|
||||
@ -98,7 +101,7 @@ static const char* extension_list[] = {
|
||||
"cbd2",
|
||||
"ccc",
|
||||
"cd",
|
||||
"cfn", //fake extension/header id for .caf (to be removed)
|
||||
"cfn", //fake extension for CAF (renamed, to be removed?)
|
||||
"ckb",
|
||||
"ckd",
|
||||
"cks",
|
||||
@ -133,6 +136,7 @@ static const char* extension_list[] = {
|
||||
"fag",
|
||||
"ffw",
|
||||
"filp",
|
||||
//"flac", //common
|
||||
"flx",
|
||||
"fsb",
|
||||
"fsv",
|
||||
@ -163,7 +167,7 @@ static const char* extension_list[] = {
|
||||
"iab",
|
||||
"iadp",
|
||||
"idsp",
|
||||
"idvi", //fake extension for .pcm (to be removed)
|
||||
"idvi", //fake extension/header id for .pcm (renamed, to be removed)
|
||||
"idx",
|
||||
"ikm",
|
||||
"ild",
|
||||
@ -180,30 +184,34 @@ static const char* extension_list[] = {
|
||||
"jstm",
|
||||
|
||||
"kces",
|
||||
"kcey", //fake extension/header id (to be removed)
|
||||
"kcey", //fake extension/header id for .pcm (renamed, to be removed)
|
||||
"khv",
|
||||
"km9",
|
||||
"kovs", //.kvs header id
|
||||
"kovs", //fake extension/header id for .kvs
|
||||
"kns",
|
||||
"kraw",
|
||||
"ktss", //.kns header id
|
||||
"ktss", //fake extension/header id for .kns
|
||||
"kvs",
|
||||
|
||||
"l",
|
||||
"laac", //fake extension, for AAC (tri-Ace/FFmpeg)
|
||||
"lac3", //fake extension, for AC3
|
||||
"laac", //fake extension for .aac (tri-Ace)
|
||||
"lac3", //fake extension for .ac3, FFmpeg/not parsed
|
||||
"leg",
|
||||
"lflac", //fake extension, FFmpeg, not parsed, use with .pos pair for fun
|
||||
"lmp4", //fake extension, for MP4s
|
||||
"logg", //fake extension, for OGGs
|
||||
"lopus", //fake extension, for OPUS
|
||||
"lflac", //fake extension for .flac, FFmpeg/not parsed
|
||||
"lmp2", //fake extension for .mp2, FFmpeg/not parsed
|
||||
"lmp3", //fake extension for .mp3, FFmpeg/not parsed
|
||||
"lmp4", //fake extension for .mp4
|
||||
"lmpc", //fake extension for .mpc, FFmpeg/not parsed
|
||||
"logg", //fake extension for .ogg
|
||||
"lopus", //fake extension for .opus
|
||||
"lpcm",
|
||||
"lpk",
|
||||
"lps",
|
||||
"lse",
|
||||
"lsf",
|
||||
"lstm", //fake extension, for STMs
|
||||
"lwav", //fake extension, for WAVs
|
||||
"lstm", //fake extension for .stm
|
||||
"lwav", //fake extension for .wav
|
||||
"lwma", //fake extension for .wma, FFmpeg/not parsed
|
||||
|
||||
"mab",
|
||||
"matx",
|
||||
@ -220,9 +228,10 @@ static const char* extension_list[] = {
|
||||
"mihb",
|
||||
"mnstr",
|
||||
"mogg",
|
||||
//"mp2", //common
|
||||
//"mp3", //common
|
||||
//"mp4", //common
|
||||
//"mpc", //FFmpeg, not parsed (musepack) //common
|
||||
//"mpc", //common
|
||||
"mpdsp",
|
||||
"mpds",
|
||||
"mps", //txth/reserved [Scandal (PS2)]
|
||||
@ -239,7 +248,7 @@ static const char* extension_list[] = {
|
||||
"mus",
|
||||
"musc",
|
||||
"musx",
|
||||
"mvb", //txth/reserved [Porsche Challenge(PS1)]
|
||||
"mvb", //txth/reserved [Porsche Challenge (PS1)]
|
||||
"mwv",
|
||||
"mxst",
|
||||
"myspd",
|
||||
@ -250,14 +259,14 @@ static const char* extension_list[] = {
|
||||
"nlsd",
|
||||
"nop",
|
||||
"nps",
|
||||
"npsf", //fake extension/header id for .nps (to be removed)
|
||||
"npsf", //fake extension/header id for .nps (in bigfiles)
|
||||
"nus3bank",
|
||||
"nwa",
|
||||
"nxa",
|
||||
|
||||
//"ogg", //common
|
||||
"ogl",
|
||||
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||
"oma", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
|
||||
"omu",
|
||||
//"opus", //common
|
||||
"otm",
|
||||
@ -274,10 +283,10 @@ static const char* extension_list[] = {
|
||||
"pnb",
|
||||
"pona",
|
||||
"pos",
|
||||
"ps2stm", //fake extension for .stm (to be removed)
|
||||
"ps2stm", //fake extension for .stm (renamed? to be removed?)
|
||||
"psh", // fake extension for VSV(?) Dawn of Mana needs to be checked again
|
||||
"psnd",
|
||||
"psw", //fake extension for .wam
|
||||
"psw", //fake extension for .wam (renamed, to be removed)
|
||||
|
||||
"r",
|
||||
"rac", //txth/reserved [Manhunt (Xbox)]
|
||||
@ -293,7 +302,7 @@ static const char* extension_list[] = {
|
||||
"rsd",
|
||||
"rsf",
|
||||
"rsm",
|
||||
"rstm", //rsm header id
|
||||
"rstm", //fake extension/header id for .rstm (in bigfiles)
|
||||
"rvws",
|
||||
"rwar",
|
||||
"rwav",
|
||||
@ -335,7 +344,7 @@ static const char* extension_list[] = {
|
||||
"sli",
|
||||
"smc",
|
||||
"smp",
|
||||
"smpl", //fake extension (to be removed)
|
||||
"smpl", //fake extension/header id for .v0/v1 (renamed, to be removed)
|
||||
"smv",
|
||||
"snd",
|
||||
"snds",
|
||||
@ -357,7 +366,7 @@ static const char* extension_list[] = {
|
||||
"ster",
|
||||
"sth",
|
||||
//"stm", //common
|
||||
"stma", //fake extension (to be removed)
|
||||
"stma", //fake extension/header id for .stm
|
||||
"str",
|
||||
"stream",
|
||||
"strm",
|
||||
@ -393,7 +402,7 @@ static const char* extension_list[] = {
|
||||
|
||||
"v0",
|
||||
//"v1", //dual channel with v0
|
||||
"va3", //konami atrac3, FFMPEG - DDR Supernova 2 AC
|
||||
"va3",
|
||||
"vag",
|
||||
"vai",
|
||||
"vas",
|
||||
@ -430,6 +439,7 @@ static const char* extension_list[] = {
|
||||
"wem",
|
||||
"wii",
|
||||
"wip", //txth/reserved [Colin McRae DiRT (PC)]
|
||||
"wma", //common
|
||||
"wmus",
|
||||
"wp2",
|
||||
"wpd",
|
||||
@ -456,7 +466,7 @@ static const char* extension_list[] = {
|
||||
"xss",
|
||||
"xvag",
|
||||
"xvas",
|
||||
"xwav",//fake, to be removed
|
||||
"xwav",//fake extension for .wav (renamed, to be removed)
|
||||
"xwb",
|
||||
"xmd",
|
||||
"xopus",
|
||||
@ -676,6 +686,7 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_blocked_sthd, "blocked (STHD)"},
|
||||
{layout_blocked_h4m, "blocked (H4M)"},
|
||||
{layout_blocked_xa_aiff, "blocked (XA AIFF)"},
|
||||
{layout_blocked_vs_ffx, "blocked (Final Fantasy X VS)"},
|
||||
};
|
||||
|
||||
static const meta_info meta_info_list[] = {
|
||||
@ -1094,8 +1105,9 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
|
||||
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
|
||||
{meta_XWMA, "Microsoft XWMA RIFF header"},
|
||||
{meta_VA3, "Konami / Sony ATRAC3 Header" },
|
||||
{meta_XOPUS, "Rovio XOPUS header"},
|
||||
{meta_VA3, "Konami VA3 header" },
|
||||
{meta_XOPUS, "Exient XOPUS header"},
|
||||
{meta_VS_FFX, "Final Fantasy X VS header"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -205,6 +205,9 @@ void block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
case layout_blocked_xa_aiff:
|
||||
block_update_xa_aiff(block_offset,vgmstream);
|
||||
break;
|
||||
case layout_blocked_vs_ffx:
|
||||
block_update_vs_ffx(block_offset,vgmstream);
|
||||
break;
|
||||
default: /* not a blocked layout */
|
||||
break;
|
||||
}
|
||||
|
26
src/layout/blocked_vs_ffx.c
Normal file
26
src/layout/blocked_vs_ffx.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "layout.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* Final Fantasy X VS headered blocks */
|
||||
void block_update_vs_ffx(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
int i;
|
||||
size_t block_size = 0x800;
|
||||
|
||||
/* 0x00: header id
|
||||
* 0x04: null
|
||||
* 0x08: block number
|
||||
* 0x0c: blocks left in the subfile
|
||||
* 0x10: always 0x1000
|
||||
* 0x14: always 0x64
|
||||
* 0x18: null
|
||||
* 0x1c: null */
|
||||
|
||||
vgmstream->current_block_offset = block_offset;
|
||||
vgmstream->current_block_size = block_size - 0x20;
|
||||
vgmstream->next_block_offset = block_offset + block_size;
|
||||
/* 0x08: number of remaning blocks, 0x10: some id/size? (shared in all blocks) */
|
||||
|
||||
for (i = 0; i < vgmstream->channels; i++) {
|
||||
vgmstream->ch[i].offset = block_offset + 0x20 + 0x800*i;
|
||||
}
|
||||
}
|
@ -46,6 +46,7 @@ void block_update_ea_wve_ad10(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_sthd(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_h4m(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_xa_aiff(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
void block_update_vs_ffx(off_t block_offset, VGMSTREAM * vgmstream);
|
||||
|
||||
/* other layouts */
|
||||
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
|
@ -1190,10 +1190,14 @@
|
||||
RelativePath=".\meta\ps2_voi.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\vpk.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\vpk.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\vs_ffx.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps2_wad.c"
|
||||
>
|
||||
@ -1946,6 +1950,10 @@
|
||||
RelativePath=".\layout\blocked_vgs.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layout\blocked_vs_ffx.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\layout\blocked_xvag.c"
|
||||
>
|
||||
|
@ -391,6 +391,7 @@
|
||||
<ClCompile Include="meta\ps2_vms.c" />
|
||||
<ClCompile Include="meta\ps2_voi.c" />
|
||||
<ClCompile Include="meta\vpk.c" />
|
||||
<ClCompile Include="meta\vs_ffx.c" />
|
||||
<ClCompile Include="meta\ps2_wad.c" />
|
||||
<ClCompile Include="meta\ps2_wb.c" />
|
||||
<ClCompile Include="meta\ps2_xa2.c" />
|
||||
@ -534,6 +535,7 @@
|
||||
<ClCompile Include="layout\blocked_awc.c" />
|
||||
<ClCompile Include="layout\blocked_ea_1snh.c" />
|
||||
<ClCompile Include="layout\blocked_vgs.c" />
|
||||
<ClCompile Include="layout\blocked_vs_ffx.c" />
|
||||
<ClCompile Include="layout\blocked_vawx.c" />
|
||||
<ClCompile Include="layout\blocked_xvag.c" />
|
||||
<ClCompile Include="layout\blocked_caf.c" />
|
||||
|
@ -742,6 +742,9 @@
|
||||
<ClCompile Include="meta\vpk.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\vs_ffx.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ps2_wad.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1165,6 +1168,9 @@
|
||||
<ClCompile Include="layout\blocked_vgs.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\blocked_vs_ffx.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="layout\blocked_vawx.c">
|
||||
<Filter>layout\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -4,8 +4,8 @@
|
||||
#include "hca_keys_awb.h"
|
||||
|
||||
typedef struct {
|
||||
uint64_t key; /* hca key or seed key */
|
||||
const uint16_t *subkeys; /* derivation subkey table for seed key */
|
||||
uint64_t key; /* hca key or seed ('user') key */
|
||||
const uint16_t *subkeys; /* scramble subkey table for seed key */
|
||||
size_t subkeys_size; /* size of the derivation subkey table */
|
||||
} hcakey_info;
|
||||
|
||||
@ -15,7 +15,7 @@ typedef struct {
|
||||
* CRI's tools expect an unsigned 64 bit number string, but keys are commonly found online in hex form.
|
||||
* Keys only use 56 bits though, so the upper 8 bits can be ignored.
|
||||
*
|
||||
* ACB+AWB after mid 2018 use a master seed key + a derivation subkey in the AWB (normally 16b LE at 0x0e)
|
||||
* ACB+AWB after mid 2018 use a user seed key + a scramble subkey in the AWB (normally 16b LE at 0x0e)
|
||||
* to create the final HCA key, which means there is one key per AWB (so most HCA have a unique key).
|
||||
* vgmstream derives the key if subkey table is provided.
|
||||
*/
|
||||
|
@ -799,4 +799,6 @@ VGMSTREAM * init_vgmstream_xwma(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_xopus(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -150,10 +150,11 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
|
||||
loop_start_sample = loop_start / 2 / channel_count;
|
||||
is_loop_samples = 1;
|
||||
}
|
||||
else if ((loop_start % 0x800 == 0) && loop_start > 0) {/* sector-aligned, min is 0x800 */
|
||||
else if ((loop_start % 0x800 == 0) && loop_start > 0) {/* sector-aligned, min/0 is 0x800 */
|
||||
/* cavia games: loop_start is offset [Drakengard 1/2, GITS: Stand Alone Complex] */
|
||||
/* offset is absolute from the "cavia stream format" container that adjusts ADS start */
|
||||
loop_flag = 1;
|
||||
loop_start_offset = loop_start;
|
||||
loop_start_offset = loop_start - 0x800;
|
||||
ignore_silent_frame_cavia = 1;
|
||||
}
|
||||
else if (loop_start % 0x800 != 0 || loop_start == 0) { /* not sector aligned */
|
||||
|
@ -273,8 +273,9 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
|
||||
* .adp: Headhunter (DC)
|
||||
* .xss: Spider-Man The Movie (Xbox)
|
||||
* .xsew: Mega Man X Legacy Collections (PC)
|
||||
* .adpcm: Angry Birds Transformers (Android) */
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm") ) {
|
||||
* .adpcm: Angry Birds Transformers (Android)
|
||||
* .adw: Dead Rising 2 (PC) */
|
||||
if ( check_extensions(streamFile, "wav,lwav,xwav,da,dax,cd,med,snd,adx,adp,xss,xsew,adpcm,adw") ) {
|
||||
;
|
||||
}
|
||||
else if ( check_extensions(streamFile, "mwv") ) {
|
||||
|
53
src/meta/vs_ffx.c
Normal file
53
src/meta/vs_ffx.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .vs/VS - from Final Fantasy X voices (PS2) */
|
||||
VGMSTREAM * init_vgmstream_vs_ffx(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
int channel_count, loop_flag;
|
||||
off_t start_offset;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .vs: header id (probably ok like The Bouncer's .vs, very similar) */
|
||||
if (!check_extensions(streamFile, "vs"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x56530000) /* "VS\0\0" */
|
||||
goto fail;
|
||||
|
||||
|
||||
loop_flag = 0;
|
||||
channel_count = 1;
|
||||
start_offset = 0x00;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_VS_FFX;
|
||||
vgmstream->sample_rate = 48000;
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_blocked_vs_ffx;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
|
||||
/* calc num_samples */
|
||||
{
|
||||
vgmstream->next_block_offset = start_offset;
|
||||
do {
|
||||
block_update(vgmstream->next_block_offset,vgmstream);
|
||||
vgmstream->num_samples += ps_bytes_to_samples(vgmstream->current_block_size, 1);
|
||||
}
|
||||
while (vgmstream->next_block_offset < get_streamfile_size(streamFile));
|
||||
block_update(start_offset, vgmstream);
|
||||
}
|
||||
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* XOPUS - from Rovio games [Angry Birds: Transformers (Android), Angry Birds: Go (Android)] */
|
||||
/* XOPUS - from Exient games [Angry Birds: Transformers (Android), Angry Birds: Go (Android)] */
|
||||
VGMSTREAM * init_vgmstream_xopus(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
@ -17,24 +17,21 @@ VGMSTREAM * init_vgmstream_xopus(STREAMFILE *streamFile) {
|
||||
if (read_32bitBE(0x00, streamFile) != 0x584F7075) /* "XOpu" */
|
||||
goto fail;
|
||||
|
||||
/* 0x04: always 1? 0x30? */
|
||||
/* 0x04: always 0x01? */
|
||||
channel_count = read_8bit(0x05, streamFile);
|
||||
/* 0x06: always 0x30? */
|
||||
/* 0x08: always 0xc8? encoder delay? */
|
||||
/* 0x08: always 0xc8? max allowed packet size? */
|
||||
num_samples = read_32bitLE(0x0c, streamFile);
|
||||
/* 0x10: always 0x138? max packet size? */
|
||||
entries = read_32bitLE(0x14, streamFile); /* packet sizes */
|
||||
/* 0x18: data size */
|
||||
skip = read_32bitLE(0x10, streamFile);
|
||||
entries = read_32bitLE(0x14, streamFile);
|
||||
data_size = read_32bitLE(0x18, streamFile);
|
||||
/* 0x1c: unused */
|
||||
/* 0x20+: packet sizes table */
|
||||
|
||||
|
||||
sample_rate = 48000;
|
||||
loop_flag = 0;
|
||||
|
||||
start_offset = 0x20 + 0x02*entries;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
skip = x_opus_get_encoder_delay(start_offset, streamFile);
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
@ -43,7 +40,7 @@ VGMSTREAM * init_vgmstream_xopus(STREAMFILE *streamFile) {
|
||||
|
||||
vgmstream->meta_type = meta_XOPUS;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples /*- skip*/;
|
||||
vgmstream->num_samples = num_samples;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
{
|
||||
|
@ -444,7 +444,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_ue4opus,
|
||||
init_vgmstream_xwma,
|
||||
init_vgmstream_xopus,
|
||||
|
||||
init_vgmstream_vs_ffx,
|
||||
|
||||
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
|
||||
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
|
||||
@ -1018,6 +1018,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
||||
case layout_blocked_sthd:
|
||||
case layout_blocked_h4m:
|
||||
case layout_blocked_xa_aiff:
|
||||
case layout_blocked_vs_ffx:
|
||||
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
case layout_aix:
|
||||
|
@ -253,6 +253,7 @@ typedef enum {
|
||||
layout_blocked_sthd, /* Dream Factory STHD */
|
||||
layout_blocked_h4m, /* H4M video */
|
||||
layout_blocked_xa_aiff, /* XA in AIFF files [Crusader: No Remorse (SAT), Road Rash (3DO)] */
|
||||
layout_blocked_vs_ffx,
|
||||
|
||||
/* otherwise odd */
|
||||
layout_aix, /* CRI AIX's wheels within wheels */
|
||||
@ -701,6 +702,7 @@ typedef enum {
|
||||
meta_XWMA,
|
||||
meta_VA3, /* DDR Supernova 2 AC */
|
||||
meta_XOPUS,
|
||||
meta_VS_FFX,
|
||||
|
||||
} meta_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user