mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 14:01:45 +00:00
Update DUMB to revision 5bee3e5ba3d57d1b16dda6d82c18fb417781625b
- Fixed XM reader for files with smaller than expected instrument or sample header sizes SVN r4092 (trunk)
This commit is contained in:
parent
3681a6673f
commit
4163817eda
1 changed files with 176 additions and 11 deletions
|
@ -111,6 +111,7 @@ typedef struct XM_INSTRUMENT_EXTRA
|
||||||
int vibrato_sweep; /* 0-0xFF */
|
int vibrato_sweep; /* 0-0xFF */
|
||||||
int vibrato_depth; /* 0-0x0F */
|
int vibrato_depth; /* 0-0x0F */
|
||||||
int vibrato_speed; /* 0-0x3F */
|
int vibrato_speed; /* 0-0x3F */
|
||||||
|
int sample_header_size;
|
||||||
}
|
}
|
||||||
XM_INSTRUMENT_EXTRA;
|
XM_INSTRUMENT_EXTRA;
|
||||||
|
|
||||||
|
@ -359,6 +360,116 @@ static int it_xm_make_envelope(IT_ENVELOPE *envelope, const unsigned short *data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct LIMITED_XM LIMITED_XM;
|
||||||
|
|
||||||
|
struct LIMITED_XM
|
||||||
|
{
|
||||||
|
unsigned char *buffered;
|
||||||
|
long ptr, limit, allocated;
|
||||||
|
DUMBFILE *remaining;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
struct DUMBFILE
|
||||||
|
{
|
||||||
|
DUMBFILE_SYSTEM *dfs;
|
||||||
|
void *file;
|
||||||
|
long pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int limit_xm_resize(void *f, long n)
|
||||||
|
{
|
||||||
|
DUMBFILE *df = f;
|
||||||
|
LIMITED_XM *lx = df->file;
|
||||||
|
if (lx->buffered || n) {
|
||||||
|
if (n > lx->allocated) {
|
||||||
|
unsigned char *buffered = realloc( lx->buffered, n );
|
||||||
|
if ( !buffered ) return -1;
|
||||||
|
lx->buffered = buffered;
|
||||||
|
memset( buffered + lx->allocated, 0, n - lx->allocated );
|
||||||
|
lx->allocated = n;
|
||||||
|
}
|
||||||
|
if ( dumbfile_getnc( lx->buffered, n, lx->remaining ) < n ) return -1;
|
||||||
|
} else if (!n) {
|
||||||
|
if ( lx->buffered ) free( lx->buffered );
|
||||||
|
lx->buffered = NULL;
|
||||||
|
lx->allocated = 0;
|
||||||
|
}
|
||||||
|
lx->limit = n;
|
||||||
|
lx->ptr = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int limit_xm_skip(void *f, long n)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
lx->ptr += n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int limit_xm_getc(void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
if (lx->ptr >= lx->allocated) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return lx->buffered[lx->ptr++];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static long limit_xm_getnc(char *ptr, long n, void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
int left;
|
||||||
|
left = lx->allocated - lx->ptr;
|
||||||
|
if (n > left) {
|
||||||
|
if (left > 0) {
|
||||||
|
memcpy( ptr, lx->buffered + lx->ptr, left );
|
||||||
|
memset( ptr + left, 0, n - left );
|
||||||
|
} else {
|
||||||
|
memset( ptr, 0, n );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memcpy( ptr, lx->buffered + lx->ptr, n );
|
||||||
|
}
|
||||||
|
lx->ptr += n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void limit_xm_close(void *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM *lx = f;
|
||||||
|
if (lx->buffered) free(lx->buffered);
|
||||||
|
/* Do NOT close lx->remaining */
|
||||||
|
free(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DUMBFILE_SYSTEM limit_xm_dfs = {
|
||||||
|
NULL,
|
||||||
|
&limit_xm_skip,
|
||||||
|
&limit_xm_getc,
|
||||||
|
&limit_xm_getnc,
|
||||||
|
&limit_xm_close
|
||||||
|
};
|
||||||
|
|
||||||
|
static DUMBFILE *dumbfile_limit_xm(DUMBFILE *f)
|
||||||
|
{
|
||||||
|
LIMITED_XM * lx = malloc(sizeof(*lx));
|
||||||
|
lx->remaining = f;
|
||||||
|
lx->buffered = NULL;
|
||||||
|
lx->ptr = 0;
|
||||||
|
lx->limit = 0;
|
||||||
|
lx->allocated = 0;
|
||||||
|
return dumbfile_open_ex( lx, &limit_xm_dfs );
|
||||||
|
}
|
||||||
|
|
||||||
static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f)
|
static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA *extra, DUMBFILE *f)
|
||||||
{
|
{
|
||||||
uint32 size, bytes_read;
|
uint32 size, bytes_read;
|
||||||
|
@ -370,8 +481,15 @@ static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA
|
||||||
* So unread bytes must be skipped before reading the first sample
|
* So unread bytes must be skipped before reading the first sample
|
||||||
* header.
|
* header.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if ( limit_xm_resize( f, 4 ) < 0 ) return -1;
|
||||||
|
|
||||||
size = dumbfile_igetl(f);
|
size = dumbfile_igetl(f);
|
||||||
|
|
||||||
|
if ( size == 0 ) size = 4 + 22 + 1 + 2 + 4 + 96 + 48 + 48 + 1 * 14 + 2 + 2;
|
||||||
|
|
||||||
|
if ( limit_xm_resize( f, size - 4 ) < 0 ) return -1;
|
||||||
|
|
||||||
dumbfile_getnc(instrument->name, 22, f);
|
dumbfile_getnc(instrument->name, 22, f);
|
||||||
instrument->name[22] = 0;
|
instrument->name[22] = 0;
|
||||||
instrument->filename[0] = 0;
|
instrument->filename[0] = 0;
|
||||||
|
@ -385,12 +503,9 @@ static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA
|
||||||
|
|
||||||
if (extra->n_samples) {
|
if (extra->n_samples) {
|
||||||
/* sample header size */
|
/* sample header size */
|
||||||
dumbfile_skip(f, 4); // XXX can't be trusted, as there are trackers that write the wrong value here
|
i = dumbfile_igetl(f);
|
||||||
/*i = dumbfile_igetl(f);
|
if (!i) i = 0x28;
|
||||||
if (i && i != 0x28) { // XXX some crap with 0 here
|
extra->sample_header_size = i;
|
||||||
TRACE("XM error: unexpected sample header size\n");
|
|
||||||
return -1;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/* sample map */
|
/* sample map */
|
||||||
for (i = 0; i < 96; i++) {
|
for (i = 0; i < 96; i++) {
|
||||||
|
@ -476,7 +591,7 @@ static int it_xm_read_instrument(IT_INSTRUMENT *instrument, XM_INSTRUMENT_EXTRA
|
||||||
for (i = 0; i < 96; i++)
|
for (i = 0; i < 96; i++)
|
||||||
instrument->map_sample[i] = 0;
|
instrument->map_sample[i] = 0;
|
||||||
|
|
||||||
if (dumbfile_skip(f, size - bytes_read))
|
if (size > bytes_read && dumbfile_skip(f, size - bytes_read))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
instrument->new_note_action = NNA_NOTE_CUT;
|
instrument->new_note_action = NNA_NOTE_CUT;
|
||||||
|
@ -924,16 +1039,24 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (i = 0; i < sigdata->n_instruments; i++) {
|
for (i = 0; i < sigdata->n_instruments; i++) {
|
||||||
XM_INSTRUMENT_EXTRA extra;
|
XM_INSTRUMENT_EXTRA extra;
|
||||||
|
|
||||||
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) {
|
DUMBFILE * lf = dumbfile_limit_xm( f );
|
||||||
|
if ( !lf ) {
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, lf) < 0) {
|
||||||
// XXX
|
// XXX
|
||||||
if ( ! i )
|
if ( ! i )
|
||||||
{
|
{
|
||||||
TRACE("XM error: instrument %d\n", i+1);
|
TRACE("XM error: instrument %d\n", i+1);
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
dumbfile_close( lf );
|
||||||
sigdata->n_instruments = i;
|
sigdata->n_instruments = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -948,17 +1071,31 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
||||||
if (!sigdata->sample) {
|
if (!sigdata->sample) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
||||||
sigdata->sample[j].data = NULL;
|
sigdata->sample[j].data = NULL;
|
||||||
|
|
||||||
|
if ( limit_xm_resize( lf, 0 ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read instrument's samples */
|
/* read instrument's samples */
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
||||||
int b = it_xm_read_sample_header(sample, f);
|
int b;
|
||||||
|
if ( limit_xm_resize( lf, extra.sample_header_size ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
b = it_xm_read_sample_header(sample, lf);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -975,12 +1112,15 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
}
|
}
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
|
if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
|
||||||
|
dumbfile_close( lf );
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
total_samples += extra.n_samples;
|
total_samples += extra.n_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dumbfile_close( lf );
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->n_samples = total_samples;
|
sigdata->n_samples = total_samples;
|
||||||
|
@ -1012,8 +1152,16 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (i = 0; i < sigdata->n_instruments; i++) {
|
for (i = 0; i < sigdata->n_instruments; i++) {
|
||||||
XM_INSTRUMENT_EXTRA extra;
|
XM_INSTRUMENT_EXTRA extra;
|
||||||
|
|
||||||
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, f) < 0) {
|
DUMBFILE * lf = dumbfile_limit_xm( f );
|
||||||
|
if ( !lf ) {
|
||||||
|
free(roguebytes);
|
||||||
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (it_xm_read_instrument(&sigdata->instrument[i], &extra, lf) < 0) {
|
||||||
TRACE("XM error: instrument %d\n", i+1);
|
TRACE("XM error: instrument %d\n", i+1);
|
||||||
|
dumbfile_close(lf);
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1026,6 +1174,7 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
|
|
||||||
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
sigdata->sample = safe_realloc(sigdata->sample, sizeof(*sigdata->sample)*(total_samples+extra.n_samples));
|
||||||
if (!sigdata->sample) {
|
if (!sigdata->sample) {
|
||||||
|
dumbfile_close( lf );
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1033,10 +1182,24 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
||||||
sigdata->sample[j].data = NULL;
|
sigdata->sample[j].data = NULL;
|
||||||
|
|
||||||
|
if ( limit_xm_resize( lf, 0 ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
free( roguebytes );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* read instrument's samples */
|
/* read instrument's samples */
|
||||||
for (j = 0; j < extra.n_samples; j++) {
|
for (j = 0; j < extra.n_samples; j++) {
|
||||||
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
IT_SAMPLE *sample = &sigdata->sample[total_samples+j];
|
||||||
int b = it_xm_read_sample_header(sample, f);
|
int b;
|
||||||
|
if ( limit_xm_resize( lf, extra.sample_header_size ) < 0 ) {
|
||||||
|
dumbfile_close( lf );
|
||||||
|
free( roguebytes );
|
||||||
|
_dumb_it_unload_sigdata( sigdata );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
b = it_xm_read_sample_header(sample, lf);
|
||||||
if (b < 0) {
|
if (b < 0) {
|
||||||
free(roguebytes);
|
free(roguebytes);
|
||||||
_dumb_it_unload_sigdata(sigdata);
|
_dumb_it_unload_sigdata(sigdata);
|
||||||
|
@ -1055,6 +1218,8 @@ static DUMB_IT_SIGDATA *it_xm_load_sigdata(DUMBFILE *f, int * version)
|
||||||
}
|
}
|
||||||
total_samples += extra.n_samples;
|
total_samples += extra.n_samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dumbfile_close( lf );
|
||||||
}
|
}
|
||||||
|
|
||||||
sigdata->n_samples = total_samples;
|
sigdata->n_samples = total_samples;
|
||||||
|
|
Loading…
Reference in a new issue