mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-20 20:41:08 +01:00
Merge pull request #942 from bnnm/fixes
- Fix some .p3d [Spider-Man 4 beta (X360)] - Fix some .ktsl2asbin/atsl [Nioh (PC)] - build: fix some emscripten/wasm crashes
This commit is contained in:
commit
95aada74c6
@ -103,10 +103,11 @@ endif()
|
||||
if(BUILD_STATIC)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(PC_OPUS REQUIRED opus>=1.1)
|
||||
|
||||
|
||||
# it is already kind of obvious when you do not have it, and just prevents you from building without ffmpeg
|
||||
#find_package(PkgConfig REQUIRED)
|
||||
#pkg_check_modules(PC_OPUS REQUIRED opus>=1.1)
|
||||
|
||||
# Incompatible with static builds
|
||||
set(BUILD_AUDACIOUS OFF)
|
||||
endif()
|
||||
|
@ -58,7 +58,7 @@ You may compile them from source as well (see *build guide*).
|
||||
|
||||
### Linux
|
||||
Generally you need to build vgmstream's components manually (see *build guide*). For
|
||||
a quick build call `/make-build-cmake.sh` (for Debian/Ubuntu-style distros, installs
|
||||
a quick build call `./make-build-cmake.sh` (for Debian/Ubuntu-style distros, installs
|
||||
various deps first so you may prefer to call commands manually).
|
||||
|
||||
Releases also distribute a static version of the CLI tool (kernel v3.2+).
|
||||
|
25
doc/BUILD.md
25
doc/BUILD.md
@ -362,6 +362,31 @@ For integration and "API" usage, easiest would be checking how `vgmstream_cli.c`
|
||||
A cleaner API/.h and build methods is planned for the future (low priority though).
|
||||
|
||||
|
||||
# emscripten / wasm
|
||||
It's possible to build vgmstream components with emscripten (in-browser support).
|
||||
|
||||
Follow emscripten's installation instructions:
|
||||
- https://emscripten.org/docs/getting_started/downloads.html
|
||||
- https://emscripten.org/docs/compiling/Building-Projects.html#building-projects
|
||||
|
||||
Then should be buildable on Linux (Windows should be possible too but has some issues at the moment), for example:
|
||||
```
|
||||
git clone https://github.com/vgmstream/vgmstream
|
||||
cd vgmstream
|
||||
mkdir -p build && cd build
|
||||
|
||||
# quickest example, some can be enabled
|
||||
emcmake cmake -DBUILD_STATIC=ON -DUSE_JANSSON=OFF -DUSE_FFMPEG=OFF -DUSE_VORBIS=OFF -DUSE_MPEG=OFF -DUSE_G7221=OFF -DUSE_G719=OFF -DUSE_ATRAC9=OFF -DUSE_SPEEX=OFF -DUSE_MPEG=OFF -S .. -B .
|
||||
emmake make
|
||||
```
|
||||
Or with the base makefiles (may need to rename output to .js ATM):
|
||||
```
|
||||
git clone https://github.com/vgmstream/vgmstream
|
||||
cd vgmstream
|
||||
make vgmstream-cli CC=emcc AR=emar strip=echo
|
||||
```
|
||||
|
||||
|
||||
## External libraries
|
||||
Support for some codecs is done with external libs, instead of copying their code in vgmstream. There are various reasons for this:
|
||||
- each lib may have complex or conflicting ways to compile that aren't simple to replicate
|
||||
|
@ -7,15 +7,15 @@
|
||||
VGMSTREAM* init_vgmstream_acb(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
off_t subfile_offset;
|
||||
size_t subfile_size;
|
||||
utf_context *utf = NULL;
|
||||
uint32_t subfile_offset;
|
||||
uint32_t subfile_size;
|
||||
utf_context* utf = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "acb"))
|
||||
if (!is_id32be(0x00,sf, "@UTF"))
|
||||
goto fail;
|
||||
if (read_u32be(0x00,sf) != 0x40555446) /* "@UTF" */
|
||||
if (!check_extensions(sf, "acb"))
|
||||
goto fail;
|
||||
|
||||
/* .acb is a cue sheet that uses @UTF (CRI's generic table format) to store row/columns
|
||||
@ -41,8 +41,10 @@ VGMSTREAM* init_vgmstream_acb(STREAMFILE* sf) {
|
||||
subfile_size = size;
|
||||
|
||||
/* column exists but can be empty */
|
||||
if (subfile_size == 0)
|
||||
if (subfile_size == 0) {
|
||||
vgm_logi("ACB: bank has no subsongs (ignore)\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
//;VGM_LOG("ACB: subfile offset=%lx + %x\n", subfile_offset, subfile_size);
|
||||
@ -50,7 +52,7 @@ VGMSTREAM* init_vgmstream_acb(STREAMFILE* sf) {
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset,subfile_size, "awb");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
if (read_u32be(0x00, temp_sf) == 0x43504B20) { /* "CPK " */
|
||||
if (is_id32be(0x00, temp_sf, "CPK ")) {
|
||||
vgmstream = init_vgmstream_cpk_memory(temp_sf, sf); /* older */
|
||||
if (!vgmstream) goto fail;
|
||||
}
|
||||
@ -107,17 +109,17 @@ typedef struct {
|
||||
STREAMFILE* acbFile; /* original reference, don't close */
|
||||
|
||||
/* keep track of these tables so they can be closed when done */
|
||||
utf_context *Header;
|
||||
utf_context* Header;
|
||||
|
||||
utf_context *CueNameTable;
|
||||
utf_context *CueTable;
|
||||
utf_context *BlockSequenceTable;
|
||||
utf_context *BlockTable;
|
||||
utf_context *SequenceTable;
|
||||
utf_context *TrackTable;
|
||||
utf_context *TrackCommandTable;
|
||||
utf_context *SynthTable;
|
||||
utf_context *WaveformTable;
|
||||
utf_context* CueNameTable;
|
||||
utf_context* CueTable;
|
||||
utf_context* BlockSequenceTable;
|
||||
utf_context* BlockTable;
|
||||
utf_context* SequenceTable;
|
||||
utf_context* TrackTable;
|
||||
utf_context* TrackCommandTable;
|
||||
utf_context* SynthTable;
|
||||
utf_context* WaveformTable;
|
||||
|
||||
STREAMFILE* CueNameSf;
|
||||
STREAMFILE* CueSf;
|
||||
@ -142,7 +144,7 @@ typedef struct {
|
||||
|
||||
/* name stuff */
|
||||
int16_t cuename_index;
|
||||
const char * cuename_name;
|
||||
const char* cuename_name;
|
||||
int awbname_count;
|
||||
int16_t awbname_list[ACB_MAX_NAMELIST];
|
||||
char name[ACB_MAX_NAME];
|
||||
|
304
src/meta/atsl.c
304
src/meta/atsl.c
@ -1,157 +1,147 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
typedef enum { ATRAC3, ATRAC9, KOVS, KTSS, KTAC } atsl_codec;
|
||||
|
||||
/* .ATSL - Koei Tecmo audio container [One Piece Pirate Warriors (PS3), Warriors All-Stars (PC)] */
|
||||
VGMSTREAM * init_vgmstream_atsl(STREAMFILE *streamFile) {
|
||||
VGMSTREAM *vgmstream = NULL;
|
||||
STREAMFILE *temp_streamFile = NULL;
|
||||
int total_subsongs, target_subsong = streamFile->stream_index;
|
||||
int type, big_endian = 0, entries;
|
||||
atsl_codec codec;
|
||||
const char* fake_ext;
|
||||
off_t subfile_offset = 0;
|
||||
size_t subfile_size = 0, header_size, entry_size;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
|
||||
if ( !check_extensions(streamFile,"atsl,atsl3,atsl4"))
|
||||
goto fail;
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4154534C) /* "ATSL" */
|
||||
goto fail;
|
||||
|
||||
/* main header (LE) */
|
||||
header_size = read_32bitLE(0x04,streamFile);
|
||||
/* 0x08/0c: flags?, 0x10: fixed? (0x03E8) */
|
||||
entries = read_32bitLE(0x14,streamFile);
|
||||
/* 0x18: 0x28, or 0x30 (rarer) */
|
||||
/* 0x1c: null, 0x20: subheader size, 0x24/28: null */
|
||||
|
||||
/* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c:
|
||||
* - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3]
|
||||
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
|
||||
* 00000301 00020101 (same)
|
||||
* - 01040301 00060301 .atsl4 from Nobunaga's Ambition: Sphere of Influence (PS4)[ATRAC9]
|
||||
* - 00060301 00040301 atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9]
|
||||
* - 00060301 00010301 atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS]
|
||||
* - 000A0301 00010501 atsl in G1L from Warriors All-Stars (PC)[KOVS]
|
||||
* - 000B0301 00080601 atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS]
|
||||
* - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC]
|
||||
*/
|
||||
entry_size = 0x28;
|
||||
type = read_16bitLE(0x0c, streamFile);
|
||||
switch(type) {
|
||||
case 0x0100:
|
||||
codec = KOVS;
|
||||
fake_ext = "kvs";
|
||||
break;
|
||||
case 0x0200:
|
||||
codec = ATRAC3;
|
||||
fake_ext = "at3";
|
||||
big_endian = 1;
|
||||
break;
|
||||
case 0x0400:
|
||||
case 0x0600:
|
||||
codec = ATRAC9;
|
||||
fake_ext = "at9";
|
||||
break;
|
||||
case 0x0601:
|
||||
codec = KTAC;
|
||||
fake_ext = "ktac";
|
||||
entry_size = 0x3c;
|
||||
break;
|
||||
case 0x0800:
|
||||
codec = KTSS;
|
||||
fake_ext = "ktss";
|
||||
break;
|
||||
default:
|
||||
VGM_LOG("ATSL: unknown type %x\n", type);
|
||||
goto fail;
|
||||
}
|
||||
read_32bit = big_endian ? read_32bitBE : read_32bitLE;
|
||||
|
||||
|
||||
/* entries can point to the same file, count unique only */
|
||||
{
|
||||
int i,j;
|
||||
|
||||
total_subsongs = 0;
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
|
||||
/* parse entry header (in machine endianness) */
|
||||
for (i = 0; i < entries; i++) {
|
||||
int is_unique = 1;
|
||||
|
||||
/* 0x00: id */
|
||||
off_t entry_subfile_offset = read_32bit(header_size + i*entry_size + 0x04,streamFile);
|
||||
size_t entry_subfile_size = read_32bit(header_size + i*entry_size + 0x08,streamFile);
|
||||
/* 0x08+: channels/sample rate/num_samples/loop_start/etc (match subfile header) */
|
||||
|
||||
/* check if current entry was repeated in a prev entry */
|
||||
for (j = 0; j < i; j++) {
|
||||
off_t prev_offset = read_32bit(header_size + j*entry_size + 0x04,streamFile);
|
||||
if (prev_offset == entry_subfile_offset) {
|
||||
is_unique = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_unique)
|
||||
continue;
|
||||
|
||||
total_subsongs++;
|
||||
|
||||
/* target GET, but keep going to count subsongs */
|
||||
if (!subfile_offset && target_subsong == total_subsongs) {
|
||||
subfile_offset = entry_subfile_offset;
|
||||
subfile_size = entry_subfile_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
if (!subfile_offset || !subfile_size) goto fail;
|
||||
|
||||
|
||||
/* some kind of seek/switch table may follow (optional, found in .atsl3) */
|
||||
|
||||
|
||||
temp_streamFile = setup_subfile_streamfile(streamFile, subfile_offset,subfile_size, fake_ext);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
/* init the VGMSTREAM */
|
||||
switch(codec) {
|
||||
case ATRAC3:
|
||||
case ATRAC9:
|
||||
vgmstream = init_vgmstream_riff(temp_streamFile);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case KOVS:
|
||||
vgmstream = init_vgmstream_ogg_vorbis(temp_streamFile);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
#endif
|
||||
case KTSS:
|
||||
vgmstream = init_vgmstream_ktss(temp_streamFile);
|
||||
if (!vgmstream) goto fail;
|
||||
break;
|
||||
case KTAC:
|
||||
//vgmstream = init_vgmstream_ktac(temp_streamFile); //Koei Tecto VBR-like ATRAC9
|
||||
//if (!vgmstream) goto fail;
|
||||
//break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
|
||||
close_streamfile(temp_streamFile);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_streamFile);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
|
||||
/* .ATSL - Koei Tecmo audio container [One Piece Pirate Warriors (PS3), Warriors All-Stars (PC)] */
|
||||
VGMSTREAM* init_vgmstream_atsl(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
int type, big_endian = 0, entries;
|
||||
uint32_t subfile_offset = 0, subfile_size = 0, header_size, entry_size;
|
||||
|
||||
VGMSTREAM* (*init_vgmstream)(STREAMFILE* sf) = NULL;
|
||||
const char* fake_ext;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "ATSL"))
|
||||
goto fail;
|
||||
/* .atsl: header id (for G1L extractions), .atsl3: PS3 games, .atsl4: PS4 games */
|
||||
if (!check_extensions(sf,"atsl,atsl3,atsl4"))
|
||||
goto fail;
|
||||
|
||||
/* main header (LE) */
|
||||
header_size = read_u32le(0x04,sf);
|
||||
/* 0x08/0c: flags? */
|
||||
/* 0x10: volume? (always 1000) */
|
||||
entries = read_u32le(0x14,sf);
|
||||
/* 0x18: 0x28, or 0x30 (rarer) */
|
||||
/* 0x1c: null */
|
||||
/* 0x20: subheader size */
|
||||
/* 0x24/28: null */
|
||||
|
||||
/* Type byte may be wrong (could need header id tests instead). Example flags at 0x08/0x0c:
|
||||
* - 00010101 00020001 .atsl3 from One Piece Pirate Warriors (PS3)[ATRAC3]
|
||||
* - 00000201 00020001 .atsl3 from Fist of North Star: Ken's Rage 2 (PS3)[ATRAC3]
|
||||
* 00000301 00020101 (same)
|
||||
* - 01040301 00060301 .atsl4 from Nobunaga's Ambition: Sphere of Influence (PS4)[ATRAC9]
|
||||
* - 00060301 00040301 atsl in G1L from One Piece Pirate Warriors 3 (Vita)[ATRAC9]
|
||||
* - 00060301 00010301 atsl in G1L from One Piece Pirate Warriors 3 (PC)[KOVS]
|
||||
* - 000A0301 00010501 atsl in G1L from Warriors All-Stars (PC)[KOVS]
|
||||
* - 000B0301 00080601 atsl in G1l from Sengoku Musou Sanada Maru (Switch)[KTSS]
|
||||
* - 010C0301 01060601 .atsl from Dynasty Warriors 9 (PS4)[KTAC]
|
||||
* - 01000000 01010501 .atsl from Nioh (PC)[KOVS]
|
||||
* - 01000000 00010501 .atsl from Nioh (PC)[KOVS]
|
||||
*/
|
||||
|
||||
type = read_u16le(0x0c, sf);
|
||||
switch(type) {
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case 0x0100: /* KOVS */
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
fake_ext = "kvs";
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
case 0x0101:
|
||||
init_vgmstream = init_vgmstream_ogg_vorbis;
|
||||
fake_ext = "kvs";
|
||||
entry_size = 0x3c;
|
||||
break;
|
||||
#endif
|
||||
case 0x0200: /* ATRAC3 */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at3";
|
||||
entry_size = 0x28;
|
||||
big_endian = 1;
|
||||
break;
|
||||
case 0x0400:
|
||||
case 0x0600: /* ATRAC9 */
|
||||
init_vgmstream = init_vgmstream_riff;
|
||||
fake_ext = "at9";
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
case 0x0601: /* KTAC */
|
||||
init_vgmstream = init_vgmstream_ktac;
|
||||
fake_ext = "ktac";
|
||||
entry_size = 0x3c;
|
||||
break;
|
||||
case 0x0800: /* KTSS */
|
||||
init_vgmstream = init_vgmstream_ktss;
|
||||
fake_ext = "ktss";
|
||||
entry_size = 0x28;
|
||||
break;
|
||||
default:
|
||||
vgm_logi("ATSL: unknown type %x (report)\n", type);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* entries can point to the same file, count unique only */
|
||||
{
|
||||
int i, j;
|
||||
uint32_t (*read_u32)(off_t,STREAMFILE*) = big_endian ? read_u32be : read_u32le;
|
||||
|
||||
total_subsongs = 0;
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
|
||||
/* parse entry header (in machine endianness) */
|
||||
for (i = 0; i < entries; i++) {
|
||||
int is_unique = 1;
|
||||
|
||||
/* 0x00: id */
|
||||
uint32_t entry_subfile_offset = read_u32(header_size + i*entry_size + 0x04,sf);
|
||||
uint32_t entry_subfile_size = read_u32(header_size + i*entry_size + 0x08,sf);
|
||||
/* 0x08+: channels/sample rate/num_samples/loop_start/etc (match subfile header) */
|
||||
|
||||
/* check if current entry was repeated in a prev entry */
|
||||
for (j = 0; j < i; j++) {
|
||||
off_t prev_offset = read_u32(header_size + j*entry_size + 0x04,sf);
|
||||
if (prev_offset == entry_subfile_offset) {
|
||||
is_unique = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!is_unique)
|
||||
continue;
|
||||
|
||||
total_subsongs++;
|
||||
|
||||
/* target GET, but keep going to count subsongs */
|
||||
if (!subfile_offset && target_subsong == total_subsongs) {
|
||||
subfile_offset = entry_subfile_offset;
|
||||
subfile_size = entry_subfile_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target_subsong > total_subsongs || total_subsongs <= 0) goto fail;
|
||||
if (!subfile_offset || !subfile_size) goto fail;
|
||||
|
||||
/* some kind of seek/switch table may follow (optional, found in .atsl3) */
|
||||
|
||||
temp_sf = setup_subfile_streamfile(sf, subfile_offset, subfile_size, fake_ext);
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
/* init the VGMSTREAM */
|
||||
vgmstream = init_vgmstream(temp_sf);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
|
||||
close_streamfile(temp_sf);
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_streamfile(temp_sf);
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -38,26 +38,25 @@ static layered_layout_data* build_layered_atrac9(ktsr_header* ktsr, STREAMFILE *
|
||||
/* KTSR - Koei Tecmo sound resource countainer */
|
||||
VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE *sf_b = NULL;
|
||||
STREAMFILE* sf_b = NULL;
|
||||
ktsr_header ktsr = {0};
|
||||
int target_subsong = sf->stream_index;
|
||||
int separate_offsets = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00, sf, "KTSR"))
|
||||
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"))
|
||||
goto fail;
|
||||
|
||||
/* KTSR can be a memory file (ktsl2asbin), streams (ktsl2stbin) and global config (ktsl2gcbin)
|
||||
* This accepts ktsl2asbin with internal data, or opening external streams as subsongs.
|
||||
* This accepts .ktsl2asbin with internal data or external streams as subsongs.
|
||||
* Some info from KTSR.bt */
|
||||
|
||||
if (!is_id32be(0x00, sf, "KTSR"))
|
||||
goto fail;
|
||||
if (read_u32be(0x04, sf) != 0x777B481A) /* hash(?) id: 0x777B481A=as, 0x0294DDFC=st, 0xC638E69E=gc */
|
||||
goto fail;
|
||||
|
||||
if (target_subsong == 0) target_subsong = 1;
|
||||
ktsr.target_subsong = target_subsong;
|
||||
|
||||
@ -68,7 +67,7 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
||||
if (ktsr.is_external) {
|
||||
sf_b = open_streamfile_by_ext(sf, "ktsl2stbin");
|
||||
if (!sf_b) {
|
||||
VGM_LOG("KTSR: companion file not found\n");
|
||||
vgm_logi("KTSR: companion file '*.ktsl2stbin' not found\n");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@ -129,28 +128,23 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
case KVS: {
|
||||
VGMSTREAM *ogg_vgmstream = NULL; //TODO: meh
|
||||
STREAMFILE *sf_kvs = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "kvs");
|
||||
if (!sf_kvs) goto fail;
|
||||
VGMSTREAM* ogg_vgmstream = NULL; //TODO: meh
|
||||
STREAMFILE* temp_sf = setup_subfile_streamfile(sf_b, ktsr.stream_offsets[0], ktsr.stream_sizes[0], "kvs");
|
||||
if (!temp_sf) goto fail;
|
||||
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis(sf_kvs);
|
||||
close_streamfile(sf_kvs);
|
||||
if (ogg_vgmstream) {
|
||||
ogg_vgmstream->stream_size = vgmstream->stream_size;
|
||||
ogg_vgmstream->num_streams = vgmstream->num_streams;
|
||||
ogg_vgmstream->channel_layout = vgmstream->channel_layout;
|
||||
/* loops look shared */
|
||||
strcpy(ogg_vgmstream->stream_name, vgmstream->stream_name);
|
||||
ogg_vgmstream = init_vgmstream_ogg_vorbis(temp_sf);
|
||||
close_streamfile(temp_sf);
|
||||
if (!ogg_vgmstream) goto fail;
|
||||
|
||||
close_vgmstream(vgmstream);
|
||||
if (sf_b != sf) close_streamfile(sf_b);
|
||||
return ogg_vgmstream;
|
||||
}
|
||||
else {
|
||||
goto fail;
|
||||
}
|
||||
ogg_vgmstream->stream_size = vgmstream->stream_size;
|
||||
ogg_vgmstream->num_streams = vgmstream->num_streams;
|
||||
ogg_vgmstream->channel_layout = vgmstream->channel_layout;
|
||||
/* loops look shared */
|
||||
strcpy(ogg_vgmstream->stream_name, vgmstream->stream_name);
|
||||
|
||||
break;
|
||||
close_vgmstream(vgmstream);
|
||||
if (sf_b != sf) close_streamfile(sf_b);
|
||||
return ogg_vgmstream;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -158,7 +152,6 @@ VGMSTREAM* init_vgmstream_ktsr(STREAMFILE* sf) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream_bf(vgmstream, sf_b, ktsr.stream_offsets[0], 1))
|
||||
goto fail;
|
||||
|
||||
@ -282,13 +275,14 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
int i;
|
||||
uint32_t type;
|
||||
|
||||
type = read_u32be(offset + 0x00, sf);
|
||||
type = read_u32be(offset + 0x00, sf); /* hash-id? */
|
||||
//size = read_u32le(offset + 0x04, sf);
|
||||
|
||||
/* probably could check the flag in sound header, but the format is kinda messy */
|
||||
switch(type) { /* hash-id? */
|
||||
switch(type) {
|
||||
|
||||
case 0x38D0437D: /* external [Nioh (PC), Atelier Ryza (PC)] */
|
||||
case 0x3DEA478D: /* external [Nioh (PC)] */
|
||||
case 0xDF92529F: /* external [Atelier Ryza (PC)] */
|
||||
case 0x6422007C: /* external [Atelier Ryza (PC)] */
|
||||
/* 08 subtype? (ex. 0x522B86B9)
|
||||
@ -311,10 +305,16 @@ static int parse_ktsr_subfile(ktsr_header* ktsr, STREAMFILE* sf, off_t offset) {
|
||||
ktsr->format = read_u32le(offset + 0x14, sf);
|
||||
/* other fields will be read in the external stream */
|
||||
|
||||
ktsr->channel_layout= read_u32le(offset + 0x28, sf);
|
||||
ktsr->channel_layout = read_u32le(offset + 0x28, sf);
|
||||
|
||||
ktsr->stream_offsets[0] = read_u32le(offset + 0x34, sf);
|
||||
ktsr->stream_sizes[0] = read_u32le(offset + 0x38, sf);
|
||||
if (type == 0x3DEA478D) { /* Nioh (PC) has one less field, some files only [ABS.ktsl2asbin] */
|
||||
ktsr->stream_offsets[0] = read_u32le(offset + 0x30, sf);
|
||||
ktsr->stream_sizes[0] = read_u32le(offset + 0x34, sf);
|
||||
}
|
||||
else {
|
||||
ktsr->stream_offsets[0] = read_u32le(offset + 0x34, sf);
|
||||
ktsr->stream_sizes[0] = read_u32le(offset + 0x38, sf);
|
||||
}
|
||||
ktsr->is_external = 1;
|
||||
|
||||
if (ktsr->format != 0x05) {
|
||||
|
182
src/meta/p3d.c
182
src/meta/p3d.c
@ -1,139 +1,152 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* P3D - from Radical's Prototype 1/2 (PC/PS3/X360) */
|
||||
VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset, parse_offset, name_offset = 0;
|
||||
/* P3D - from Radical's Prototype 1/2 (PC/PS3/X360), Spider-Man 4 Beta (X360) */
|
||||
VGMSTREAM* init_vgmstream_p3d(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset, offset, name_offset = 0;
|
||||
size_t header_size, file_size, data_size;
|
||||
int loop_flag = 0, channel_count, sample_rate, codec;
|
||||
int i, name_count, text_len, block_size = 0, block_count = 0, num_samples;
|
||||
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
|
||||
uint32_t xma2_offset = 0, xma2_size = 0;
|
||||
int loop_flag, channels, sample_rate, codec;
|
||||
int i, name_count, text_len, block_size = 0, num_samples;
|
||||
uint32_t (*read_u32)(off_t,STREAMFILE*) = NULL;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile,"p3d"))
|
||||
if (!is_id32be(0x00,sf, "P3D\xFF") && /* LE: PC */
|
||||
!is_id32le(0x00,sf, "P3D\xFF")) /* BE: PS3, X360 */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x0,streamFile) != 0x503344FF && /* "P3D"\FF (LE: PC) */
|
||||
read_32bitBE(0x0,streamFile) != 0xFF443350) /* \FF"D3P" (BE: PS3, X360) */
|
||||
if (!check_extensions(sf,"p3d"))
|
||||
goto fail;
|
||||
|
||||
read_32bit = read_32bitBE(0x0,streamFile) == 0xFF443350 ? read_32bitBE : read_32bitLE;
|
||||
file_size = get_streamfile_size(streamFile);
|
||||
read_u32 = guess_endianness32bit(0x04,sf) ? read_u32be : read_u32le;
|
||||
file_size = get_streamfile_size(sf);
|
||||
|
||||
/* base header */
|
||||
header_size = read_32bit(0x4,streamFile);
|
||||
if (0x0C != header_size) goto fail;
|
||||
if (read_32bit(0x08,streamFile) != file_size) goto fail;
|
||||
if (read_32bit(0x0C,streamFile) != 0xFE000000) goto fail; /* fixed */
|
||||
if (read_32bit(0x10,streamFile) + header_size != file_size) goto fail;
|
||||
if (read_32bit(0x14,streamFile) + header_size != file_size) goto fail; /* body size again */
|
||||
if (read_32bit(0x18,streamFile) != 0x0000000A) goto fail; /* fixed */
|
||||
header_size = read_u32(0x04,sf);
|
||||
if (header_size != 0x0C) goto fail;
|
||||
if (read_u32(0x08,sf) != file_size) goto fail;
|
||||
if (read_u32(0x0C,sf) != 0xFE000000) goto fail; /* fixed */
|
||||
if (read_u32(0x10,sf) + header_size != file_size) goto fail;
|
||||
if (read_u32(0x14,sf) + header_size != file_size) goto fail; /* body size again */
|
||||
if (read_u32(0x18,sf) != 0x0000000A) goto fail; /* fixed */
|
||||
|
||||
/* header text */
|
||||
parse_offset = 0x1C;
|
||||
text_len = read_32bit(parse_offset,streamFile);
|
||||
if (9 != text_len) goto fail;
|
||||
parse_offset += 4;
|
||||
offset = 0x1C;
|
||||
text_len = read_u32(offset,sf);
|
||||
if (text_len != 9) goto fail;
|
||||
offset += 0x04;
|
||||
|
||||
/* check the type as P3D is just a generic container used in Radical's games */
|
||||
if (read_32bitBE(parse_offset+0x00,streamFile) != 0x41756469 ||
|
||||
read_32bitBE(parse_offset+0x04,streamFile) != 0x6F46696C ||
|
||||
read_16bitBE(parse_offset+0x08,streamFile) != 0x6500) goto fail; /* "AudioFile\0" */
|
||||
parse_offset += text_len + 1;
|
||||
if (!is_id64be(offset+0x00,sf, "AudioFil") || read_u16be(offset+0x08,sf) != 0x6500) /* "AudioFile\0" */
|
||||
goto fail;
|
||||
offset += text_len + 0x01;
|
||||
|
||||
/* file names: always 2 (repeated); but if it's 3 there is an extra string later */
|
||||
name_count = read_32bit(parse_offset,streamFile);
|
||||
name_count = read_u32(offset,sf);
|
||||
if (name_count != 2 && name_count != 3) goto fail; /* 2: Prototype1, 3: Prototype2 */
|
||||
parse_offset += 4;
|
||||
offset += 0x04;
|
||||
|
||||
/* skip names */
|
||||
for (i = 0; i < 2; i++) {
|
||||
if (!name_offset)
|
||||
name_offset = parse_offset + 4;
|
||||
text_len = read_32bit(parse_offset,streamFile) + 1; /* null-terminated */
|
||||
parse_offset += 4 + text_len;
|
||||
name_offset = offset + 0x04;
|
||||
text_len = read_u32(offset,sf) + 1; /* null-terminated */
|
||||
offset += 0x04 + text_len;
|
||||
}
|
||||
|
||||
/* info count? */
|
||||
if (0x01 != read_32bit(parse_offset,streamFile)) goto fail;
|
||||
parse_offset += 4;
|
||||
if (0x01 != read_u32(offset,sf)) goto fail;
|
||||
offset += 0x04;
|
||||
|
||||
/* next string can be used as a codec id */
|
||||
text_len = read_32bit(parse_offset,streamFile);
|
||||
codec = read_32bitBE(parse_offset+4,streamFile);
|
||||
parse_offset += 4 + text_len + 1;
|
||||
text_len = read_u32(offset,sf);
|
||||
codec = read_u32be(offset+0x04,sf);
|
||||
offset += 0x04 + text_len + 0x01;
|
||||
|
||||
/* extra "Music" string in Prototype 2 */
|
||||
if (name_count == 3) {
|
||||
text_len = read_32bit(parse_offset,streamFile) + 1; /* null-terminated */
|
||||
parse_offset += 4 + text_len;
|
||||
text_len = read_u32(offset,sf) + 1; /* null-terminated */
|
||||
offset += 0x04 + text_len;
|
||||
}
|
||||
|
||||
loop_flag = 0;
|
||||
|
||||
/* sub-header per codec */
|
||||
switch(codec) {
|
||||
case 0x72616470: /* "radp" (PC) */
|
||||
if (read_32bitBE(parse_offset,streamFile) != 0x52414450) goto fail; /* "RADP" */
|
||||
parse_offset += 0x04;
|
||||
channel_count = read_32bit(parse_offset+0x00,streamFile);
|
||||
sample_rate = read_32bit(parse_offset+0x04,streamFile);
|
||||
if (!is_id32be(offset,sf, "RADP"))
|
||||
goto fail;
|
||||
offset += 0x04;
|
||||
|
||||
channels = read_u32(offset+0x00,sf);
|
||||
sample_rate = read_u32(offset+0x04,sf);
|
||||
/* 0x08: ? (0x0F) */
|
||||
data_size = read_32bit(parse_offset+0x0c,streamFile);
|
||||
block_size = 0x14;
|
||||
num_samples = data_size / block_size / channel_count * 32;
|
||||
start_offset = parse_offset+0x10;
|
||||
data_size = read_u32(offset+0x0c,sf);
|
||||
block_size = 0x14;
|
||||
|
||||
num_samples = data_size / block_size / channels * 32;
|
||||
start_offset = offset + 0x10;
|
||||
break;
|
||||
|
||||
case 0x6D703300: /* "mp3\0" (PS3) */
|
||||
if ((read_32bitBE(parse_offset,streamFile) & 0xFFFFFF00) != 0x6D703300) goto fail; /* "mp3" */
|
||||
parse_offset += 0x03;
|
||||
if ((read_u32be(offset,sf) & 0xFFFFFF00) != get_id32be("mp3\0"))
|
||||
goto fail;
|
||||
offset += 0x03;
|
||||
|
||||
/* all fields LE even though the prev parts were BE */
|
||||
sample_rate = read_32bitLE(parse_offset+0x00,streamFile);
|
||||
sample_rate = read_s32le(offset+0x00,sf);
|
||||
/* 0x04: mp3 sample rate (ex. @0x00 is 47999 and @0x04 is 48000) */
|
||||
num_samples = read_32bitLE(parse_offset+0x08,streamFile);
|
||||
data_size = read_32bitLE(parse_offset+0x0c,streamFile);
|
||||
channel_count = read_32bitLE(parse_offset+0x10,streamFile);
|
||||
block_size = read_32bitLE(parse_offset+0x14,streamFile);
|
||||
num_samples = num_samples / channel_count; /* total samples */
|
||||
start_offset = parse_offset+0x18;
|
||||
num_samples = read_s32le(offset+0x08,sf);
|
||||
data_size = read_u32le(offset+0x0c,sf);
|
||||
channels = read_s32le(offset+0x10,sf);
|
||||
block_size = read_u32le(offset+0x14,sf);
|
||||
|
||||
num_samples = num_samples / channels; /* total samples */
|
||||
start_offset = offset + 0x18;
|
||||
break;
|
||||
|
||||
case 0x786D6100: /* "xma\0" (X360) */
|
||||
if (read_32bitBE(parse_offset,streamFile) != 0x584D4132) goto fail; /* "XMA2" */
|
||||
parse_offset += 0x04;
|
||||
/* 0x00: subheader size? (0x2c), 0x04: seek table size */
|
||||
data_size = read_32bitBE(parse_offset+0x08,streamFile);
|
||||
/* 0x0c: ?, 0x10: ?, 0x14/18: 0x0 */
|
||||
sample_rate = read_32bitBE(parse_offset+0x1c,streamFile);
|
||||
/* 0x20: XMA decoder params, 0x24: abr */
|
||||
block_size = read_32bitBE(parse_offset+0x28,streamFile);
|
||||
num_samples = read_32bitBE(parse_offset+0x2c,streamFile);
|
||||
/* 0x30: original file's samples */
|
||||
block_count = read_32bitBE(parse_offset+0x34,streamFile);
|
||||
channel_count = read_8bit(parse_offset+0x38,streamFile);
|
||||
/* 0x39: channel related? (stream config? channel layout?) */
|
||||
start_offset = parse_offset + 0x3c + read_32bitBE(parse_offset+0x04,streamFile);
|
||||
case 0x786D6100: { /* "xma\0" (X360) */
|
||||
uint32_t seek_size;
|
||||
|
||||
if (!is_id32be(offset,sf, "XMA2"))
|
||||
goto fail;
|
||||
offset += 0x04;
|
||||
|
||||
xma2_size = read_u32be(offset+0x00,sf);
|
||||
seek_size = read_u32be(offset+0x04,sf);
|
||||
data_size = read_u32be(offset+0x08,sf);
|
||||
/* 0x0c: ? */
|
||||
xma2_offset = offset+0x10;
|
||||
if (!read_u8(xma2_offset+0x00, sf)) /* needs "xma2" chunk (Spider-Man 4 beta has multi-streams) */
|
||||
goto fail;
|
||||
|
||||
/* loops never set */
|
||||
xma2_parse_xma2_chunk(sf, xma2_offset, &channels, &sample_rate, &loop_flag, &num_samples, NULL, NULL);
|
||||
|
||||
start_offset = offset + 0x10 + xma2_size + seek_size;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
VGM_LOG("P3D: unknown codec 0x%04x\n", codec);
|
||||
vgm_logi("P3D: unknown codec 0x%04x\n", codec);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (start_offset + data_size != file_size) goto fail;
|
||||
if (start_offset + data_size != file_size)
|
||||
goto fail;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_P3D;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = num_samples;
|
||||
vgmstream->meta_type = meta_P3D;
|
||||
if (name_offset)
|
||||
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,streamFile);
|
||||
read_string(vgmstream->stream_name,STREAM_NAME_SIZE, name_offset,sf);
|
||||
|
||||
/* codec init */
|
||||
switch(codec) {
|
||||
case 0x72616470: /* "radp" (PC) */
|
||||
vgmstream->coding_type = coding_RAD_IMA_mono;
|
||||
@ -149,7 +162,7 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
|
||||
cfg.data_size = data_size;
|
||||
/* block_size * 3 = frame size (0x60*3=0x120 or 0x40*3=0xC0) but doesn't seem to have any significance) */
|
||||
|
||||
vgmstream->codec_data = init_mpeg_custom(streamFile, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_P3D, &cfg);
|
||||
vgmstream->codec_data = init_mpeg_custom(sf, start_offset, &vgmstream->coding_type, vgmstream->channels, MPEG_P3D, &cfg);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
@ -161,23 +174,24 @@ VGMSTREAM * init_vgmstream_p3d(STREAMFILE *streamFile) {
|
||||
uint8_t buf[0x100];
|
||||
size_t bytes;
|
||||
|
||||
bytes = ffmpeg_make_riff_xma2(buf,0x100, vgmstream->num_samples, data_size, vgmstream->channels, vgmstream->sample_rate, block_count, block_size);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,data_size);
|
||||
if ( !vgmstream->codec_data ) goto fail;
|
||||
//TODO: some in Spider-Man 4 beta use 18ch but ffmpeg supports max 16ch XMA2
|
||||
bytes = ffmpeg_make_riff_xma2_from_xma2_chunk(buf, sizeof(buf), xma2_offset, xma2_size, data_size, sf);
|
||||
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,data_size);
|
||||
if (!vgmstream->codec_data) goto fail;
|
||||
vgmstream->coding_type = coding_FFmpeg;
|
||||
vgmstream->layout_type = layout_none;
|
||||
|
||||
xma_fix_raw_samples(vgmstream, streamFile, start_offset, data_size, 0, 1,1); /* samples needs adjustment */
|
||||
xma_fix_raw_samples(vgmstream, sf, start_offset, data_size, 0, 1,1); /* samples needs adjustment */
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
VGM_LOG("P3D: unknown codec 0x%04x\n", codec);
|
||||
vgm_logi("P3D: unknown codec 0x%04x\n", codec);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
@ -6,7 +6,7 @@
|
||||
static STREAMFILE* setup_ubi_lyn_streamfile(STREAMFILE* sf, off_t stream_offset, size_t interleave_size, int stream_number, int stream_count, size_t logical_size) {
|
||||
STREAMFILE *new_sf = NULL;
|
||||
deblock_config_t cfg = {0};
|
||||
VGM_LOG("so=%lx, chu=%x, n=%i, c=%i, lo=%x\n", stream_offset, interleave_size, stream_number, stream_count, logical_size);
|
||||
|
||||
cfg.stream_start = stream_offset;
|
||||
cfg.chunk_size = interleave_size;
|
||||
cfg.step_start = stream_number;
|
||||
|
@ -2,6 +2,22 @@
|
||||
#include "util.h"
|
||||
#include "vgmstream.h"
|
||||
|
||||
/* for dup/fdopen in some systems */
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* For (rarely needed) +2GB file support we use fseek64/ftell64. Those are usually available
|
||||
* but may depend on compiler.
|
||||
* - MSVC: +VS2008 should work
|
||||
* - GCC/MingW: should be available
|
||||
* - GCC/Linux: should be available but some systems may need __USE_FILE_OFFSET64,
|
||||
* that we (probably) don't want since that turns off_t to off64_t
|
||||
* - Clang: seems only defined on Linux/GNU environments, somehow emscripten is out
|
||||
* (unsure about Clang Win since apparently they define _MSC_VER)
|
||||
* - Android: API +24 if not using __USE_FILE_OFFSET64
|
||||
* Not sure if fopen64 is needed in some cases. May be work adding some compiler flag to control this manually.
|
||||
*/
|
||||
|
||||
/* MSVC fixes (though mingw uses MSVCRT but not MSC_VER, maybe use AND?) */
|
||||
#if defined(__MSVCRT__) || defined(_MSC_VER)
|
||||
@ -15,8 +31,15 @@
|
||||
#define ftello ftell
|
||||
#endif
|
||||
*/
|
||||
#define fseek_v _fseeki64 //fseek/fseeko
|
||||
#define ftell_v _ftelli64 //ftell/ftello
|
||||
|
||||
#define fopen_v fopen
|
||||
#if (_MSC_VER >= 1400)
|
||||
#define fseek_v _fseeki64
|
||||
#define ftell_v _ftelli64
|
||||
#else
|
||||
#define fseek_v fseek
|
||||
#define ftell_v ftell
|
||||
#endif
|
||||
|
||||
#ifdef fileno
|
||||
#undef fileno
|
||||
@ -29,12 +52,15 @@
|
||||
#define off_t __int64
|
||||
#endif
|
||||
|
||||
#elif defined(XBMC)
|
||||
#elif defined(XBMC) || defined(__EMSCRIPTEN__) || defined (__ANDROID__)
|
||||
#define fopen_v fopen
|
||||
#define fseek_v fseek
|
||||
#define ftell_v ftell
|
||||
|
||||
#else
|
||||
#define fopen_v fopen
|
||||
#define fseek_v fseeko64 //fseeko
|
||||
#define ftell_v ftello64 //ftelloo
|
||||
#define ftell_v ftello64 //ftello
|
||||
#endif
|
||||
|
||||
|
||||
@ -48,7 +74,7 @@ typedef struct {
|
||||
offv_t buf_offset; /* current buffer data start */
|
||||
uint8_t* buf; /* data buffer */
|
||||
size_t buf_size; /* max buffer size */
|
||||
size_t valid_size; /* current buffer size */
|
||||
size_t valid_size; /* current buffer size */
|
||||
size_t file_size; /* buffered file size */
|
||||
} STDIO_STREAMFILE;
|
||||
|
||||
@ -154,12 +180,6 @@ static void stdio_get_name(STDIO_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
strncpy(name, sf->name, name_size);
|
||||
name[name_size - 1] = '\0';
|
||||
}
|
||||
static void stdio_close(STDIO_STREAMFILE* sf) {
|
||||
if (sf->infile)
|
||||
fclose(sf->infile);
|
||||
free(sf->buf);
|
||||
free(sf);
|
||||
}
|
||||
|
||||
static STREAMFILE* stdio_open(STDIO_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
if (!filename)
|
||||
@ -187,11 +207,19 @@ static STREAMFILE* stdio_open(STDIO_STREAMFILE* sf, const char* const filename,
|
||||
|
||||
/* on failure just close and try the default path (which will probably fail a second time) */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
// a normal open, open a new file
|
||||
return open_stdio_streamfile_buffer(filename, buf_size);
|
||||
}
|
||||
|
||||
static void stdio_close(STDIO_STREAMFILE* sf) {
|
||||
if (sf->infile)
|
||||
fclose(sf->infile);
|
||||
free(sf->buf);
|
||||
free(sf);
|
||||
}
|
||||
|
||||
|
||||
static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char* const filename, size_t buf_size) {
|
||||
uint8_t* buf = NULL;
|
||||
STDIO_STREAMFILE* this_sf = NULL;
|
||||
@ -245,7 +273,7 @@ static STREAMFILE* open_stdio_streamfile_buffer(const char* const filename, size
|
||||
FILE* infile = NULL;
|
||||
STREAMFILE* sf = NULL;
|
||||
|
||||
infile = fopen(filename,"rb");
|
||||
infile = fopen_v(filename,"rb");
|
||||
if (!infile) {
|
||||
/* allow non-existing files in some cases */
|
||||
if (!vgmstream_is_virtual_filename(filename))
|
||||
@ -360,10 +388,12 @@ static offv_t buffer_get_offset(BUFFER_STREAMFILE* sf) {
|
||||
static void buffer_get_name(BUFFER_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_size); /* default */
|
||||
}
|
||||
|
||||
static STREAMFILE* buffer_open(BUFFER_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
STREAMFILE* new_inner_sf = sf->inner_sf->open(sf->inner_sf,filename,buf_size);
|
||||
return open_buffer_streamfile(new_inner_sf, buf_size); /* original buffer size is preferable? */
|
||||
}
|
||||
|
||||
static void buffer_close(BUFFER_STREAMFILE* sf) {
|
||||
sf->inner_sf->close(sf->inner_sf);
|
||||
free(sf->buf);
|
||||
@ -435,12 +465,14 @@ static size_t wrap_get_size(WRAP_STREAMFILE* sf) {
|
||||
static offv_t wrap_get_offset(WRAP_STREAMFILE* sf) {
|
||||
return sf->inner_sf->get_offset(sf->inner_sf); /* default */
|
||||
}
|
||||
static void wrap_get_name(WRAP_STREAMFILE* sf, char* name, size_t name_len) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_len); /* default */
|
||||
static void wrap_get_name(WRAP_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_size); /* default */
|
||||
}
|
||||
static void wrap_open(WRAP_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
sf->inner_sf->open(sf->inner_sf, filename, buf_size); /* default (don't wrap) */
|
||||
|
||||
static STREAMFILE* wrap_open(WRAP_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
return sf->inner_sf->open(sf->inner_sf, filename, buf_size); /* default (don't call open_wrap_streamfile) */
|
||||
}
|
||||
|
||||
static void wrap_close(WRAP_STREAMFILE* sf) {
|
||||
//sf->inner_sf->close(sf->inner_sf); /* don't close */
|
||||
free(sf);
|
||||
@ -503,9 +535,10 @@ static size_t clamp_get_size(CLAMP_STREAMFILE* sf) {
|
||||
static offv_t clamp_get_offset(CLAMP_STREAMFILE* sf) {
|
||||
return sf->inner_sf->get_offset(sf->inner_sf) - sf->start;
|
||||
}
|
||||
static void clamp_get_name(CLAMP_STREAMFILE* sf, char* name, size_t name_len) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_len); /* default */
|
||||
static void clamp_get_name(CLAMP_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_size); /* default */
|
||||
}
|
||||
|
||||
static STREAMFILE* clamp_open(CLAMP_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
char original_filename[PATH_LIMIT];
|
||||
STREAMFILE* new_inner_sf = NULL;
|
||||
@ -520,6 +553,7 @@ static STREAMFILE* clamp_open(CLAMP_STREAMFILE* sf, const char* const filename,
|
||||
return new_inner_sf;
|
||||
}
|
||||
}
|
||||
|
||||
static void clamp_close(CLAMP_STREAMFILE* sf) {
|
||||
sf->inner_sf->close(sf->inner_sf);
|
||||
free(sf);
|
||||
@ -582,13 +616,15 @@ static size_t io_get_size(IO_STREAMFILE* sf) {
|
||||
static offv_t io_get_offset(IO_STREAMFILE* sf) {
|
||||
return sf->inner_sf->get_offset(sf->inner_sf); /* default */
|
||||
}
|
||||
static void io_get_name(IO_STREAMFILE* sf, char* name, size_t name_len) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_len); /* default */
|
||||
static void io_get_name(IO_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
sf->inner_sf->get_name(sf->inner_sf, name, name_size); /* default */
|
||||
}
|
||||
|
||||
static STREAMFILE* io_open(IO_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
STREAMFILE* new_inner_sf = sf->inner_sf->open(sf->inner_sf,filename,buf_size);
|
||||
return open_io_streamfile_ex(new_inner_sf, sf->data, sf->data_size, sf->read_callback, sf->size_callback, sf->init_callback, sf->close_callback);
|
||||
}
|
||||
|
||||
static void io_close(IO_STREAMFILE* sf) {
|
||||
if (sf->close_callback)
|
||||
sf->close_callback(sf->inner_sf, sf->data);
|
||||
@ -633,7 +669,7 @@ STREAMFILE* open_io_streamfile_ex(STREAMFILE* sf, void* data, size_t data_size,
|
||||
}
|
||||
|
||||
return &this_sf->vt;
|
||||
|
||||
|
||||
fail:
|
||||
if (this_sf) free(this_sf->data);
|
||||
free(this_sf);
|
||||
@ -676,6 +712,7 @@ static void fakename_get_name(FAKENAME_STREAMFILE* sf, char* name, size_t name_s
|
||||
strncpy(name,sf->fakename, name_size);
|
||||
name[name_size - 1] = '\0';
|
||||
}
|
||||
|
||||
static STREAMFILE* fakename_open(FAKENAME_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
/* detect re-opening the file */
|
||||
if (strcmp(filename, sf->fakename) == 0) {
|
||||
@ -797,6 +834,7 @@ static offv_t multifile_get_offset(MULTIFILE_STREAMFILE* sf) {
|
||||
static void multifile_get_name(MULTIFILE_STREAMFILE* sf, char* name, size_t name_size) {
|
||||
sf->inner_sfs[0]->get_name(sf->inner_sfs[0], name, name_size);
|
||||
}
|
||||
|
||||
static STREAMFILE* multifile_open(MULTIFILE_STREAMFILE* sf, const char* const filename, size_t buf_size) {
|
||||
char original_filename[PATH_LIMIT];
|
||||
STREAMFILE* new_sf = NULL;
|
||||
@ -1219,7 +1257,7 @@ STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
|
||||
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
|
||||
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
|
||||
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
|
||||
continue;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, filename) == 0) {
|
||||
@ -1454,7 +1492,7 @@ void dump_streamfile(STREAMFILE* sf, int num) {
|
||||
get_streamfile_filename(sf, filename, sizeof(filename));
|
||||
snprintf(dumpname, sizeof(dumpname), "%s_%02i.dump", filename, num);
|
||||
|
||||
f = fopen(dumpname,"wb");
|
||||
f = fopen_v(dumpname,"wb");
|
||||
if (!f) return;
|
||||
}
|
||||
|
||||
|
@ -66,16 +66,16 @@ typedef struct _STREAMFILE {
|
||||
size_t (*get_size)(struct _STREAMFILE* sf);
|
||||
|
||||
//todo: DO NOT USE, NOT RESET PROPERLY (remove?)
|
||||
offv_t (*get_offset)(struct _STREAMFILE*);
|
||||
offv_t (*get_offset)(struct _STREAMFILE* sf);
|
||||
|
||||
/* copy current filename to name buf */
|
||||
void (*get_name)(struct _STREAMFILE* sf, char* name, size_t name_size);
|
||||
|
||||
/* open another streamfile from filename */
|
||||
struct _STREAMFILE* (*open)(struct _STREAMFILE* sf, const char* const filename, size_t buffer_size);
|
||||
struct _STREAMFILE* (*open)(struct _STREAMFILE* sf, const char* const filename, size_t buf_size);
|
||||
|
||||
/* free current STREAMFILE */
|
||||
void (*close)(struct _STREAMFILE*);
|
||||
void (*close)(struct _STREAMFILE* sf);
|
||||
|
||||
/* Substream selection for formats with subsongs.
|
||||
* Not ideal here, but it was the simplest way to pass to all init_vgmstream_x functions. */
|
||||
|
@ -140,7 +140,7 @@ static inline int clamp16(int32_t val) {
|
||||
/* transforms a string to uint32 (for comparison), but if this is static + all goes well
|
||||
* compiler should pre-calculate and use uint32 directly */
|
||||
static inline /*const*/ uint32_t get_id32be(const char* s) {
|
||||
return (uint32_t)(s[0] << 24) | (s[1] << 16) | (s[2] << 8) | (s[3] << 0);
|
||||
return (uint32_t)((uint8_t)s[0] << 24) | ((uint8_t)s[1] << 16) | ((uint8_t)s[2] << 8) | ((uint8_t)s[3] << 0);
|
||||
}
|
||||
|
||||
//static inline /*const*/ uint32_t get_id32le(const char* s) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user