mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +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_depth; /* 0-0x0F */
|
||||
int vibrato_speed; /* 0-0x3F */
|
||||
int sample_header_size;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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
|
||||
* header.
|
||||
*/
|
||||
|
||||
if ( limit_xm_resize( f, 4 ) < 0 ) return -1;
|
||||
|
||||
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);
|
||||
instrument->name[22] = 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) {
|
||||
/* 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);
|
||||
if (i && i != 0x28) { // XXX some crap with 0 here
|
||||
TRACE("XM error: unexpected sample header size\n");
|
||||
return -1;
|
||||
}*/
|
||||
i = dumbfile_igetl(f);
|
||||
if (!i) i = 0x28;
|
||||
extra->sample_header_size = i;
|
||||
|
||||
/* sample map */
|
||||
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++)
|
||||
instrument->map_sample[i] = 0;
|
||||
|
||||
if (dumbfile_skip(f, size - bytes_read))
|
||||
if (size > bytes_read && dumbfile_skip(f, size - bytes_read))
|
||||
return -1;
|
||||
|
||||
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++) {
|
||||
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
|
||||
if ( ! i )
|
||||
{
|
||||
TRACE("XM error: instrument %d\n", i+1);
|
||||
dumbfile_close( lf );
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
dumbfile_close( lf );
|
||||
sigdata->n_instruments = i;
|
||||
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));
|
||||
if (!sigdata->sample) {
|
||||
dumbfile_close( lf );
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
for (j = total_samples; j < total_samples+extra.n_samples; j++)
|
||||
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 */
|
||||
for (j = 0; j < extra.n_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) {
|
||||
dumbfile_close( lf );
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
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++) {
|
||||
if (it_xm_read_sample_data(&sigdata->sample[total_samples+j], roguebytes[j], f) != 0) {
|
||||
dumbfile_close( lf );
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
total_samples += extra.n_samples;
|
||||
}
|
||||
|
||||
dumbfile_close( lf );
|
||||
}
|
||||
|
||||
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++) {
|
||||
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);
|
||||
dumbfile_close(lf);
|
||||
free(roguebytes);
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
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));
|
||||
if (!sigdata->sample) {
|
||||
dumbfile_close( lf );
|
||||
free(roguebytes);
|
||||
_dumb_it_unload_sigdata(sigdata);
|
||||
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++)
|
||||
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 */
|
||||
for (j = 0; j < extra.n_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) {
|
||||
free(roguebytes);
|
||||
_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;
|
||||
}
|
||||
|
||||
dumbfile_close( lf );
|
||||
}
|
||||
|
||||
sigdata->n_samples = total_samples;
|
||||
|
|
Loading…
Reference in a new issue