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);
write_audio(buffer, to_do * sizeof(short) * output_channels);
//TODO: detect how many written
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);
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);
/* 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);
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);
}
}

View File

@ -4,26 +4,26 @@
/* Must pass at least 8 bytes of data to this function.
* 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. */
typedef struct clHCA clHCA;
/* In case you wish to allocate and reset the structure on your own. */
int clHCA_sizeof(void);
void clHCA_clear(clHCA *);
void clHCA_done(clHCA *);
void clHCA_clear(clHCA* hca);
void clHCA_done(clHCA* hca);
/* Or you could let the library allocate it. */
clHCA * clHCA_new(void);
void clHCA_delete(clHCA *);
clHCA* clHCA_new(void);
void clHCA_delete(clHCA* hca);
/* 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
* the header length with clHCA_isOurFile, then read data and call this.
* May be called multiple times to reset decoder state.
* 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 {
unsigned int version;
@ -40,7 +40,7 @@ typedef struct clHCA_stInfo {
unsigned int loopStartDelay; /* samples in block before loop starts */
unsigned int loopEndPadding; /* samples in block after loop ends */
unsigned int samplesPerBlock; /* should be 1024 */
const char *comment;
const char* comment;
unsigned int encryptionEnabled; /* requires keycode */
/* Derived sample formulas:
@ -53,33 +53,33 @@ typedef struct clHCA_stInfo {
/* 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.
* 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
* clHCA_DecodeHeader and size must be at least blockSize long.
* Data may be modified if encrypted.
* 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.
* May be called after clHCA_DecodeBlock, and will return the same data until
* 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
* multiple times to change the key, before or after clHCA_DecodeHeader.
* 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.
* 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).
* 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. */
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.
* Without it there are minor differences, mainly useful when testing a new key. */
void clHCA_DecodeReset(clHCA * hca);
void clHCA_DecodeReset(clHCA* hca);
#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. */
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*);
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*);
return common_extension_list;
}
@ -766,18 +772,18 @@ typedef struct {
static const coding_info coding_info_list[] = {
{coding_SILENCE, "Silence"},
{coding_PCM16LE, "Little Endian 16-bit PCM"},
{coding_PCM16BE, "Big Endian 16-bit PCM"},
{coding_PCM16_int, "16-bit PCM with 2 byte interleave (block)"},
{coding_PCM16LE, "16-bit Little Endian PCM"},
{coding_PCM16BE, "16-bit Big Endian PCM"},
{coding_PCM16_int, "16-bit PCM (block)"},
{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_int, "8-bit unsigned PCM with 1 byte interleave (block)"},
{coding_PCM8_SB, "8-bit PCM with sign bit"},
{coding_PCM8_U_int, "8-bit unsigned PCM (block)"},
{coding_PCM8_SB, "8-bit sign bit PCM"},
{coding_PCM4, "4-bit signed PCM"},
{coding_PCM4_U, "4-bit unsigned PCM"},
{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_PCMFLOAT, "32-bit float 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_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_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_DERF, "Xilam DERF 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_RXWS, "Sony RXWS 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_EXST, "Sony EXST 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_EA_SCHL, "Electronic Arts SCHl header"},
{meta_EA_SCHL_fixed, "Electronic Arts SCHl header (fixed)"},
{meta_CAF, "tri-Crescendo CAF Header"},
{meta_VPK, "SCE America VPK Header"},
{meta_CAF, "tri-Crescendo CAF header"},
{meta_VPK, "SCE America VPK header"},
{meta_GENH, "GENH generic header"},
{meta_DSP_SADB, "Procyon Studio SADB 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_XSS, "Dino Crisis 3 XSS File"},
{meta_HGC1, "Cauldron HGC1 header"},
{meta_AUS, "Capcom AUS Header"},
{meta_AUS, "Atomic Planet AUS header"},
{meta_RWS, "RenderWare RWS header"},
{meta_EA_1SNH, "Electronic Arts 1SNh 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_MUSC, "Krome MUSC header"},
{meta_MUSX, "Eurocom MUSX header"},
{meta_FILP, "cavia FILp Header"},
{meta_FILP, "cavia FILp header"},
{meta_IKM, "MiCROViSiON IKM header"},
{meta_STER, "ALCHEMY STER header"},
{meta_SAT_DVI, "Konami DVI. header"},
{meta_DC_KCEY, "Konami KCEY header"},
{meta_BG00, "Cave BG00 header"},
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM Header"},
{meta_ACM, "InterPlay ACM Header"},
{meta_RSTM_ROCKSTAR, "Rockstar Games RSTM header"},
{meta_ACM, "InterPlay ACM header"},
{meta_MUS_ACM, "InterPlay MUS ACM header"},
{meta_VIG_KCES, "Konami .VIG Header"},
{meta_HXD, "Tecmo HXD Header"},
{meta_VIG_KCES, "Konami .VIG header"},
{meta_HXD, "Tecmo HXD header"},
{meta_VSV, "Square Enix .vsv Header"},
{meta_RIFF_WAVE_labl, "RIFF WAVE header (labl 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_XMU, "Outrage XMU header"},
{meta_XVAS, "Konami .XVAS header"},
{meta_XA2_ACCLAIM, "Acclaim .XA2 Header"},
{meta_XA2_ACCLAIM, "Acclaim .XA2 header"},
{meta_SAP, "VING .SAP header"},
{meta_DC_IDVI, "Capcom IDVI header"},
{meta_KRAW, "Geometry Wars: Galaxies KRAW header"},

View File

@ -2,20 +2,31 @@
#include "../vgmstream.h"
/* each block is a new CAF header */
void block_update_caf(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile;
int i,ch;
void block_update_caf(off_t block_offset, VGMSTREAM* vgmstream) {
STREAMFILE* sf = vgmstream->ch[0].streamfile;
// 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->next_block_offset = block_offset + read_32bitBE(block_offset+0x04, streamFile);
vgmstream->current_block_size = read_32bitBE(block_offset+0x14, streamFile);
vgmstream->next_block_offset = block_offset + read_u32be(block_offset + 0x04, sf);
vgmstream->current_block_size = read_u32be(block_offset + 0x14, sf);
for (ch = 0; ch < vgmstream->channels; ch++) {
vgmstream->ch[ch].offset = block_offset + read_32bitBE(block_offset+0x10+(0x08*ch), streamFile);
for (int ch = 0; ch < vgmstream->channels; ch++) {
vgmstream->ch[ch].offset = block_offset + read_u32be(block_offset + 0x10 + 0x08 * ch, sf);
/* re-read coeffs (though blocks seem to repeat them) */
for (i = 0; i < 16; i++) {
vgmstream->ch[ch].adpcm_coef[i] = read_16bitBE(block_offset+0x34 + 0x2c*ch + 0x02*i, streamFile);
for (int i = 0; i < 16; i++) {
vgmstream->ch[ch].adpcm_coef[i] = read_s16be(block_offset + 0x34 + 0x2c * ch + 0x02 * i, sf);
}
}
}

View File

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

View File

@ -2,49 +2,47 @@
#include "../coding/coding.h"
/* VPK - from SCE America second party devs [God of War (PS2), NBA 08 (PS3)] */
VGMSTREAM * init_vgmstream_vpk(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int loop_flag, channel_count;
VGMSTREAM* init_vgmstream_vpk(STREAMFILE* sf) {
VGMSTREAM* vgmstream = NULL;
int loop_flag, channels;
off_t start_offset, loop_channel_offset;
size_t channel_size;
/* checks */
if (!check_extensions(streamFile, "vpk"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x204B5056) /* " KPV" */
goto fail;
if (!is_id32be(0x00,sf, " KPV"))
return NULL;
if (!check_extensions(sf, "vpk"))
return NULL;
/* 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).
* 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);
channel_count = read_32bitLE(0x14,streamFile);
start_offset = read_u32le(0x08,sf);
channels = read_s32le(0x14,sf);
/* 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 */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream = allocate_vgmstream(channels, loop_flag);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x10,streamFile);
vgmstream->num_samples = ps_bytes_to_samples(channel_size*vgmstream->channels,vgmstream->channels);
vgmstream->sample_rate = read_s32le(0x10,sf);
vgmstream->num_samples = ps_bytes_to_samples(channel_size * channels, channels);
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->meta_type = meta_VPK;
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;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
goto fail;
return vgmstream;

View File

@ -75,7 +75,7 @@ typedef struct {
int fix_xma_loop_samples;
} 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) */
@ -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;
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;
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;
}
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.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')
goto fail;
strncpy(buf,xsb.name,maxsize);
buf[maxsize-1] = '\0';
snprintf(buf, buf_size, "%s", xsb.name);
return 1;
fail:
return 0;
@ -715,12 +714,12 @@ fail:
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;
int name_found;
/* 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;
/* 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");
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);
}
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);
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);
}

View File

@ -242,6 +242,9 @@ static STREAMFILE* open_stdio_streamfile_buffer_by_file(FILE* infile, const char
uint8_t* buf = NULL;
STDIO_STREAMFILE* this_sf = NULL;
if (buf_size <= 0)
buf_size = STREAMFILE_DEFAULT_BUFFER_SIZE;
buf = calloc(buf_size, sizeof(uint8_t));
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) {
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) {
return open_stdio_streamfile_buffer_by_file(file, filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
return open_stdio_streamfile_buffer_by_file(file, filename, 0);
}
/* **************************************************** */

View File

@ -1,43 +1,43 @@
#ifndef _TEXT_READER_H_
#define _TEXT_READER_H_
/* Reader tuned for whole text files, reading chunks to minimize I/O with a single buffer.
* For short lines read_line may be more appropriate (reads up to line end, while this reads bigger chunks),
* which also allow \0 (this reader returns an error).
* NOTE: modifies passed buffer (lines are forced to end with \0 rather than \n).
*
* Usage: set text_reader_t and defaults with text_reader_init, call text_reader_get_line(...) to get lines.
* buf may be size+1 to allow 2^N chunk reads + trailing \0 (better performance?).
*/
#include "../streamfile.h"
typedef struct {
/* init */
uint8_t* buf; /* where data will be read */
int buf_size; /* size of the struct (also max line size) */
STREAMFILE* sf; /* used to read data */
uint32_t offset; /* sf pos */
uint32_t max_offset; /* sf max */
/* internal */
int filled; /* current buf bytes */
int pos; /* current buf pos (last line) */
int next_pos; /* buf pos on next call, after line end */
int line_ok; /* current line is fully correct */
char* line;
int line_len;
} text_reader_t;
/* convenience function to init the above struct */
int text_reader_init(text_reader_t* tr, uint8_t* buf, int buf_size, STREAMFILE* sf, uint32_t offset, uint32_t max);
/* Reads and sets next line, or NULL if no lines are found (EOF).
* returns line length (0 for empty lines), or <0 if line was too long to store in buf.
* Will always return a valid (null terminated) string. */
int text_reader_get_line(text_reader_t* tr, char** p_line);
#endif
#ifndef _TEXT_READER_H_
#define _TEXT_READER_H_
/* Reader tuned for whole text files, reading chunks to minimize I/O with a single buffer.
* For short lines read_line may be more appropriate (reads up to line end, while this reads bigger chunks),
* which also allow \0 (this reader returns an error).
* NOTE: modifies passed buffer (lines are forced to end with \0 rather than \n).
*
* Usage: set text_reader_t and defaults with text_reader_init, call text_reader_get_line(...) to get lines.
* buf may be size+1 to allow 2^N chunk reads + trailing \0 (better performance?).
*/
#include "../streamfile.h"
typedef struct {
/* init */
uint8_t* buf; /* where data will be read */
int buf_size; /* size of the struct (also max line size) */
STREAMFILE* sf; /* used to read data */
uint32_t offset; /* sf pos */
uint32_t max_offset; /* sf max */
/* internal */
int filled; /* current buf bytes */
int pos; /* current buf pos (last line) */
int next_pos; /* buf pos on next call, after line end */
int line_ok; /* current line is fully correct */
char* line;
int line_len;
} text_reader_t;
/* convenience function to init the above struct */
int text_reader_init(text_reader_t* tr, uint8_t* buf, int buf_size, STREAMFILE* sf, uint32_t offset, uint32_t max);
/* Reads and sets next line, or NULL if no lines are found (EOF).
* returns line length (0 for empty lines), or <0 if line was too long to store in buf.
* Will always return a valid (null terminated) string. */
int text_reader_get_line(text_reader_t* tr, char** p_line);
#endif