cleanup: misc doc/fixes

This commit is contained in:
bnnm 2024-07-14 20:24:53 +02:00
parent 5f5eacd824
commit 6805937d1b
10 changed files with 203 additions and 181 deletions

View File

@ -442,6 +442,7 @@ bool VgmstreamPlugin::play(const char * filename, VFSFile & file) {
render_vgmstream(buffer, to_do, vgmstream); render_vgmstream(buffer, to_do, vgmstream);
write_audio(buffer, to_do * sizeof(short) * output_channels); write_audio(buffer, to_do * sizeof(short) * output_channels);
//TODO: detect how many written
decode_pos_samples += to_do; decode_pos_samples += to_do;
} }

View File

@ -901,7 +901,7 @@ static int write_file(VGMSTREAM* vgmstream, cli_config* cfg) {
render_vgmstream(buf, to_get, vgmstream); render_vgmstream(buf, to_get, vgmstream);
swap_samples_le(buf, channels * to_get); /* write PC endian */ swap_samples_le(buf, channels * to_get); /* change to WAV (LE) endian if PC is Big Endian */
fwrite(buf, sizeof(sample_t), to_get * channels, outfile); fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
/* should write infinitely until program kill */ /* should write infinitely until program kill */
} }
@ -929,7 +929,7 @@ static int write_file(VGMSTREAM* vgmstream, cli_config* cfg) {
render_vgmstream(buf, to_get, vgmstream); render_vgmstream(buf, to_get, vgmstream);
if (!cfg->decode_only) { if (!cfg->decode_only) {
swap_samples_le(buf, channels * to_get); /* write PC endian */ swap_samples_le(buf, channels * to_get); /* change to WAV (LE) endian if PC is Big Endian */
fwrite(buf, sizeof(sample_t), to_get * channels, outfile); fwrite(buf, sizeof(sample_t), to_get * channels, outfile);
} }
} }

View File

@ -4,26 +4,26 @@
/* Must pass at least 8 bytes of data to this function. /* Must pass at least 8 bytes of data to this function.
* Returns <0 on non-match, or header size on success. */ * Returns <0 on non-match, or header size on success. */
int clHCA_isOurFile(const void *data, unsigned int size); int clHCA_isOurFile(const void* data, unsigned int size);
/* The opaque state structure. */ /* The opaque state structure. */
typedef struct clHCA clHCA; typedef struct clHCA clHCA;
/* In case you wish to allocate and reset the structure on your own. */ /* In case you wish to allocate and reset the structure on your own. */
int clHCA_sizeof(void); int clHCA_sizeof(void);
void clHCA_clear(clHCA *); void clHCA_clear(clHCA* hca);
void clHCA_done(clHCA *); void clHCA_done(clHCA* hca);
/* Or you could let the library allocate it. */ /* Or you could let the library allocate it. */
clHCA * clHCA_new(void); clHCA* clHCA_new(void);
void clHCA_delete(clHCA *); void clHCA_delete(clHCA* hca);
/* Parses the HCA header. Must be called before any decoding may be performed, /* Parses the HCA header. Must be called before any decoding may be performed,
* and size must be at least headerSize long. The recommended way is to detect * and size must be at least headerSize long. The recommended way is to detect
* the header length with clHCA_isOurFile, then read data and call this. * the header length with clHCA_isOurFile, then read data and call this.
* May be called multiple times to reset decoder state. * May be called multiple times to reset decoder state.
* Returns 0 on success, <0 on failure. */ * Returns 0 on success, <0 on failure. */
int clHCA_DecodeHeader(clHCA *, const void *data, unsigned int size); int clHCA_DecodeHeader(clHCA* hca, const void* data, unsigned int size);
typedef struct clHCA_stInfo { typedef struct clHCA_stInfo {
unsigned int version; unsigned int version;
@ -40,7 +40,7 @@ typedef struct clHCA_stInfo {
unsigned int loopStartDelay; /* samples in block before loop starts */ unsigned int loopStartDelay; /* samples in block before loop starts */
unsigned int loopEndPadding; /* samples in block after loop ends */ unsigned int loopEndPadding; /* samples in block after loop ends */
unsigned int samplesPerBlock; /* should be 1024 */ unsigned int samplesPerBlock; /* should be 1024 */
const char *comment; const char* comment;
unsigned int encryptionEnabled; /* requires keycode */ unsigned int encryptionEnabled; /* requires keycode */
/* Derived sample formulas: /* Derived sample formulas:
@ -53,33 +53,33 @@ typedef struct clHCA_stInfo {
/* Retrieves header information for decoding and playback (it's the caller's responsability /* Retrieves header information for decoding and playback (it's the caller's responsability
* to apply looping, encoder delay/skip samples, etc). May be called after clHCA_DecodeHeader. * to apply looping, encoder delay/skip samples, etc). May be called after clHCA_DecodeHeader.
* Returns 0 on success, <0 on failure. */ * Returns 0 on success, <0 on failure. */
int clHCA_getInfo(clHCA *, clHCA_stInfo *out); int clHCA_getInfo(clHCA* hca, clHCA_stInfo* out);
/* Decodes a single frame, from data after headerSize. Should be called after /* Decodes a single frame, from data after headerSize. Should be called after
* clHCA_DecodeHeader and size must be at least blockSize long. * clHCA_DecodeHeader and size must be at least blockSize long.
* Data may be modified if encrypted. * Data may be modified if encrypted.
* Returns 0 on success, <0 on failure. */ * Returns 0 on success, <0 on failure. */
int clHCA_DecodeBlock(clHCA *, void *data, unsigned int size); int clHCA_DecodeBlock(clHCA* hca, void* data, unsigned int size);
/* Extracts signed and clipped 16 bit samples into sample buffer. /* Extracts signed and clipped 16 bit samples into sample buffer.
* May be called after clHCA_DecodeBlock, and will return the same data until * May be called after clHCA_DecodeBlock, and will return the same data until
* next decode. Buffer must be at least (samplesPerBlock*channels) long. */ * next decode. Buffer must be at least (samplesPerBlock*channels) long. */
void clHCA_ReadSamples16(clHCA *, signed short * outSamples); void clHCA_ReadSamples16(clHCA* hca, short* outSamples);
/* Sets a 64 bit encryption key, to properly decode blocks. This may be called /* Sets a 64 bit encryption key, to properly decode blocks. This may be called
* multiple times to change the key, before or after clHCA_DecodeHeader. * multiple times to change the key, before or after clHCA_DecodeHeader.
* Key is ignored if the file is not encrypted. */ * Key is ignored if the file is not encrypted. */
void clHCA_SetKey(clHCA *, unsigned long long keycode); void clHCA_SetKey(clHCA* hca, unsigned long long keycode);
/* Tests a single frame for validity, mainly to test if current key is correct. /* Tests a single frame for validity, mainly to test if current key is correct.
* Returns <0 on incorrect block (wrong key), 0 on silent block (not useful to determine) * Returns <0 on incorrect block (wrong key), 0 on silent block (not useful to determine)
* and >0 if block is correct (the closer to 1 the more likely). * and >0 if block is correct (the closer to 1 the more likely).
* Incorrect keys may give a few valid frames, so it's best to test a number of them * Incorrect keys may give a few valid frames, so it's best to test a number of them
* and select the key with scores closer to 1. */ * and select the key with scores closer to 1. */
int clHCA_TestBlock(clHCA *hca, void *data, unsigned int size); int clHCA_TestBlock(clHCA* hca, void* data, unsigned int size);
/* Resets the internal decode state, used when restarting to decode the file from the beginning. /* Resets the internal decode state, used when restarting to decode the file from the beginning.
* Without it there are minor differences, mainly useful when testing a new key. */ * Without it there are minor differences, mainly useful when testing a new key. */
void clHCA_DecodeReset(clHCA * hca); void clHCA_DecodeReset(clHCA* hca);
#endif #endif

View File

@ -734,12 +734,18 @@ static const char* common_extension_list[] = {
/* List supported formats and return elements in the list, for plugins that need to know. */ /* List supported formats and return elements in the list, for plugins that need to know. */
const char ** vgmstream_get_formats(size_t * size) { const char** vgmstream_get_formats(size_t* size) {
if (!size)
return NULL;
*size = sizeof(extension_list) / sizeof(char*); *size = sizeof(extension_list) / sizeof(char*);
return extension_list; return extension_list;
} }
const char ** vgmstream_get_common_formats(size_t * size) { const char** vgmstream_get_common_formats(size_t* size) {
if (!size)
return NULL;
*size = sizeof(common_extension_list) / sizeof(char*); *size = sizeof(common_extension_list) / sizeof(char*);
return common_extension_list; return common_extension_list;
} }
@ -766,18 +772,18 @@ typedef struct {
static const coding_info coding_info_list[] = { static const coding_info coding_info_list[] = {
{coding_SILENCE, "Silence"}, {coding_SILENCE, "Silence"},
{coding_PCM16LE, "Little Endian 16-bit PCM"}, {coding_PCM16LE, "16-bit Little Endian PCM"},
{coding_PCM16BE, "Big Endian 16-bit PCM"}, {coding_PCM16BE, "16-bit Big Endian PCM"},
{coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"}, {coding_PCM16_int, "16-bit PCM (block)"},
{coding_PCM8, "8-bit signed PCM"}, {coding_PCM8, "8-bit signed PCM"},
{coding_PCM8_int, "8-bit signed PCM with 1 byte interleave (block)"}, {coding_PCM8_int, "8-bit signed PCM (block)"},
{coding_PCM8_U, "8-bit unsigned PCM"}, {coding_PCM8_U, "8-bit unsigned PCM"},
{coding_PCM8_U_int, "8-bit unsigned PCM with 1 byte interleave (block)"}, {coding_PCM8_U_int, "8-bit unsigned PCM (block)"},
{coding_PCM8_SB, "8-bit PCM with sign bit"}, {coding_PCM8_SB, "8-bit sign bit PCM"},
{coding_PCM4, "4-bit signed PCM"}, {coding_PCM4, "4-bit signed PCM"},
{coding_PCM4_U, "4-bit unsigned PCM"}, {coding_PCM4_U, "4-bit unsigned PCM"},
{coding_ULAW, "8-bit u-Law"}, {coding_ULAW, "8-bit u-Law"},
{coding_ULAW_int, "8-bit u-Law with 1 byte interleave (block)"}, {coding_ULAW_int, "8-bit u-Law (block)"},
{coding_ALAW, "8-bit a-Law"}, {coding_ALAW, "8-bit a-Law"},
{coding_PCMFLOAT, "32-bit float PCM"}, {coding_PCMFLOAT, "32-bit float PCM"},
{coding_PCM24LE, "24-bit Little Endian PCM"}, {coding_PCM24LE, "24-bit Little Endian PCM"},
@ -876,9 +882,9 @@ static const coding_info coding_info_list[] = {
{coding_COMPRESSWAVE, "CompressWave Huffman ADPCM"}, {coding_COMPRESSWAVE, "CompressWave Huffman ADPCM"},
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"}, {coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM (block)"},
{coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"}, {coding_CBD2, "Cuberoot-delta-exact (CBD2) 8-bit DPCM"},
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"}, {coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM (block)"},
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"}, {coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
{coding_DERF, "Xilam DERF 8-bit DPCM"}, {coding_DERF, "Xilam DERF 8-bit DPCM"},
{coding_WADY, "Marble WADY 8-bit DPCM"}, {coding_WADY, "Marble WADY 8-bit DPCM"},
@ -1010,7 +1016,7 @@ static const meta_info meta_info_list[] = {
{meta_XA, "Sony XA header"}, {meta_XA, "Sony XA header"},
{meta_RXWS, "Sony RXWS header"}, {meta_RXWS, "Sony RXWS header"},
{meta_RAW_INT, "PS2 .int raw header"}, {meta_RAW_INT, "PS2 .int raw header"},
{meta_OMU, "Outrage OMU Header"}, {meta_OMU, "Outrage OMU header"},
{meta_DSP_STM, "Intelligent Systems STM header"}, {meta_DSP_STM, "Intelligent Systems STM header"},
{meta_EXST, "Sony EXST header"}, {meta_EXST, "Sony EXST header"},
{meta_SVAG_KCET, "Konami SVAG header"}, {meta_SVAG_KCET, "Konami SVAG header"},
@ -1035,8 +1041,8 @@ static const meta_info meta_info_list[] = {
{meta_DSP_STR, "Cauldron .STR header"}, {meta_DSP_STR, "Cauldron .STR header"},
{meta_EA_SCHL, "Electronic Arts SCHl header"}, {meta_EA_SCHL, "Electronic Arts SCHl header"},
{meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"}, {meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"},
{meta_CAF, "tri-Crescendo CAF Header"}, {meta_CAF, "tri-Crescendo CAF header"},
{meta_VPK, "SCE America VPK Header"}, {meta_VPK, "SCE America VPK header"},
{meta_GENH, "GENH generic header"}, {meta_GENH, "GENH generic header"},
{meta_DSP_SADB, "Procyon Studio SADB header"}, {meta_DSP_SADB, "Procyon Studio SADB header"},
{meta_SADL, "Procyon Studio SADL header"}, {meta_SADL, "Procyon Studio SADL header"},
@ -1055,7 +1061,7 @@ static const meta_info meta_info_list[] = {
{meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"}, {meta_NWA_GAMEEXEINI, "VisualArt's NWA header (Gameexe.ini looping)"},
{meta_XSS, "Dino Crisis 3 XSS File"}, {meta_XSS, "Dino Crisis 3 XSS File"},
{meta_HGC1, "Cauldron HGC1 header"}, {meta_HGC1, "Cauldron HGC1 header"},
{meta_AUS, "Capcom AUS Header"}, {meta_AUS, "Atomic Planet AUS header"},
{meta_RWS, "RenderWare RWS header"}, {meta_RWS, "RenderWare RWS header"},
{meta_EA_1SNH, "Electronic Arts 1SNh header"}, {meta_EA_1SNH, "Electronic Arts 1SNh header"},
{meta_EA_EACS, "Electronic Arts EACS header"}, {meta_EA_EACS, "Electronic Arts EACS header"},
@ -1070,17 +1076,17 @@ static const meta_info meta_info_list[] = {
{meta_PS2_XA30, "Reflections XA30 PS2 header"}, {meta_PS2_XA30, "Reflections XA30 PS2 header"},
{meta_MUSC, "Krome MUSC header"}, {meta_MUSC, "Krome MUSC header"},
{meta_MUSX, "Eurocom MUSX header"}, {meta_MUSX, "Eurocom MUSX header"},
{meta_FILP, "cavia FILp Header"}, {meta_FILP, "cavia FILp header"},
{meta_IKM, "MiCROViSiON IKM header"}, {meta_IKM, "MiCROViSiON IKM header"},
{meta_STER, "ALCHEMY STER header"}, {meta_STER, "ALCHEMY STER header"},
{meta_SAT_DVI, "Konami DVI. header"}, {meta_SAT_DVI, "Konami DVI. header"},
{meta_DC_KCEY, "Konami KCEY header"}, {meta_DC_KCEY, "Konami KCEY header"},
{meta_BG00, "Cave BG00 header"}, {meta_BG00, "Cave BG00 header"},
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"}, {meta_RSTM_ROCKSTAR, "Rockstar Games RSTM header"},
{meta_ACM, "InterPlay ACM Header"}, {meta_ACM, "InterPlay ACM header"},
{meta_MUS_ACM, "InterPlay MUS ACM header"}, {meta_MUS_ACM, "InterPlay MUS ACM header"},
{meta_VIG_KCES, "Konami .VIG Header"}, {meta_VIG_KCES, "Konami .VIG header"},
{meta_HXD, "Tecmo HXD Header"}, {meta_HXD, "Tecmo HXD header"},
{meta_VSV, "Square Enix .vsv Header"}, {meta_VSV, "Square Enix .vsv Header"},
{meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"}, {meta_RIFF_WAVE_labl, "RIFF WAVE header (labl looping)"},
{meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"}, {meta_RIFF_WAVE_smpl, "RIFF WAVE header (smpl looping)"},
@ -1101,7 +1107,7 @@ static const meta_info meta_info_list[] = {
{meta_STR_SEGA_custom, "Sega Stream Asset Builder header (custom)"}, {meta_STR_SEGA_custom, "Sega Stream Asset Builder header (custom)"},
{meta_XMU, "Outrage XMU header"}, {meta_XMU, "Outrage XMU header"},
{meta_XVAS, "Konami .XVAS header"}, {meta_XVAS, "Konami .XVAS header"},
{meta_XA2_ACCLAIM, "Acclaim .XA2 Header"}, {meta_XA2_ACCLAIM, "Acclaim .XA2 header"},
{meta_SAP, "VING .SAP header"}, {meta_SAP, "VING .SAP header"},
{meta_DC_IDVI, "Capcom IDVI header"}, {meta_DC_IDVI, "Capcom IDVI header"},
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"}, {meta_KRAW, "Geometry Wars: Galaxies KRAW header"},

View File

@ -2,20 +2,31 @@
#include "../vgmstream.h" #include "../vgmstream.h"
/* each block is a new CAF header */ /* each block is a new CAF header */
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream) { void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile; STREAMFILE* sf = vgmstream->ch[0].streamfile;
int i,ch;
// 00: "CAF "
// 04: block size
// 08: block number
// 0c: empty
// 10: channel 1 offset
// 14: channel 1 size
// 18: channel 2 offset
// 1c: channel 2 size
// 20: loop start
// 24: loop end (same as last block)
// 28: DSP header stuff (repeated per block)
vgmstream->current_block_offset = block_offset; vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + read_32bitBE(block_offset+0x04, streamFile); vgmstream->next_block_offset = block_offset + read_u32be(block_offset + 0x04, sf);
vgmstream->current_block_size = read_32bitBE(block_offset+0x14, streamFile); vgmstream->current_block_size = read_u32be(block_offset + 0x14, sf);
for (ch = 0; ch < vgmstream->channels; ch++) { for (int ch = 0; ch < vgmstream->channels; ch++) {
vgmstream->ch[ch].offset = block_offset + read_32bitBE(block_offset+0x10+(0x08*ch), streamFile); vgmstream->ch[ch].offset = block_offset + read_u32be(block_offset + 0x10 + 0x08 * ch, sf);
/* re-read coeffs (though blocks seem to repeat them) */ /* re-read coeffs (though blocks seem to repeat them) */
for (i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(block_offset+0x34 + 0x2c*ch + 0x02*i, streamFile); vgmstream->ch[ch].adpcm_coef[i] = read_s16be(block_offset + 0x34 + 0x2c * ch + 0x02 * i, sf);
} }
} }
} }

View File

@ -1,58 +1,62 @@
#include "meta.h" #include "meta.h"
#include "../layout/layout.h" #include "../layout/layout.h"
#include "../util.h" #include "../coding/coding.h"
/* CAF - from tri-Crescendo games [Baten Kaitos 1/2 (GC), Fragile (Wii)] */ /* CAF - from tri-Crescendo games [Baten Kaitos 1/2 (GC), Fragile (Wii)] */
VGMSTREAM * init_vgmstream_caf(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_caf(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
off_t start_offset, offset; off_t start_offset;
size_t file_size; int channels, loop_flag;
int channel_count, loop_flag;
int32_t num_samples = 0; int32_t num_samples = 0;
uint32_t loop_start = -1;
/* checks */ /* checks */
/* .caf: header id, .cfn: fake extension? , "" is accepted as files don't have extensions in the disc */ if (!is_id32be(0x00,sf, "CAF "))
if (!check_extensions(streamFile,"caf,cfn,")) return NULL;
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x43414620) /* "CAF " */
goto fail;
/* get total samples */ /* .caf: header id
offset = 0; * (extensionless): files on disc don't have any extensions
file_size = get_streamfile_size(streamFile); * .cfn: fake extension */
if (!check_extensions(sf,"caf,cfn,"))
return NULL;
/* get total samples from blocks + find loop */ //TODO reuse function calls
uint32_t loop_start = -1;
off_t offset = 0x00;
off_t file_size = get_streamfile_size(sf);
while (offset < file_size) { while (offset < file_size) {
off_t next_block = read_32bitBE(offset+0x04,streamFile); // see blocked layout for block info
num_samples += read_32bitBE(offset+0x14,streamFile)/8*14; off_t next_block = read_u32be(offset+0x04,sf);
off_t channel_bytes = read_u32be(offset+0x14,sf);
int channel_samples = dsp_bytes_to_samples(channel_bytes, 1);
if(read_32bitBE(offset+0x20,streamFile)==read_32bitBE(offset+0x08,streamFile)) { if (read_u32be(offset+0x08,sf) == read_u32be(offset+0x20,sf) && loop_start < 0) {
loop_start = num_samples - read_32bitBE(offset+0x14,streamFile)/8*14; loop_start = num_samples;
} }
num_samples += channel_samples;
offset += next_block; offset += next_block;
} }
start_offset = 0x00; start_offset = 0x00;
channel_count = 2; /* always stereo */ channels = 2; /* always stereo */
loop_flag = (loop_start!=-1); loop_flag = (loop_start != -1);
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = 32000; vgmstream->sample_rate = 32000;
vgmstream->num_samples = num_samples; vgmstream->num_samples = num_samples;
if (loop_flag) { vgmstream->loop_start_sample = loop_start;
vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = num_samples;
vgmstream->loop_end_sample = num_samples;
}
vgmstream->meta_type = meta_CAF; vgmstream->meta_type = meta_CAF;
vgmstream->coding_type = coding_NGC_DSP; vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_blocked_caf; vgmstream->layout_type = layout_blocked_caf;
if ( !vgmstream_open_stream(vgmstream,streamFile,start_offset) ) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -2,49 +2,47 @@
#include "../coding/coding.h" #include "../coding/coding.h"
/* VPK - from SCE America second party devs [God of War (PS2), NBA 08 (PS3)] */ /* VPK - from SCE America second party devs [God of War (PS2), NBA 08 (PS3)] */
VGMSTREAM * init_vgmstream_vpk(STREAMFILE *streamFile) { VGMSTREAM* init_vgmstream_vpk(STREAMFILE* sf) {
VGMSTREAM * vgmstream = NULL; VGMSTREAM* vgmstream = NULL;
int loop_flag, channel_count; int loop_flag, channels;
off_t start_offset, loop_channel_offset; off_t start_offset, loop_channel_offset;
size_t channel_size;
/* checks */ /* checks */
if (!check_extensions(streamFile, "vpk")) if (!is_id32be(0x00,sf, " KPV"))
goto fail; return NULL;
if (!check_extensions(sf, "vpk"))
if (read_32bitBE(0x00,streamFile) != 0x204B5056) /* " KPV" */ return NULL;
goto fail;
/* files are padded with garbage/silent 0xC00000..00 frames, and channel_size sometimes /* files are padded with garbage/silent 0xC00000..00 frames, and channel_size sometimes
* has extra size into the padding: +0x10 (NBA08), +0x20 (GoW), or none (Sly 2, loops ok). * has extra size into the padding: +0x10 (NBA08), +0x20 (GoW), or none (Sly 2, loops ok).
* Could detect and remove to slightly improve full loops, but maybe this is just how the game works */ * Could detect and remove to slightly improve full loops, but maybe this is just how the game works */
channel_size = read_32bitLE(0x04,streamFile); size_t channel_size = read_u32le(0x04,sf);
start_offset = read_32bitLE(0x08,streamFile); start_offset = read_u32le(0x08,sf);
channel_count = read_32bitLE(0x14,streamFile); channels = read_s32le(0x14,sf);
/* 0x18+: channel config(?), 0x04 per channel */ /* 0x18+: channel config(?), 0x04 per channel */
loop_channel_offset = read_32bitLE(0x7FC,streamFile); loop_channel_offset = read_u32le(0x7FC,sf);
loop_flag = (loop_channel_offset != 0); /* found in Sly 2/3 */ loop_flag = (loop_channel_offset != 0); /* found in Sly 2/3 */
/* build the VGMSTREAM */ /* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag); vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile); vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = ps_bytes_to_samples(channel_size*vgmstream->channels,vgmstream->channels); vgmstream->num_samples = ps_bytes_to_samples(channel_size * channels, channels);
if (vgmstream->loop_flag) { if (vgmstream->loop_flag) {
vgmstream->loop_start_sample = ps_bytes_to_samples(loop_channel_offset*vgmstream->channels,vgmstream->channels); vgmstream->loop_start_sample = ps_bytes_to_samples(loop_channel_offset * channels, channels);
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
vgmstream->meta_type = meta_VPK; vgmstream->meta_type = meta_VPK;
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
vgmstream->interleave_block_size = read_32bitLE(0x0C,streamFile) / 2; /* even in >2ch */ vgmstream->interleave_block_size = read_u32le(0x0C,sf) / 2; /* even in >2ch */
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset)) if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail; goto fail;
return vgmstream; return vgmstream;

View File

@ -75,7 +75,7 @@ typedef struct {
int fix_xma_loop_samples; int fix_xma_loop_samples;
} xwb_header; } xwb_header;
static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf); static void get_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf);
/* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */ /* XWB - XACT Wave Bank (Microsoft SDK format for XBOX/XBOX360/Windows) */
@ -638,10 +638,10 @@ fail:
/* ****************************************************************************** */ /* ****************************************************************************** */
static int get_xwb_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf) { static int get_xwb_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
size_t read; size_t read;
if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > maxsize) if (!xwb->names_offset || !xwb->names_size || xwb->names_entry_size > buf_size)
goto fail; goto fail;
read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),sf); read = read_string(buf,xwb->names_entry_size, xwb->names_offset + xwb->names_entry_size*(target_subsong-1),sf);
@ -653,7 +653,7 @@ fail:
return 0; return 0;
} }
static int get_xsb_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf) { static int get_xsb_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf) {
xsb_header xsb = {0}; xsb_header xsb = {0};
xsb.selected_stream = target_subsong - 1; xsb.selected_stream = target_subsong - 1;
@ -670,8 +670,7 @@ static int get_xsb_name(char* buf, size_t maxsize, int target_subsong, xwb_heade
if (!xsb.name_len || xsb.name[0] == '\0') if (!xsb.name_len || xsb.name[0] == '\0')
goto fail; goto fail;
strncpy(buf,xsb.name,maxsize); snprintf(buf, buf_size, "%s", xsb.name);
buf[maxsize-1] = '\0';
return 1; return 1;
fail: fail:
return 0; return 0;
@ -715,12 +714,12 @@ fail:
return 0; return 0;
} }
static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header* xwb, STREAMFILE* sf_xwb) { static void get_name(char* buf, size_t buf_size, int target_subsong, xwb_header* xwb, STREAMFILE* sf_xwb) {
STREAMFILE* sf_name = NULL; STREAMFILE* sf_name = NULL;
int name_found; int name_found;
/* try to get the stream name in the .xwb, though they are very rarely included */ /* try to get the stream name in the .xwb, though they are very rarely included */
name_found = get_xwb_name(buf, maxsize, target_subsong, xwb, sf_xwb); name_found = get_xwb_name(buf, buf_size, target_subsong, xwb, sf_xwb);
if (name_found) return; if (name_found) return;
/* try again in a companion files */ /* try again in a companion files */
@ -730,7 +729,7 @@ static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header*
sf_name = open_streamfile_by_ext(sf_xwb, "wbh"); sf_name = open_streamfile_by_ext(sf_xwb, "wbh");
if (!sf_name) goto fail; /* rarely found [Pac-Man World 2 (Xbox)] */ if (!sf_name) goto fail; /* rarely found [Pac-Man World 2 (Xbox)] */
name_found = get_wbh_name(buf, maxsize, target_subsong, xwb, sf_name); name_found = get_wbh_name(buf, buf_size, target_subsong, xwb, sf_name);
close_streamfile(sf_name); close_streamfile(sf_name);
} }
else { else {
@ -738,7 +737,7 @@ static void get_name(char* buf, size_t maxsize, int target_subsong, xwb_header*
sf_name = open_xsb_filename_pair(sf_xwb); sf_name = open_xsb_filename_pair(sf_xwb);
if (!sf_name) goto fail; /* not all xwb have xsb though */ if (!sf_name) goto fail; /* not all xwb have xsb though */
name_found = get_xsb_name(buf, maxsize, target_subsong, xwb, sf_name); name_found = get_xsb_name(buf, buf_size, target_subsong, xwb, sf_name);
close_streamfile(sf_name); close_streamfile(sf_name);
} }

View File

@ -242,6 +242,9 @@ static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char
uint8_t* buf = NULL; uint8_t* buf = NULL;
STDIO_STREAMFILE* this_sf = NULL; STDIO_STREAMFILE* this_sf = NULL;
if (buf_size <= 0)
buf_size = STREAMFILE_DEFAULT_BUFFER_SIZE;
buf = calloc(buf_size, sizeof(uint8_t)); buf = calloc(buf_size, sizeof(uint8_t));
if (!buf) goto fail; if (!buf) goto fail;
@ -326,11 +329,11 @@ static STREAMFILE* open_stdio_streamfile_buffer(const char* const filename, size
} }
STREAMFILE* open_stdio_streamfile(const char* filename) { STREAMFILE* open_stdio_streamfile(const char* filename) {
return open_stdio_streamfile_buffer(filename, STREAMFILE_DEFAULT_BUFFER_SIZE); return open_stdio_streamfile_buffer(filename, 0);
} }
STREAMFILE* open_stdio_streamfile_by_file(FILE* file, const char* filename) { STREAMFILE* open_stdio_streamfile_by_file(FILE* file, const char* filename) {
return open_stdio_streamfile_buffer_by_file(file, filename, STREAMFILE_DEFAULT_BUFFER_SIZE); return open_stdio_streamfile_buffer_by_file(file, filename, 0);
} }
/* **************************************************** */ /* **************************************************** */