mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-02-17 19:19:16 +01:00
cleanup: separate functions
This commit is contained in:
parent
bf218c08b4
commit
4b0387fb7a
@ -1,5 +1,6 @@
|
||||
#include "coding.h"
|
||||
#include "../util/channel_mappings.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
|
||||
|
@ -171,15 +171,18 @@
|
||||
<ClInclude Include="util\bitstream_msb.h" />
|
||||
<ClInclude Include="util\channel_mappings.h" />
|
||||
<ClInclude Include="util\chunks.h" />
|
||||
<ClInclude Include="util\companion_files.h" />
|
||||
<ClInclude Include="util\cri_keys.h" />
|
||||
<ClInclude Include="util\cri_utf.h" />
|
||||
<ClInclude Include="util\endianness.h" />
|
||||
<ClInclude Include="util\log.h" />
|
||||
<ClInclude Include="util\m2_psb.h" />
|
||||
<ClInclude Include="util\miniz.h" />
|
||||
<ClInclude Include="util\paths.h" />
|
||||
<ClInclude Include="util\reader_get.h" />
|
||||
<ClInclude Include="util\reader_get_nibbles.h" />
|
||||
<ClInclude Include="util\reader_put.h" />
|
||||
<ClInclude Include="util\reader_sf.h" />
|
||||
<ClInclude Include="util\samples_ops.h" />
|
||||
<ClInclude Include="util\text_reader.h" />
|
||||
</ItemGroup>
|
||||
@ -736,11 +739,13 @@
|
||||
<ClCompile Include="meta\zwdsp.c" />
|
||||
<ClCompile Include="meta\zwv.c" />
|
||||
<ClCompile Include="util\chunks.c" />
|
||||
<ClCompile Include="util\companion_files.c" />
|
||||
<ClCompile Include="util\cri_keys.c" />
|
||||
<ClCompile Include="util\cri_utf.c" />
|
||||
<ClCompile Include="util\log.c" />
|
||||
<ClCompile Include="util\m2_psb.c" />
|
||||
<ClCompile Include="util\miniz.c" />
|
||||
<ClCompile Include="util\paths.c" />
|
||||
<ClCompile Include="util\reader_put.c" />
|
||||
<ClCompile Include="util\samples_ops.c" />
|
||||
<ClCompile Include="util\text_reader.c" />
|
||||
|
@ -338,6 +338,9 @@
|
||||
<ClInclude Include="util\chunks.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\companion_files.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\cri_keys.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -356,6 +359,9 @@
|
||||
<ClInclude Include="util\miniz.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\paths.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\reader_get.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -365,6 +371,9 @@
|
||||
<ClInclude Include="util\reader_put.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\reader_sf.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="util\samples_ops.h">
|
||||
<Filter>util\Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -2029,6 +2038,9 @@
|
||||
<ClCompile Include="util\chunks.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\companion_files.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\cri_keys.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -2044,6 +2056,9 @@
|
||||
<ClCompile Include="util\miniz.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\paths.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="util\reader_put.c">
|
||||
<Filter>util\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "adx_keys.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/cri_keys.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../coding/coding.h"
|
||||
#include "ahx_keys.h"
|
||||
#include "../util/cri_keys.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
#ifdef VGM_USE_MPEG
|
||||
static int find_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey);
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
//typedef enum { ADX, HCA, VAG, RIFF, CWAV, DSP, CWAC, M4A } awb_type_t;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
#include "../util/companion_files.h"
|
||||
#include "bnsf_keys.h"
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/cri_utf.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
|
||||
typedef enum { HCA, CWAV, ADX } cpk_type_t;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* CSMP - Retro Studios sample [Metroid Prime 3 (Wii)-sfx, Donkey Kong Country Returns (Wii)-sfx] */
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/companion_files.h"
|
||||
#include "ea_eaac_streamfile.h"
|
||||
|
||||
/* EAAudioCore (aka SND10) formats, EA's current audio middleware */
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/companion_files.h"
|
||||
#include "ea_schl_streamfile.h"
|
||||
|
||||
/* header version */
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/companion_files.h"
|
||||
#include "../util/chunks.h"
|
||||
#include "ogg_vorbis_streamfile.h"
|
||||
#include "encrypted_bgm_streamfile.h"
|
||||
#include "encrypted_mc161_streamfile.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
static int get_subsongs(STREAMFILE* sf, off_t fsb5_offset, size_t fsb5_size);
|
||||
@ -16,13 +17,14 @@ VGMSTREAM* init_vgmstream_fsb5_fev_bank(STREAMFILE* sf) {
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "RIFF"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x08,sf, "FEV "))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf, "bank"))
|
||||
goto fail;
|
||||
|
||||
if (read_u32be(0x00,sf) != 0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
if (read_u32be(0x08,sf) != 0x46455620) /* "FEV " */
|
||||
goto fail;
|
||||
version = read_u32le(0x14,sf); /* newer FEV have some kind of sub-version at 0x18 */
|
||||
|
||||
/* .fev is an event format referencing various external .fsb, but FMOD can bake .fev and .fsb to
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "meta.h"
|
||||
#include "../util/companion_files.h"
|
||||
#include "fsb_keys.h"
|
||||
#include "fsb_encrypted_streamfile.h"
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
/* GSP+GSB - from Tecmo's Super Swing Golf 1 & 2 (Wii), Quantum Theory (PS3/X360) */
|
||||
VGMSTREAM* init_vgmstream_gsp_gsb(STREAMFILE* sf) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "../coding/coding.h"
|
||||
#include "../coding/hca_decoder_clhca.h"
|
||||
#include "../util/channel_mappings.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
#ifdef VGM_DEBUG_OUTPUT
|
||||
//#define HCA_BRUTEFORCE
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* LucasArts iMUSE (Interactive Music Streaming Engine) formats */
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
static void load_name(char* name, size_t name_size, STREAMFILE* sf, int big_endian, int total_subsongs, int target_subsong);
|
||||
@ -20,17 +21,17 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) {
|
||||
|
||||
|
||||
/* checks */
|
||||
/* .nub: standard
|
||||
* .nub2: rare [iDOLM@STER - Gravure For You (PS3)] */
|
||||
if (!check_extensions(sf, "nub,nub2"))
|
||||
goto fail;
|
||||
|
||||
version = read_32bitBE(0x00,sf);
|
||||
version = read_u32be(0x00,sf);
|
||||
if (version != 0x00020000 && /* v2.0 (rare, ex. Ridge Race 6 (X360)) */
|
||||
version != 0x00020100 && /* v2.1 (common) */
|
||||
version != 0x01020100) /* same but LE (seen in PSP/PC games, except PS4) */
|
||||
goto fail;
|
||||
if (read_32bitBE(0x04,sf) != 0x00000000) /* null */
|
||||
if (read_u32be(0x04,sf) != 0x00000000) /* null */
|
||||
goto fail;
|
||||
|
||||
/* .nub: standard
|
||||
* .nub2: rare [iDOLM@STER - Gravure For You (PS3)] */
|
||||
if (!check_extensions(sf, "nub,nub2"))
|
||||
goto fail;
|
||||
|
||||
/* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* .SBK - from Addiction Pinball (PC) */
|
||||
VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) {
|
||||
@ -11,13 +13,12 @@ VGMSTREAM *init_vgmstream_sbk(STREAMFILE *sf) {
|
||||
int target_subsong = sf->stream_index, total_subsongs, loop_flag, is_streamed;
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(sf, "sbk"))
|
||||
if (!is_id32be(0x00,sf, "RIFF"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x08,sf, "SBNK"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_u32be(0x00, sf) != 0x52494646) /* "RIFF" */
|
||||
goto fail;
|
||||
if (read_u32be(0x08, sf) != 0x53424E4B) /* "SBNK" */
|
||||
if (!check_extensions(sf, "sbk"))
|
||||
goto fail;
|
||||
|
||||
if (!find_chunk_le(sf, 0x57415649, 0x0c, 0, &table_offset, &table_size)) /* "WAVI" */
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* SGXD - Sony/SCEI's format (SGB+SGH / SGD / SGX) */
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* SXD - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "txth_streamfile.h"
|
||||
#include "../util/text_reader.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/paths.h"
|
||||
|
||||
#define TXT_LINE_MAX 2048 /* probably ~1000 would be ok */
|
||||
#define TXT_LINE_KEY_MAX 128
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "../base/mixing.h"
|
||||
#include "../base/plugins.h"
|
||||
#include "../util/text_reader.h"
|
||||
#include "../util/paths.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
typedef enum { MSADPCM, DSP, MP3, XMA2 } ckd_codec;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../layout/layout.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/endianness.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
typedef enum { PCM, UBI, PSX, DSP, XIMA, ATRAC3, XMA2, MP3, SILENCE } ubi_hx_codec;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
/* VXN - from Gameloft mobile games */
|
||||
@ -11,11 +12,12 @@ VGMSTREAM* init_vgmstream_vxn(STREAMFILE* sf) {
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "VoxN"))
|
||||
goto fail;
|
||||
|
||||
if (!check_extensions(sf,"vxn"))
|
||||
goto fail;
|
||||
|
||||
if (!is_id32be(0x00,sf, "VoxN"))
|
||||
goto fail;
|
||||
/* 0x04: chunk size */
|
||||
/* 0x08: ASCII version? ("0.0.1") */
|
||||
if (read_u32le(0x10,sf) != get_streamfile_size(sf))
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
//#include <ctype.h>
|
||||
|
||||
/* .WBK - seen in some Treyarch games [Spider-Man 2, Ultimate Spider-Man, Call of Duty 2: Big Red One] */
|
||||
|
@ -1,64 +1,65 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
/* XAU - XPEC Entertainment sound format (Beat Down PS2/Xbox, Spectral Force Chronicle [SLPM-65967]) */
|
||||
VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
/* XAU - XPEC Entertainment sound format [Beat Down (PS2/Xbox), Spectral Force Chronicle (PS2)] */
|
||||
VGMSTREAM* init_vgmstream_xau(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count, type, loop_start, loop_end;
|
||||
int loop_flag, channels, type, loop_start, loop_end;
|
||||
|
||||
|
||||
/* check extension */
|
||||
if (!check_extensions(streamFile, "xau"))
|
||||
goto fail;
|
||||
|
||||
/* check header */
|
||||
if (read_32bitBE(0x00,streamFile) != 0x58415500) /* "XAU\0" "*/
|
||||
if (!is_id32be(0x00,sf, "XAU\0"))
|
||||
goto fail;
|
||||
if (read_32bitLE(0x08,streamFile) != 0x40) /* header start */
|
||||
|
||||
if (!check_extensions(sf, "xau"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitLE(0x08,sf) != 0x40) /* header start */
|
||||
goto fail;
|
||||
|
||||
/* 0x04: version? (0x100) */
|
||||
type = read_32bitBE(0x0c, streamFile);
|
||||
loop_start = read_32bitLE(0x10, streamFile);
|
||||
loop_end = read_32bitLE(0x14, streamFile);
|
||||
loop_flag = (loop_end > 0);
|
||||
type = read_32bitBE(0x0c, sf);
|
||||
loop_start = read_32bitLE(0x10, sf);
|
||||
loop_end = read_32bitLE(0x14, sf);
|
||||
loop_flag = (loop_end > 0);
|
||||
|
||||
channel_count = read_8bit(0x18,streamFile);
|
||||
channels = read_8bit(0x18,sf);
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->channels = channels;
|
||||
vgmstream->meta_type = meta_XAU;
|
||||
|
||||
/* miniheader over a common header with some tweaks, so we'll simplify parsing */
|
||||
switch(type) {
|
||||
case 0x50533200: /* "PS2\0" */
|
||||
if (read_32bitBE(0x40,streamFile) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */
|
||||
/* miniheader over a common header with some tweaks, so we'll simplify parsing */
|
||||
switch(type) {
|
||||
case 0x50533200: /* "PS2\0" */
|
||||
if (read_32bitBE(0x40,sf) != 0x56414770) goto fail; /* mutant "VAGp" (long header size) */
|
||||
|
||||
start_offset = 0x800;
|
||||
vgmstream->sample_rate = read_32bitBE(0x50, streamFile);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,streamFile) * channel_count, channel_count);
|
||||
start_offset = 0x800;
|
||||
vgmstream->sample_rate = read_32bitBE(0x50, sf);
|
||||
vgmstream->num_samples = ps_bytes_to_samples(read_32bitBE(0x4C,sf) * channels, channels);
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
vgmstream->coding_type = coding_PSX;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x8000;
|
||||
break;
|
||||
vgmstream->interleave_block_size = 0x8000;
|
||||
break;
|
||||
|
||||
case 0x58420000: /* "XB\0\0" */
|
||||
if (read_32bitBE(0x40,streamFile) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */
|
||||
case 0x58420000: /* "XB\0\0" */
|
||||
if (read_32bitBE(0x40,sf) != 0x52494646) goto fail; /* mutant "RIFF" (sometimes wrong RIFF size) */
|
||||
|
||||
/* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */
|
||||
if (!find_chunk_le(streamFile, 0x64617461, 0x4c, 0, &start_offset, NULL) )
|
||||
goto fail;
|
||||
/* start offset: find "data" chunk, as sometimes there is a "smpl" chunk at the start or the end (same as loop_start/end) */
|
||||
if (!find_chunk_le(sf, 0x64617461, 0x4c, 0, &start_offset, NULL) )
|
||||
goto fail;
|
||||
|
||||
vgmstream->sample_rate = read_32bitLE(0x58, streamFile);
|
||||
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, streamFile), channel_count);
|
||||
vgmstream->sample_rate = read_32bitLE(0x58, sf);
|
||||
vgmstream->num_samples = xbox_ima_bytes_to_samples(read_32bitLE(start_offset-4, sf), channels);
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
@ -66,13 +67,13 @@ VGMSTREAM * init_vgmstream_xau(STREAMFILE *streamFile) {
|
||||
vgmstream->layout_type = layout_none;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
if (!vgmstream_open_stream(vgmstream,sf,start_offset))
|
||||
goto fail;
|
||||
|
||||
return vgmstream;
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "xvag_streamfile.h"
|
||||
#include "../util/chunks.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
@ -41,12 +42,13 @@ VGMSTREAM* init_vgmstream_xvag(STREAMFILE* sf) {
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!is_id32be(0x00,sf, "XVAG"))
|
||||
goto fail;
|
||||
|
||||
/* .xvag: standard
|
||||
* (extensionless): The Last of Us (PS3) speech files */
|
||||
if (!check_extensions(sf,"xvag,"))
|
||||
goto fail;
|
||||
if (!is_id32be(0x00,sf, "XVAG"))
|
||||
goto fail;
|
||||
|
||||
/* endian flag (XVAGs of the same game can use BE or LE, usually when reusing from other platforms) */
|
||||
xvag.big_endian = read_8bit(0x08,sf) & 0x01;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _XWB_XSB_H_
|
||||
#define _XWB_XSB_H_
|
||||
#include "meta.h"
|
||||
#include "../util/companion_files.h"
|
||||
|
||||
#define XSB_XACT1_0_MAX 5 /* Unreal Championship (Xbox) */
|
||||
#define XSB_XACT1_1_MAX 8 /* Die Hard: Vendetta (Xbox) */
|
||||
|
233
src/streamfile.c
233
src/streamfile.c
@ -2,6 +2,7 @@
|
||||
#include "util.h"
|
||||
#include "vgmstream.h"
|
||||
#include "util/reader_sf.h"
|
||||
#include "util/paths.h"
|
||||
#include <string.h>
|
||||
|
||||
/* for dup/fdopen in some systems */
|
||||
@ -9,15 +10,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
//TODO: move
|
||||
#ifndef DIR_SEPARATOR
|
||||
#if defined (_WIN32) || defined (WIN32)
|
||||
#define DIR_SEPARATOR '\\'
|
||||
#else
|
||||
#define DIR_SEPARATOR '/'
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* For (rarely needed) +2GB file support we use fseek64/ftell64. Those are usually available
|
||||
* but may depend on compiler.
|
||||
* - MSVC: +VS2008 should work
|
||||
@ -1205,162 +1197,6 @@ size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE*
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
|
||||
char keyname[PATH_LIMIT];
|
||||
char filename[PATH_LIMIT];
|
||||
const char *path, *ext;
|
||||
STREAMFILE* sf_key = NULL;
|
||||
size_t keysize;
|
||||
|
||||
get_streamfile_name(sf, filename, sizeof(filename));
|
||||
|
||||
if (strlen(filename)+4 > sizeof(keyname)) goto fail;
|
||||
|
||||
/* try to open a keyfile using variations */
|
||||
{
|
||||
ext = strrchr(filename,'.');
|
||||
if (ext!=NULL) ext = ext+1;
|
||||
|
||||
path = strrchr(filename, DIR_SEPARATOR);
|
||||
if (path!=NULL) path = path+1;
|
||||
|
||||
/* "(name.ext)key" */
|
||||
strcpy(keyname, filename);
|
||||
strcat(keyname, "key");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
|
||||
/* "(name.ext)KEY" */
|
||||
/*
|
||||
strcpy(keyname+strlen(keyname)-3,"KEY");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
*/
|
||||
|
||||
|
||||
/* "(.ext)key" */
|
||||
if (path) {
|
||||
strcpy(keyname, filename);
|
||||
keyname[path-filename] = '\0';
|
||||
strcat(keyname, ".");
|
||||
} else {
|
||||
strcpy(keyname, ".");
|
||||
}
|
||||
if (ext) strcat(keyname, ext);
|
||||
strcat(keyname, "key");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
|
||||
/* "(.ext)KEY" */
|
||||
/*
|
||||
strcpy(keyname+strlen(keyname)-3,"KEY");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
*/
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
found:
|
||||
keysize = get_streamfile_size(sf_key);
|
||||
if (keysize > buf_size) goto fail;
|
||||
|
||||
if (read_streamfile(buf, 0, keysize, sf_key) != keysize)
|
||||
goto fail;
|
||||
|
||||
close_streamfile(sf_key);
|
||||
return keysize;
|
||||
|
||||
fail:
|
||||
close_streamfile(sf_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
|
||||
return read_filemap_file_pos(sf, file_num, NULL);
|
||||
}
|
||||
|
||||
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
|
||||
char filename[PATH_LIMIT];
|
||||
off_t txt_offset, file_size;
|
||||
STREAMFILE* sf_map = NULL;
|
||||
int file_pos = 0;
|
||||
|
||||
sf_map = open_streamfile_by_filename(sf, ".txtm");
|
||||
if (!sf_map) goto fail;
|
||||
|
||||
get_streamfile_filename(sf, filename, sizeof(filename));
|
||||
|
||||
txt_offset = read_bom(sf_map);
|
||||
file_size = get_streamfile_size(sf_map);
|
||||
|
||||
/* read lines and find target filename, format is (filename): value1, ... valueN */
|
||||
while (txt_offset < file_size) {
|
||||
char line[0x2000];
|
||||
char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 };
|
||||
int ok, bytes_read, line_ok;
|
||||
|
||||
bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok);
|
||||
if (!line_ok) goto fail;
|
||||
|
||||
txt_offset += bytes_read;
|
||||
|
||||
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
|
||||
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
|
||||
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
|
||||
/* better way? */
|
||||
if (strcmp(line, "#@reset-pos") == 0) {
|
||||
file_pos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, filename) == 0) {
|
||||
int n;
|
||||
char subval[PATH_LIMIT];
|
||||
const char* current = val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= file_num; i++) {
|
||||
if (current[0] == '\0')
|
||||
goto fail;
|
||||
|
||||
ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n);
|
||||
if (ok != 1)
|
||||
goto fail;
|
||||
|
||||
if (i == file_num) {
|
||||
if (p_pos) *p_pos = file_pos;
|
||||
|
||||
close_streamfile(sf_map);
|
||||
return open_streamfile_by_filename(sf, subval);
|
||||
}
|
||||
|
||||
current += n;
|
||||
if (current[0] == ',')
|
||||
current++;
|
||||
}
|
||||
}
|
||||
file_pos++;
|
||||
}
|
||||
|
||||
fail:
|
||||
close_streamfile(sf_map);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fix_dir_separators(char* filename) {
|
||||
char c;
|
||||
int i = 0;
|
||||
while ((c = filename[i]) != '\0') {
|
||||
if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\'))
|
||||
filename[i] = DIR_SEPARATOR;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
|
||||
char filename[PATH_LIMIT];
|
||||
const char* ext = NULL;
|
||||
@ -1393,73 +1229,6 @@ int check_extensions(STREAMFILE* sf, const char* cmp_exts) {
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/**
|
||||
* Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size.
|
||||
* Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF).
|
||||
* The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt ").
|
||||
* "full_chunk_size" signals chunk_size includes 4+4+data.
|
||||
*
|
||||
* returns 0 on failure
|
||||
*/
|
||||
static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) {
|
||||
int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE;
|
||||
int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE;
|
||||
off_t offset, max_offset;
|
||||
size_t file_size = get_streamfile_size(sf);
|
||||
|
||||
if (max_size == 0)
|
||||
max_size = file_size;
|
||||
|
||||
offset = start_offset;
|
||||
max_offset = offset + max_size;
|
||||
if (max_offset > file_size)
|
||||
max_offset = file_size;
|
||||
|
||||
|
||||
/* read chunks */
|
||||
while (offset < max_offset) {
|
||||
uint32_t chunk_type = read_32bit_type(offset + 0x00,sf);
|
||||
uint32_t chunk_size = read_32bit_size(offset + 0x04,sf);
|
||||
|
||||
if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
if (chunk_type == chunk_id) {
|
||||
if (out_chunk_offset) *out_chunk_offset = offset + 0x08;
|
||||
if (out_chunk_size) *out_chunk_size = chunk_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
|
||||
if (chunk_size == 0 && zero_size_end)
|
||||
return 0;
|
||||
|
||||
offset += full_chunk_size ? chunk_size : 0x08 + chunk_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0);
|
||||
}
|
||||
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0);
|
||||
}
|
||||
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end);
|
||||
}
|
||||
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0);
|
||||
}
|
||||
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0);
|
||||
}
|
||||
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 0);
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/* copies name as-is (may include full path included) */
|
||||
void get_streamfile_name(STREAMFILE* sf, char* buffer, size_t size) {
|
||||
sf->get_name(sf, buffer, size);
|
||||
|
@ -178,34 +178,11 @@ size_t read_string_utf16(char* buf, size_t buf_size, off_t offset, STREAMFILE* s
|
||||
size_t read_string_utf16le(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
|
||||
size_t read_string_utf16be(char* buf, size_t buf_size, off_t offset, STREAMFILE* sf);
|
||||
|
||||
/* Opens a file containing decryption keys and copies to buffer.
|
||||
* Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames.
|
||||
* returns size of key if found and copied */
|
||||
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
|
||||
|
||||
/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match
|
||||
* then loads the associated companion file if one is found */
|
||||
STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num);
|
||||
STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos);
|
||||
|
||||
|
||||
/* hack to allow relative paths in various OSs */
|
||||
void fix_dir_separators(char* filename);
|
||||
|
||||
/* Checks if the stream filename is one of the extensions (comma-separated, ex. "adx" or "adx,aix").
|
||||
* Empty is ok to accept files without extension ("", "adx,,aix"). Returns 0 on failure */
|
||||
int check_extensions(STREAMFILE* sf, const char* cmp_exts);
|
||||
|
||||
/* chunk-style file helpers */
|
||||
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end);
|
||||
/* find a RIFF-style chunk (with chunk_size not including id and size) */
|
||||
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */
|
||||
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian);
|
||||
|
||||
/* filename helpers */
|
||||
void get_streamfile_name(STREAMFILE* sf, char* buf, size_t size);
|
||||
void get_streamfile_filename(STREAMFILE* sf, char* buf, size_t size);
|
||||
|
@ -33,3 +33,71 @@ int next_chunk(chunk_t* chunk, STREAMFILE* sf) {
|
||||
/* more chunks remain */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ************************************************************************* */
|
||||
|
||||
/**
|
||||
* Find a chunk starting from an offset, and save its offset/size (if not NULL), with offset after id/size.
|
||||
* Works for chunked headers in the form of "chunk_id chunk_size (data)"xN (ex. RIFF).
|
||||
* The start_offset should be the first actual chunk (not "RIFF" or "WAVE" but "fmt ").
|
||||
* "full_chunk_size" signals chunk_size includes 4+4+data.
|
||||
*
|
||||
* returns 0 on failure
|
||||
*/
|
||||
static int find_chunk_internal(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_type, int big_endian_size, int zero_size_end) {
|
||||
int32_t (*read_32bit_type)(off_t,STREAMFILE*) = big_endian_type ? read_32bitBE : read_32bitLE;
|
||||
int32_t (*read_32bit_size)(off_t,STREAMFILE*) = big_endian_size ? read_32bitBE : read_32bitLE;
|
||||
off_t offset, max_offset;
|
||||
size_t file_size = get_streamfile_size(sf);
|
||||
|
||||
if (max_size == 0)
|
||||
max_size = file_size;
|
||||
|
||||
offset = start_offset;
|
||||
max_offset = offset + max_size;
|
||||
if (max_offset > file_size)
|
||||
max_offset = file_size;
|
||||
|
||||
|
||||
/* read chunks */
|
||||
while (offset < max_offset) {
|
||||
uint32_t chunk_type = read_32bit_type(offset + 0x00,sf);
|
||||
uint32_t chunk_size = read_32bit_size(offset + 0x04,sf);
|
||||
|
||||
if (chunk_type == 0xFFFFFFFF || chunk_size == 0xFFFFFFFF)
|
||||
return 0;
|
||||
|
||||
if (chunk_type == chunk_id) {
|
||||
if (out_chunk_offset) *out_chunk_offset = offset + 0x08;
|
||||
if (out_chunk_size) *out_chunk_size = chunk_size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* empty chunk with 0 size, seen in some formats (XVAG uses it as end marker, Wwise doesn't) */
|
||||
if (chunk_size == 0 && zero_size_end)
|
||||
return 0;
|
||||
|
||||
offset += full_chunk_size ? chunk_size : 0x08 + chunk_size;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 1, 0);
|
||||
}
|
||||
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk(sf, chunk_id, start_offset, full_chunk_size, out_chunk_offset, out_chunk_size, 0, 0);
|
||||
}
|
||||
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian_size, int zero_size_end) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, 0, full_chunk_size, out_chunk_offset, out_chunk_size, 1, big_endian_size, zero_size_end);
|
||||
}
|
||||
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 0, 0);
|
||||
}
|
||||
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, 1, 1, 0);
|
||||
}
|
||||
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t *out_chunk_offset, size_t *out_chunk_size, int big_endian) {
|
||||
return find_chunk_internal(sf, chunk_id, start_offset, max_size, 0, out_chunk_offset, out_chunk_size, big_endian, big_endian, 0);
|
||||
}
|
||||
|
@ -26,4 +26,16 @@ enum {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* chunk-style file helpers (the above is more performant, this is mainly for quick checks) */
|
||||
int find_chunk_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, int full_chunk_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian_size, int zero_size_end);
|
||||
/* find a RIFF-style chunk (with chunk_size not including id and size) */
|
||||
int find_chunk_riff_le(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
int find_chunk_riff_be(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size);
|
||||
/* same with chunk ids in variable endianess (so instead of "fmt " has " tmf" */
|
||||
int find_chunk_riff_ve(STREAMFILE* sf, uint32_t chunk_id, off_t start_offset, size_t max_size, off_t* p_chunk_offset, size_t* p_chunk_size, int big_endian);
|
||||
|
||||
|
||||
#endif
|
||||
|
148
src/util/companion_files.c
Normal file
148
src/util/companion_files.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include "companion_files.h"
|
||||
#include "paths.h"
|
||||
#include "../vgmstream.h"
|
||||
|
||||
|
||||
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf) {
|
||||
char keyname[PATH_LIMIT];
|
||||
char filename[PATH_LIMIT];
|
||||
const char *path, *ext;
|
||||
STREAMFILE* sf_key = NULL;
|
||||
size_t keysize;
|
||||
|
||||
get_streamfile_name(sf, filename, sizeof(filename));
|
||||
|
||||
if (strlen(filename)+4 > sizeof(keyname)) goto fail;
|
||||
|
||||
/* try to open a keyfile using variations */
|
||||
{
|
||||
ext = strrchr(filename,'.');
|
||||
if (ext!=NULL) ext = ext+1;
|
||||
|
||||
path = strrchr(filename, DIR_SEPARATOR);
|
||||
if (path!=NULL) path = path+1;
|
||||
|
||||
/* "(name.ext)key" */
|
||||
strcpy(keyname, filename);
|
||||
strcat(keyname, "key");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
|
||||
/* "(name.ext)KEY" */
|
||||
/*
|
||||
strcpy(keyname+strlen(keyname)-3,"KEY");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
*/
|
||||
|
||||
|
||||
/* "(.ext)key" */
|
||||
if (path) {
|
||||
strcpy(keyname, filename);
|
||||
keyname[path-filename] = '\0';
|
||||
strcat(keyname, ".");
|
||||
} else {
|
||||
strcpy(keyname, ".");
|
||||
}
|
||||
if (ext) strcat(keyname, ext);
|
||||
strcat(keyname, "key");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
|
||||
/* "(.ext)KEY" */
|
||||
/*
|
||||
strcpy(keyname+strlen(keyname)-3,"KEY");
|
||||
sf_key = sf->open(sf, keyname, STREAMFILE_DEFAULT_BUFFER_SIZE);
|
||||
if (sf_key) goto found;
|
||||
*/
|
||||
|
||||
goto fail;
|
||||
}
|
||||
|
||||
found:
|
||||
keysize = get_streamfile_size(sf_key);
|
||||
if (keysize > buf_size) goto fail;
|
||||
|
||||
if (read_streamfile(buf, 0, keysize, sf_key) != keysize)
|
||||
goto fail;
|
||||
|
||||
close_streamfile(sf_key);
|
||||
return keysize;
|
||||
|
||||
fail:
|
||||
close_streamfile(sf_key);
|
||||
return 0;
|
||||
}
|
||||
|
||||
STREAMFILE* read_filemap_file(STREAMFILE* sf, int file_num) {
|
||||
return read_filemap_file_pos(sf, file_num, NULL);
|
||||
}
|
||||
|
||||
STREAMFILE* read_filemap_file_pos(STREAMFILE* sf, int file_num, int* p_pos) {
|
||||
char filename[PATH_LIMIT];
|
||||
off_t txt_offset, file_size;
|
||||
STREAMFILE* sf_map = NULL;
|
||||
int file_pos = 0;
|
||||
|
||||
sf_map = open_streamfile_by_filename(sf, ".txtm");
|
||||
if (!sf_map) goto fail;
|
||||
|
||||
get_streamfile_filename(sf, filename, sizeof(filename));
|
||||
|
||||
txt_offset = read_bom(sf_map);
|
||||
file_size = get_streamfile_size(sf_map);
|
||||
|
||||
/* read lines and find target filename, format is (filename): value1, ... valueN */
|
||||
while (txt_offset < file_size) {
|
||||
char line[0x2000];
|
||||
char key[PATH_LIMIT] = { 0 }, val[0x2000] = { 0 };
|
||||
int ok, bytes_read, line_ok;
|
||||
|
||||
bytes_read = read_line(line, sizeof(line), txt_offset, sf_map, &line_ok);
|
||||
if (!line_ok) goto fail;
|
||||
|
||||
txt_offset += bytes_read;
|
||||
|
||||
/* get key/val (ignores lead/trailing spaces, stops at comment/separator) */
|
||||
ok = sscanf(line, " %[^\t#:] : %[^\t#\r\n] ", key, val);
|
||||
if (ok != 2) { /* ignore line if no key=val (comment or garbage) */
|
||||
/* better way? */
|
||||
if (strcmp(line, "#@reset-pos") == 0) {
|
||||
file_pos = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(key, filename) == 0) {
|
||||
int n;
|
||||
char subval[PATH_LIMIT];
|
||||
const char* current = val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= file_num; i++) {
|
||||
if (current[0] == '\0')
|
||||
goto fail;
|
||||
|
||||
ok = sscanf(current, " %[^\t#\r\n,]%n ", subval, &n);
|
||||
if (ok != 1)
|
||||
goto fail;
|
||||
|
||||
if (i == file_num) {
|
||||
if (p_pos) *p_pos = file_pos;
|
||||
|
||||
close_streamfile(sf_map);
|
||||
return open_streamfile_by_filename(sf, subval);
|
||||
}
|
||||
|
||||
current += n;
|
||||
if (current[0] == ',')
|
||||
current++;
|
||||
}
|
||||
}
|
||||
file_pos++;
|
||||
}
|
||||
|
||||
fail:
|
||||
close_streamfile(sf_map);
|
||||
return NULL;
|
||||
}
|
16
src/util/companion_files.h
Normal file
16
src/util/companion_files.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _COMPANION_FILES_H
|
||||
#define _COMPANION_FILES_H
|
||||
|
||||
#include "../streamfile.h"
|
||||
|
||||
/* Opens a file containing decryption keys and copies to buffer.
|
||||
* Tries "(name.ext)key" (per song), "(.ext)key" (per folder) keynames.
|
||||
* returns size of key if found and copied */
|
||||
size_t read_key_file(uint8_t* buf, size_t buf_size, STREAMFILE* sf);
|
||||
|
||||
/* Opens .txtm file containing file:companion file(-s) mappings and tries to see if there's a match
|
||||
* then loads the associated companion file if one is found */
|
||||
STREAMFILE* read_filemap_file(STREAMFILE *sf, int file_num);
|
||||
STREAMFILE* read_filemap_file_pos(STREAMFILE *sf, int file_num, int* p_pos);
|
||||
|
||||
#endif
|
11
src/util/paths.c
Normal file
11
src/util/paths.c
Normal file
@ -0,0 +1,11 @@
|
||||
#include "paths.h"
|
||||
|
||||
void fix_dir_separators(char* filename) {
|
||||
char c;
|
||||
int i = 0;
|
||||
while ((c = filename[i]) != '\0') {
|
||||
if ((c == '\\' && DIR_SEPARATOR == '/') || (c == '/' && DIR_SEPARATOR == '\\'))
|
||||
filename[i] = DIR_SEPARATOR;
|
||||
i++;
|
||||
}
|
||||
}
|
17
src/util/paths.h
Normal file
17
src/util/paths.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef _PATHS_H
|
||||
#define _PATHS_H
|
||||
|
||||
#ifndef DIR_SEPARATOR
|
||||
#if defined (_WIN32) || defined (WIN32)
|
||||
#define DIR_SEPARATOR '\\'
|
||||
#else
|
||||
#define DIR_SEPARATOR '/'
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* hack to allow relative paths in various OSs */
|
||||
void fix_dir_separators(char* filename);
|
||||
|
||||
//const char* filename_extension(const char* pathname);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user