diff --git a/README.md b/README.md index 15aca198..99ec7382 100644 --- a/README.md +++ b/README.md @@ -39,52 +39,58 @@ There are multiple end-user components: The main library (plain *vgmstream*) is the code that handles the internal conversion, while the above components are what you use to get sound. -If you just want to convert game audio to `.wav`, easiest would be getting *vgmstream-cli* (see -below) then drag-and-drop one or more files to the executable. This should create `(file.extension).wav`, -if the format is supported. More usable would be installing a music player like *foobar2000* (for -Windows) or *Audacious* (for Linux) then the appropriate component, so you can listen to VGM without -converting and set options like infinite looping. +If you want to convert game audio to `.wav`, try getting *vgmstream-cli* (see below) then +drag-and-drop one or more files to the executable (support may vary per O.S. or distro). +This should create `(file.extension).wav`, if the format is supported. More user-friendly +would be installing a player like *foobar2000* (for Windows) or *Audacious* (for Linux) +and the vgmstream plugin. Then you can directly listen your files and set options like infinite +looping, or convert to `.wav` with the player's options (also easier if your file has multiple +"subsongs"). See [components](doc/USAGE.md#components) in the *usage guide* for full install instructions and explanations. The aim is feature parity, but there are a few differences between them due to -missing implementation on vgmstream's side or lack of support in target player or API. +missing parts on vgmstream's side or lack of support in the player. -Note vgmstream cannot *encode* (convert from `.wav` to some video game format), it only *decodes* +Note that vgmstream cannot *encode* (convert from `.wav` to a video game format), it only *decodes* (plays game audio). ### Windows -You should get `vgmstream-win.zip`, which also bundles various components, or -`foo_input_vgmstream.fb2k-component` for the installable foobar2000 plugin from the -latest prebuilt binaries on our website: +Get the latest prebuilt binaries (CLI/plugins/etc) on our website: - https://vgmstream.org -You can also get them from the less frequently updated releases on GitHub: +Or the less frequent "official" releases on GitHub: - https://github.com/vgmstream/vgmstream/releases -If the above links fail, you may also try the alternative, somewhat recent versions built by +The foobar2000 component is also available on https://www.foobar2000.org based on current +release. + +If the above links fail, you may also try the alternative versions built by [bnnm](https://github.com/bnnm): - https://github.com/bnnm/vgmstream-builds/raw/master/bin/vgmstream-latest-test-u.zip -If you prefer, you may compile the components from source as well, see the -[build guide](doc/BUILD.md) for more information. +You may compile from source as well, see the [build guide](doc/BUILD.md). ### Linux -For convenience, releases distribute a command-line decoder in `vgmstream-cli.zip`. It is -statically linked and should work on all systems running Linux kernel v3.2 and above. +A prebuilt CLI binary is available. It's statically linked and should work on systems running +Linux kernel v3.2 and above: - https://vgmstream.org - https://github.com/vgmstream/vgmstream/releases -Building from source will also give you *vgmstream.so*, an Audacious plugin, and *vgmstream123*, -a command-line player. +Building from source will also give you *vgmstream.so* (Audacious plugin), and *vgmstream123* +(command-line player). -When building from source code, many components have to be installed or compiled separately. The -[build guide](doc/BUILD.md) describes this process in more detail. For a quick build on Debian and -Ubuntu-style distributions, run `./make-build-cmake.sh`. The script will be installing various -dependencies, so you may prefer to copy the commands from the file and run them one by one. +When building, many extra components have to be installed or compiled separately, which the +[build guide](doc/BUILD.md) describes in detail. For a quick build on Debian and Ubuntu-style +distributions run `./make-build-cmake.sh`. The script will need to install various dependencies, +so you may prefer to copy commands and run them manually. ### macOS -Please follow the [build guide](doc/BUILD.md). +A prebuilt CLI binary is available as well: +- https://vgmstream.org +- https://github.com/vgmstream/vgmstream/releases + +Otherwise follow the [build guide](doc/BUILD.md). ## More info diff --git a/src/formats.c b/src/formats.c index 2107a797..9db4e8d4 100644 --- a/src/formats.c +++ b/src/formats.c @@ -706,6 +706,7 @@ static const char* common_extension_list[] = { "flac", //common "m4a", //common "m4v", //common + "mov", //common "mp+", //common [Moonshine Runners (PC)] "mp2", //common "mp3", //common diff --git a/src/meta/bwav.c b/src/meta/bwav.c index 8cc39a36..b2f933cd 100644 --- a/src/meta/bwav.c +++ b/src/meta/bwav.c @@ -75,13 +75,15 @@ VGMSTREAM* init_vgmstream_bwav(STREAMFILE* sf) { vgmstream->allow_dual_stereo = 1; /* Animal Crossing: Happy Home Paradise */ break; - case 0x0002: /* Zelda TOTK (Switch) */ +#ifdef VGM_USE_FFMPEG + case 0x0002: /* The Legend of Zelda: Tears of the Kingdom (Switch) */ vgmstream->layout_data = build_layered_data(sf, channels); if (!vgmstream->layout_data) goto fail; vgmstream->coding_type = coding_FFmpeg; vgmstream->layout_type = layout_layered; break; +#endif default: goto fail; } diff --git a/src/meta/fsb_keys.h b/src/meta/fsb_keys.h index 384ef26f..b852a04e 100644 --- a/src/meta/fsb_keys.h +++ b/src/meta/fsb_keys.h @@ -25,7 +25,7 @@ typedef struct { #define MODE_FSB4_STD (FLAG_FSB4 | FLAG_STD) #define MODE_FSB4_ALT (FLAG_FSB4 | FLAG_ALT) -#define MODE_FSB4_ALL (FLAG_FSB4 | FLAG_ALT) +#define MODE_FSB4_ALL (FLAG_FSB4 | FLAG_STD | FLAG_ALT) #define MODE_FSB5_STD (FLAG_FSB5 | FLAG_STD) #define MODE_FSB5_ALT (FLAG_FSB5 | FLAG_STD) #define MODE_FSB5_ALL (FLAG_FSB5 | FLAG_STD | FLAG_ALT) @@ -42,8 +42,8 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSB5_STD, FSBKEY_ADD("sTOoeJXI2LjK8jBMOk8h5IDRNZl3jq3I") }, // Slightly Mad Studios: Project CARS (PC?), World of Speed (PC) { MODE_FSB5_STD, FSBKEY_ADD("%lAn2{Pi*Lhw3T}@7*!kV=?qS$@iNlJ") }, // Ghost in the Shell: First Assault (PC) { MODE_FSB5_STD, FSBKEY_ADD("1^7%82#&5$~/8sz") }, // RevHeadz Engine Sounds (Mobile) - { MODE_FSB5_ALL, FSBKEY_ADD("FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg") }, // Dark Souls 3 (PC) [untested] - { MODE_FSB4_ALL, FSBKEY_ADD("p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj") }, // Need for Speed Shift 2 Unleashed (PC demo?)[untested] + { MODE_FSB5_STD, FSBKEY_ADD("FDPrVuT4fAFvdHJYAgyMzRF4EcBAnKg") }, // Dark Souls 3 (PC) + { MODE_FSB4_STD, FSBKEY_ADD("p&oACY^c4LK5C2v^x5nIO6kg5vNH$tlj") }, // Need for Speed Shift 2 Unleashed (PC) { MODE_FSB5_STD, FSBKEY_ADD("996164B5FC0F402983F61F220BB51DC6") }, // Mortal Kombat X/XL (PC) { MODE_FSB5_STD, FSBKEY_ADD("logicsounddesignmwsdev") }, // Mirror War: Reincarnation of Holiness (PC) { MODE_FSBS_ALL, FSBKEY_ADD("gat@tcqs2010") }, // Xian Xia Chuan (PC) [untested] @@ -56,8 +56,8 @@ static const fsbkey_info fsbkey_list[] = { { MODE_FSBS_ALL, FSBKEY_ADD("B2A7BB00") }, // Supreme Commander 2 [untested] { MODE_FSB4_STD, FSBKEY_ADD("ghfxhslrghfxhslr") }, // Cookie Run: Ovenbreak { MODE_FSB4_ALT, FSBKEY_ADD("truck/impact/carbody") },// Monster Jam (PS2) [FSB3] - { MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") }, - { MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") }, + { MODE_FSB4_ALT, FSBKEY_ADD("\xFC\xF9\xE4\xB3\xF5\x57\x5C\xA5\xAC\x13\xEC\x4A\x43\x19\x58\xEB\x4E\xF3\x84\x0B\x8B\x78\xFA\xFD\xBB\x18\x46\x7E\x31\xFB\xD0") }, // Guitar Hero 5 (X360) + { MODE_FSB4_ALT, FSBKEY_ADD("\x8C\xFA\xF3\x14\xB1\x53\xDA\xAB\x2B\x82\x6B\xD5\x55\x16\xCF\x01\x90\x20\x28\x14\xB1\x53\xD8") }, // Guitar Hero: Metallica (X360) { MODE_FSB5_STD, FSBKEY_ADD("G0KTrWjS9syqF7vVD6RaVXlFD91gMgkC") }, // Sekiro: Shadows Die Twice (PC) { MODE_FSB5_STD, FSBKEY_ADD("BasicEncryptionKey") }, // SCP: Unity (PC) { MODE_FSB5_STD, FSBKEY_ADD("FXnTffGJ9LS855Gc") }, // Worms Rumble Beta (PC) diff --git a/src/meta/rsd.c b/src/meta/rsd.c index a8b22d07..58547fb4 100644 --- a/src/meta/rsd.c +++ b/src/meta/rsd.c @@ -5,7 +5,7 @@ /* RSD - from Radical Entertainment games */ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; - off_t start_offset, name_offset; + uint32_t start_offset, name_offset, coef_offset; size_t data_size; int loop_flag, channels, sample_rate, interleave; uint32_t codec; @@ -14,9 +14,9 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { /* checks */ if ((read_u32be(0x00,sf) & 0xFFFFFF00) != get_id32be("RSD\00")) - goto fail; + return NULL; if (!check_extensions(sf,"rsd,rsp")) - goto fail; + return NULL; loop_flag = 0; @@ -32,14 +32,19 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { interleave = read_u32le(0x14,sf); /* VAG only, 0x04 otherwise */ start_offset = read_u32le(0x18,sf); name_offset = 0; + coef_offset = 0x1C; + + if ((codec == get_id32be("GADP"))) + start_offset = 0xA0; break; case '4': /* known codecs: VAG/PCM/RADP/PCMB [The Simpsons: Hit & Run, Tetris Worlds, Hulk] */ - /* 0x14: padding */ + /* 0x14: padding/coefs */ /* 0x18: padding */ interleave = 0; start_offset = 0x800; name_offset = 0; + coef_offset = 0x14; /* PCMB/PCM/GADP normally start early but sometimes have padding [The Simpsons: Hit & Run (GC/Xbox)] */ if ((codec == get_id32be("PCM ") || codec == get_id32be("PCMB") || codec == get_id32be("GADP")) @@ -52,6 +57,7 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { name_offset = 0x18; /* dev file path */ interleave = 0; start_offset = 0x800; + coef_offset = 0x00; break; default: @@ -104,8 +110,8 @@ VGMSTREAM* init_vgmstream_rsd(STREAMFILE* sf) { vgmstream->coding_type = coding_NGC_DSP; vgmstream->layout_type = layout_interleave; vgmstream->interleave_block_size = 0x08; /* assumed, known files are mono */ - dsp_read_coefs_le(vgmstream,sf,0x1c,0x2e); /* LE! */ - dsp_read_hist_le (vgmstream,sf,0x38,0x2e); + dsp_read_coefs_le(vgmstream,sf,coef_offset,0x2e); /* LE! */ + dsp_read_hist_le (vgmstream,sf,coef_offset + 0x24, 0x2e); vgmstream->num_samples = dsp_bytes_to_samples(data_size, channels); break; diff --git a/src/meta/sfh.c b/src/meta/sfh.c index b22a2205..7ca7a902 100644 --- a/src/meta/sfh.c +++ b/src/meta/sfh.c @@ -1,46 +1,65 @@ -#include "meta.h" -#include "../coding/coding.h" -#include "sfh_streamfile.h" - - -/* .SFH - Capcom wrapper [Devil May Cry 4 Demo (PS3), Jojo's Bizarre Adventure HD (PS3)] */ -VGMSTREAM * init_vgmstream_sfh(STREAMFILE *streamFile) { - VGMSTREAM *vgmstream = NULL; - STREAMFILE *temp_streamFile = NULL; - uint32_t version; - size_t clean_size, block_size; - - /* check extensions */ - if ( !check_extensions(streamFile,"at3")) - goto fail; - - if (read_32bitBE(0x00, streamFile) != 0x00534648) /* "\0SFH" */ - goto fail; - if (read_32bitBE(0x10, streamFile) != 0x52494646) /* "RIFF" */ - goto fail; - - /* mini header */ - version = read_32bitBE(0x04,streamFile); - clean_size = read_32bitBE(0x08,streamFile); /* there is padding data at the end */ - /* 0x0c: always 0 */ - - switch(version) { - case 0x00010000: block_size = 0x10010; break; /* DMC4 Demo (not retail) */ - case 0x00010001: block_size = 0x20000; break; /* Jojo */ - default: goto fail; - } - - temp_streamFile = setup_sfh_streamfile(streamFile, 0x00, block_size, clean_size, "at3"); - if (!temp_streamFile) goto fail; - - vgmstream = init_vgmstream_riff(temp_streamFile); - if (!vgmstream) goto fail; - - close_streamfile(temp_streamFile); - return vgmstream; - -fail: - close_streamfile(temp_streamFile); - close_vgmstream(vgmstream); - return NULL; -} +#include "meta.h" +#include "../coding/coding.h" +#include "sfh_streamfile.h" + +typedef VGMSTREAM* (*init_vgmstream_t)(STREAMFILE*); + + +/* .SFH - Capcom wrapper used with common audio extensions [Devil May Cry 4 Demo (PS3), Jojo's Bizarre Adventure HD (PS3), Sengoku Basara 4 Sumeragi (PS3)] */ +VGMSTREAM* init_vgmstream_sfh(STREAMFILE* sf) { + VGMSTREAM* vgmstream = NULL; + STREAMFILE* temp_sf = NULL; + init_vgmstream_t init_vgmstream = NULL; + + + /* checks */ + if (!is_id32be(0x00, sf, "\0SFH")) + return NULL; + if (!check_extensions(sf,"at3,sspr")) + return NULL; + + /* mini header */ + uint32_t version = read_u32be(0x04,sf); + uint32_t clean_size = read_u32be(0x08,sf); /* there is padding data at the end */ + /* 0x0c: always 0 */ + + char* extension; + uint32_t header_id = read_u32be(0x10,sf); + switch(header_id) { + case 0x52494646: // RIFF + init_vgmstream = init_vgmstream_riff; + extension = "at3"; + break; + + case 0x53535052: // SSPR + init_vgmstream = init_vgmstream_sspr; + extension = "sspr"; + break; + + case 0x00434C44: // \0CLD (.dlcp) + case 0x00435241: // \0CRA (.arc) + default: + goto fail; + } + + uint32_t block_size; + switch(version) { + case 0x00010000: block_size = 0x10010; break; /* DMC4 Demo (not retail) */ + case 0x00010001: block_size = 0x20000; break; /* Jojo, SB4 */ + default: goto fail; + } + + temp_sf = setup_sfh_streamfile(sf, 0x00, block_size, clean_size, extension); + if (!temp_sf) goto fail; + + vgmstream = init_vgmstream(temp_sf); + if (!vgmstream) goto fail; + + close_streamfile(temp_sf); + return vgmstream; + +fail: + close_streamfile(temp_sf); + close_vgmstream(vgmstream); + return NULL; +} diff --git a/src/meta/sspr.c b/src/meta/sspr.c index c877be76..3a58b10f 100644 --- a/src/meta/sspr.c +++ b/src/meta/sspr.c @@ -6,23 +6,22 @@ VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf) { VGMSTREAM* vgmstream = NULL; STREAMFILE* temp_sf = NULL; - uint32_t name_offset, subfile_offset, subfile_size, name_size; - int big_endian; - int total_subsongs, target_subsong = sf->stream_index; - char* extension; - uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL; - /* checks */ - if (!check_extensions(sf,"sspr")) - goto fail; if (!is_id32be(0x00,sf,"SSPR")) - goto fail; + return NULL; + if (!check_extensions(sf,"sspr")) + return NULL; + + uint32_t name_offset, subfile_offset, subfile_size, name_size; + int total_subsongs, target_subsong = sf->stream_index; + char* extension; + read_u32_t read_u32 = NULL; /* Simple (audio only) container used some Capcom games (common engine?). * Some files come with a .stqr with unknown data (cues?). */ - big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */ + int big_endian = guess_endian32(0x04, sf); /* 0x01 (version?) */ read_u32 = big_endian ? read_u32be : read_u32le; total_subsongs = read_u32(0x08,sf); diff --git a/src/meta/str_wav.c b/src/meta/str_wav.c index 0c915eda..18fc59d9 100644 --- a/src/meta/str_wav.c +++ b/src/meta/str_wav.c @@ -639,7 +639,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } /* SpongeBob SquarePants: Creature from the Krusty Krab (PS2)[2006] */ - /* Big Bumpin (Xbox)[2006] */ + /* Big Bumpin' (Xbox)[2006] */ /* Sneak King (Xbox)[2006] */ if ( read_u32be(0x04,sf_h) == 0x00000800 && read_u32le(0x08,sf_h) == 0x00000000 && @@ -674,7 +674,7 @@ static int parse_header(STREAMFILE* sf_h, STREAMFILE* sf_b, strwav_header* strwa } else { strwav->codec = XBOX; - strwav->interleave = strwav->tracks > 1 ? 0x9000 : 0xD800; /* assumed for multitrack */ + strwav->interleave = strwav->tracks > 1 ? 0x9000 : 0xD800; } ;VGM_LOG("STR+WAV: header SBCKK/BB/SK (PS2/Xbox)\n"); return 1;