shithub: dumb

Download patch

ref: d8784727e4b117e77c9cf4ff609dace2c4d1da24
parent: 3267dd862062e755782f04eee5db47ef338fc5b8
author: Chris Moeller <kode54@gmail.com>
date: Mon Jan 14 14:06:08 EST 2013

Implemented full seeking in DUMBFILE and modified several readers to account for this change, which also reduces their overall memory usage

--- a/dumb/include/dumb.h
+++ b/dumb/include/dumb.h
@@ -160,6 +160,8 @@
 	int (*getc)(void *f);
 	long (*getnc)(char *ptr, long n, void *f);
 	void (*close)(void *f);
+    int (*seek)(void *f, long n);
+    long (*get_size)(void *f);
 }
 DUMBFILE_SYSTEM;
 
@@ -172,6 +174,14 @@
 
 long dumbfile_pos(DUMBFILE *f);
 int dumbfile_skip(DUMBFILE *f, long n);
+
+#define DFS_SEEK_SET 0
+#define DFS_SEEK_CUR 1
+#define DFS_SEEK_END 2
+
+int dumbfile_seek(DUMBFILE *f, long n, int origin);
+
+long dumbfile_get_size(DUMBFILE *f);
 
 int dumbfile_getc(DUMBFILE *f);
 
--- a/dumb/include/internal/riff.h
+++ b/dumb/include/internal/riff.h
@@ -1,11 +1,14 @@
 #ifndef RIFF_H
 #define RIFF_H
 
+struct riff;
+
 struct riff_chunk
 {
 	unsigned type;
-	void * data;
+    long offset;
 	unsigned size;
+    struct riff * nested;
 };
 
 struct riff
@@ -15,7 +18,7 @@
 	struct riff_chunk * chunks;
 };
 
-struct riff * riff_parse( unsigned char *, unsigned size, unsigned proper );
+struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper );
 void riff_free( struct riff * );
 
 #endif
--- a/dumb/src/core/dumbfile.c
+++ b/dumb/src/core/dumbfile.c
@@ -33,6 +33,8 @@
 	ASSERT(dfs->open);
 	ASSERT(dfs->getc);
 	ASSERT(dfs->close);
+    ASSERT(dfs->seek);
+    ASSERT(dfs->get_size);
 	the_dfs = dfs;
 }
 
@@ -371,6 +373,26 @@
 	f->pos += rv;
 
 	return rv;
+}
+
+
+
+int dumbfile_seek(DUMBFILE *f, long n, int origin)
+{
+    switch ( origin )
+    {
+    case DFS_SEEK_CUR: n += f->pos; break;
+    case DFS_SEEK_END: n += (*f->dfs->get_size)(f->file); break;
+    }
+    f->pos = n;
+    return (*f->dfs->seek)(f->file, n);
+}
+
+
+
+long dumbfile_get_size(DUMBFILE *f)
+{
+    return (*f->dfs->get_size)(f->file);
 }
 
 
--- a/dumb/src/helpers/riff.c
+++ b/dumb/src/helpers/riff.c
@@ -1,58 +1,57 @@
+#include "dumb.h"
 #include "internal/riff.h"
 
 #include <stdlib.h>
 
-struct riff * riff_parse( unsigned char * ptr, unsigned size, unsigned proper )
+struct riff * riff_parse( DUMBFILE * f, long offset, long size, unsigned proper )
 {
 	unsigned stream_size;
 	struct riff * stream;
 
-	if ( size < 8 ) return 0;
+    if ( size < 8 ) return 0;
 
-	if ( ptr[0] != 'R' || ptr[1] != 'I' || ptr[2] != 'F' || ptr[3] != 'F' ) return 0;
+    if ( dumbfile_seek(f, offset, DFS_SEEK_SET) ) return 0;
+    if ( dumbfile_mgetl(f) != DUMB_ID('R','I','F','F') ) return 0;
 
-	stream_size = ptr[4] | ( ptr[5] << 8 ) | ( ptr[6] << 16 ) | ( ptr[7] << 24 );
-	if ( stream_size + 8 > size ) return 0;
+    stream_size = dumbfile_igetl(f);
+    if ( stream_size + 8 > size ) return 0;
 	if ( stream_size < 4 ) return 0;
 
-	stream = malloc( sizeof( struct riff ) );
+    stream = (struct riff *) malloc( sizeof( struct riff ) );
 	if ( ! stream ) return 0;
 
-	stream->type = ( ptr[8] << 24 ) | ( ptr[9] << 16 ) | ( ptr[10] << 8 ) | ptr[11];
+    stream->type = dumbfile_mgetl(f);
 	stream->chunk_count = 0;
 	stream->chunks = 0;
 
-	ptr += 12;
 	stream_size -= 4;
 
-	while ( stream_size )
+    while ( stream_size && !dumbfile_error(f) )
 	{
 		struct riff_chunk * chunk;
 		if ( stream_size < 8 ) break;
-		stream->chunks = realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) );
+        stream->chunks = ( struct riff_chunk * ) realloc( stream->chunks, ( stream->chunk_count + 1 ) * sizeof( struct riff_chunk ) );
 		if ( ! stream->chunks ) break;
 		chunk = stream->chunks + stream->chunk_count;
-		chunk->type = ( ptr[0] << 24 ) | ( ptr[1] << 16 ) | ( ptr[2] << 8 ) | ptr[3];
-		chunk->size = ptr[4] | ( ptr[5] << 8 ) | ( ptr[6] << 16 ) | ( ptr[7] << 24 );
-		ptr += 8;
+        chunk->type = dumbfile_mgetl(f);
+        chunk->size = dumbfile_igetl(f);
+        chunk->offset = dumbfile_pos(f);
 		stream_size -= 8;
 		if ( stream_size < chunk->size ) break;
-		if ( chunk->type == 'RIFF' )
+        if ( chunk->type == DUMB_ID('R','I','F','F') )
 		{
-			chunk->data = riff_parse( ptr - 8, chunk->size + 8, proper );
-			if ( ! chunk->data ) break;
+            chunk->nested = riff_parse( f, chunk->offset - 8, chunk->size + 8, proper );
+            if ( ! chunk->nested ) break;
 		}
 		else
 		{
-			chunk->data = malloc( chunk->size );
-			if ( ! chunk->data ) break;
-			memcpy( chunk->data, ptr, chunk->size );
+            chunk->nested = 0;
 		}
-		ptr += chunk->size;
+        dumbfile_seek(f, chunk->offset + chunk->size, DFS_SEEK_SET);
 		stream_size -= chunk->size;
 		if ( proper && ( chunk->size & 1 ) )
 		{
-			++ ptr;
+            dumbfile_skip(f, 1);
 			-- stream_size;
 		}
 		++stream->chunk_count;
@@ -77,8 +76,7 @@
 			for ( i = 0; i < stream->chunk_count; ++i )
 			{
 				struct riff_chunk * chunk = stream->chunks + i;
-				if ( chunk->type == 'RIFF' ) riff_free( ( struct riff * ) chunk->data );
-				else free( chunk->data );
+                if ( chunk->nested ) riff_free( chunk->nested );
 			}
 			free( stream->chunks );
 		}
--- a/dumb/src/helpers/stdfile.c
+++ b/dumb/src/helpers/stdfile.c
@@ -23,9 +23,23 @@
 
 
 
+typedef struct dumb_stdfile
+{
+    FILE * file;
+    long size;
+} dumb_stdfile;
+
+
+
 static void *dumb_stdfile_open(const char *filename)
 {
-	return fopen(filename, "rb");
+    dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
+    if ( !file ) return 0;
+    file->file = fopen(filename, "rb");
+    fseek(file->file, 0, SEEK_END);
+    file->size = ftell(file->file);
+    fseek(file->file, 0, SEEK_SET);
+    return file;
 }
 
 
@@ -32,7 +46,8 @@
 
 static int dumb_stdfile_skip(void *f, long n)
 {
-	return fseek(f, n, SEEK_CUR);
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    return fseek(file->file, n, SEEK_CUR);
 }
 
 
@@ -39,7 +54,8 @@
 
 static int dumb_stdfile_getc(void *f)
 {
-	return fgetc(f);
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    return fgetc(file->file);
 }
 
 
@@ -46,7 +62,8 @@
 
 static long dumb_stdfile_getnc(char *ptr, long n, void *f)
 {
-	return fread(ptr, 1, n, f);
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    return fread(ptr, 1, n, file->file);
 }
 
 
@@ -53,17 +70,44 @@
 
 static void dumb_stdfile_close(void *f)
 {
-	fclose(f);
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    fclose(file->file);
+    free(f);
 }
 
 
 
+static void dumb_stdfile_noclose(void *f)
+{
+    free(f);
+}
+
+
+
+static int dumb_stdfile_seek(void *f, long n)
+{
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    return fseek(file->file, n, SEEK_SET);
+}
+
+
+
+static long dumb_stdfile_get_size(void *f)
+{
+    dumb_stdfile * file = ( dumb_stdfile * ) f;
+    return file->size;
+}
+
+
+
 static const DUMBFILE_SYSTEM stdfile_dfs = {
 	&dumb_stdfile_open,
 	&dumb_stdfile_skip,
 	&dumb_stdfile_getc,
 	&dumb_stdfile_getnc,
-	&dumb_stdfile_close
+    &dumb_stdfile_close,
+    &dumb_stdfile_seek,
+    &dumb_stdfile_get_size
 };
 
 
@@ -80,7 +124,9 @@
 	&dumb_stdfile_skip,
 	&dumb_stdfile_getc,
 	&dumb_stdfile_getnc,
-	NULL
+    &dumb_stdfile_noclose,
+    &dumb_stdfile_seek,
+    &dumb_stdfile_get_size
 };
 
 
@@ -87,7 +133,13 @@
 
 DUMBFILE *dumbfile_open_stdfile(FILE *p)
 {
-	DUMBFILE *d = dumbfile_open_ex(p, &stdfile_dfs_leave_open);
+    dumb_stdfile * file = ( dumb_stdfile * ) malloc( sizeof(dumb_stdfile) );
+    if ( !file ) return 0;
+    file->file = p;
+    fseek(p, 0, SEEK_END);
+    file->size = ftell(p);
+    fseek(p, 0, SEEK_SET);
+    DUMBFILE *d = dumbfile_open_ex(file, &stdfile_dfs_leave_open);
 
 	return d;
 }
--- a/dumb/src/it/itread.c
+++ b/dumb/src/it/itread.c
@@ -32,78 +32,6 @@
 
 
 
-typedef struct tdumbfile_mem_status
-{
-    const unsigned char * ptr;
-    unsigned offset, size;
-} dumbfile_mem_status;
-
-
-
-static int dumbfile_mem_skip(void * f, long n)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    s->offset += n;
-    if (s->offset > s->size)
-    {
-        s->offset = s->size;
-        return 1;
-    }
-
-    return 0;
-}
-
-
-
-static int dumbfile_mem_getc(void * f)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    if (s->offset < s->size)
-    {
-        return *(s->ptr + s->offset++);
-    }
-    return -1;
-}
-
-
-
-static long dumbfile_mem_getnc(char * ptr, long n, void * f)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    long max = s->size - s->offset;
-    if (max > n) max = n;
-    if (max)
-    {
-        memcpy(ptr, s->ptr + s->offset, max);
-        s->offset += max;
-    }
-    return max;
-}
-
-
-
-static DUMBFILE_SYSTEM mem_dfs = {
-    NULL, // open
-    &dumbfile_mem_skip,
-    &dumbfile_mem_getc,
-    &dumbfile_mem_getnc,
-    NULL // close
-};
-
-
-
-static int it_seek(dumbfile_mem_status * s, long offset)
-{
-    if ( offset > s->size )
-        return -1;
-
-    s->offset = offset;
-
-	return 0;
-}
-
-
-
 typedef unsigned char byte;
 typedef unsigned short word;
 typedef unsigned long dword;
@@ -1013,47 +941,8 @@
 
 	unsigned char *buffer;
 
-    unsigned char *file_buffer = NULL;
-    unsigned int file_size = 0;
-    int block_size;
-
-    dumbfile_mem_status memdata;
-
-    do
-    {
-        void * temp = realloc( file_buffer, file_size + 32768 );
-        if ( !temp )
-        {
-            if ( file_buffer ) free( file_buffer );
-            return NULL;
-        }
-        file_buffer = temp;
-        block_size = dumbfile_getnc( file_buffer + file_size, 32768, f );
-        if ( block_size < 0 )
-        {
-            free( file_buffer );
-            return NULL;
-        }
-        file_size += block_size;
-    }
-    while ( block_size == 32768 );
-
-    memdata.ptr = file_buffer;
-    memdata.offset = 0;
-    memdata.size = file_size;
-
-    f = dumbfile_open_ex(&memdata, &mem_dfs);
-
-    if ( !f )
-    {
-        free( file_buffer );
-        return NULL;
-    }
-
 	if (dumbfile_mgetl(f) != IT_SIGNATURE)
     {
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
     }
 
@@ -1061,8 +950,6 @@
 
 	if (!sigdata)
     {
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
     }
 
@@ -1113,8 +1000,6 @@
 	// XXX sample count
 	if (dumbfile_error(f) || sigdata->n_orders <= 0 || sigdata->n_instruments > 256 || sigdata->n_samples > 4000 || sigdata->n_patterns > 256) {
 		_dumb_it_unload_sigdata(sigdata);
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
 	}
 
@@ -1121,8 +1006,6 @@
 	sigdata->order = malloc(sigdata->n_orders);
 	if (!sigdata->order) {
 		_dumb_it_unload_sigdata(sigdata);
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
 	}
 
@@ -1130,8 +1013,6 @@
 		sigdata->instrument = malloc(sigdata->n_instruments * sizeof(*sigdata->instrument));
 		if (!sigdata->instrument) {
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 	}
@@ -1140,8 +1021,6 @@
 		sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
 		if (!sigdata->sample) {
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 		for (n = 0; n < sigdata->n_samples; n++)
@@ -1152,8 +1031,6 @@
 		sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
 		if (!sigdata->pattern) {
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 		for (n = 0; n < sigdata->n_patterns; n++)
@@ -1166,8 +1043,6 @@
 	component = malloc(769 * sizeof(*component));
 	if (!component) {
 		_dumb_it_unload_sigdata(sigdata);
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
 	}
 
@@ -1212,8 +1087,6 @@
 	if (dumbfile_error(f)) {
 		free(component);
 		_dumb_it_unload_sigdata(sigdata);
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
 	}
 
@@ -1234,8 +1107,6 @@
 		if (!sigdata->midi) {
 			free(component);
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 			// Should we be happy with this outcome in some situations?
 		}
@@ -1244,8 +1115,6 @@
 		if (dumbfile_error(f) || dumbfile_skip(f, 8*i)) {
 			free(component);
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 		/* Read embedded MIDI configuration */
@@ -1253,8 +1122,6 @@
 		if (dumbfile_skip(f, 32*9)) {
 			free(component);
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 		for (i = 0; i < 16; i++) {
@@ -1263,8 +1130,6 @@
 			if (dumbfile_getnc(mididata, 32, f) < 32) {
 				free(component);
 				_dumb_it_unload_sigdata(sigdata);
-                dumbfile_close(f);
-                free(file_buffer);
 				return NULL;
 			}
 			sigdata->midi->SFmacroz[i] = 0;
@@ -1326,8 +1191,6 @@
 	if (!buffer) {
 		free(component);
 		_dumb_it_unload_sigdata(sigdata);
-        dumbfile_close(f);
-        free(file_buffer);
 		return NULL;
 	}
 
@@ -1356,12 +1219,10 @@
 			continue;
 		}
 
-        if (it_seek(&memdata, component[n].offset)) {
+        if (dumbfile_seek(f, component[n].offset, DFS_SEEK_SET)) {
 			free(buffer);
 			free(component);
 			_dumb_it_unload_sigdata(sigdata);
-            dumbfile_close(f);
-            free(file_buffer);
 			return NULL;
 		}
 
@@ -1377,8 +1238,6 @@
 						free(buffer);
 						free(component);
 						_dumb_it_unload_sigdata(sigdata);
-                        dumbfile_close(f);
-                        free(file_buffer);
 						return NULL;
 					}
 					sigdata->song_message[message_length] = 0;
@@ -1395,8 +1254,6 @@
 					free(buffer);
 					free(component);
 					_dumb_it_unload_sigdata(sigdata);
-                    dumbfile_close(f);
-                    free(file_buffer);
 					return NULL;
 				}
 				break;
@@ -1406,8 +1263,6 @@
 					free(buffer);
 					free(component);
 					_dumb_it_unload_sigdata(sigdata);
-                    dumbfile_close(f);
-                    free(file_buffer);
 					return NULL;
 				}
 				break;
@@ -1417,8 +1272,6 @@
 					free(buffer);
 					free(component);
 					_dumb_it_unload_sigdata(sigdata);
-                    dumbfile_close(f);
-                    free(file_buffer);
 					return NULL;
 				}
 
@@ -1445,12 +1298,10 @@
 		m = component[n].sampfirst;
 
 		while (m >= 0) {
-            if (it_seek(&memdata, component[m].offset)) {
+            if (dumbfile_seek(f, component[m].offset, DFS_SEEK_SET)) {
 				free(buffer);
 				free(component);
 				_dumb_it_unload_sigdata(sigdata);
-                dumbfile_close(f);
-                free(file_buffer);
 				return NULL;
 			}
 
@@ -1458,8 +1309,6 @@
 				free(buffer);
 				free(component);
 				_dumb_it_unload_sigdata(sigdata);
-                dumbfile_close(f);
-                free(file_buffer);
 				return NULL;
 			}
 
@@ -1503,7 +1352,7 @@
         }
 
         mptx_id = dumbfile_igetl( f );
-        while ( memdata.offset < file_size )
+        while ( dumbfile_pos(f) < dumbfile_get_size(f) )
         {
             unsigned int size = dumbfile_igetw( f );
             switch (mptx_id)
@@ -1527,9 +1376,6 @@
 
     free(buffer);
 	free(component);
-
-    dumbfile_close(f);
-    free(file_buffer);
 
 	_dumb_it_fix_invalid_orders(sigdata);
 
--- a/dumb/src/it/readam.c
+++ b/dumb/src/it/readam.c
@@ -24,7 +24,7 @@
 #include "internal/it.h"
 #include "internal/riff.h"
 
-static int it_riff_am_process_sample( IT_SAMPLE * sample, const unsigned char * data, int len, int ver )
+static int it_riff_am_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len, int ver )
 {
 	int header_length;
 	int default_pan;
@@ -34,49 +34,51 @@
 	int length_bytes;
 	int loop_start;
 	int loop_end;
-	int sample_rate;
+    int sample_rate;
 
+    long start = dumbfile_pos( f );
+
 	if ( ver == 0 )
-	{
+    {
 		if ( len < 0x38 )
 			return -1;
 
 		header_length = 0x38;
 
-		memcpy( sample->name, data, 28 );
+        dumbfile_getnc( sample->name, 28, f );
 		sample->name[ 28 ] = 0;
 
-		default_pan = data[ 0x1C ];
-		default_volume = data[ 0x1D ];
-		flags = data[ 0x1E ] | ( data[ 0x1F ] << 8 );
-		length = data[ 0x20 ] | ( data[ 0x21 ] << 8 ) | ( data[ 0x22 ] << 16 ) | ( data[ 0x23 ] << 24 );
-		loop_start = data[ 0x24 ] | ( data[ 0x25 ] << 8 ) | ( data[ 0x26 ] << 16 ) | ( data[ 0x27 ] << 24 );
-		loop_end = data[ 0x28 ] | ( data[ 0x29 ] << 8 ) | ( data[ 0x2A ] << 16 ) | ( data[ 0x2B ] << 24 );
-		sample_rate = data[ 0x2C ] | ( data[ 0x2D ] << 8 ) | ( data[ 0x2E ] << 16 ) | ( data[ 0x2F ] << 24 );
+        default_pan = dumbfile_getc( f );
+        default_volume = dumbfile_getc( f );
+        flags = dumbfile_igetw( f );
+        length = dumbfile_igetl( f );
+        loop_start = dumbfile_igetl( f );
+        loop_end = dumbfile_igetl( f );
+        sample_rate = dumbfile_igetl( f );
 	}
 	else
 	{
 		if (len < 4) return -1;
 
-		header_length = data[ 0 ] | ( data[ 1 ] << 8 ) | ( data[ 2 ] << 16 ) | ( data[ 3 ] << 24 );
+        header_length = dumbfile_igetl( f );
 		if ( header_length < 0x40 )
 			return -1;
 		if ( header_length + 4 > len )
 			return -1;
 
-		data += 4;
+        start += 4;
 		len -= 4;
 
-		memcpy( sample->name, data, 32 );
-		sample->name[ 32 ] = 0;
+        dumbfile_getnc( sample->name, 32, f );
 
-		default_pan = data[ 0x20 ] | ( data[ 0x21 ] << 8 );
-		default_volume = data[ 0x22 ] | ( data[ 0x23 ] << 8 );
-		flags = data[ 0x24 ] | ( data[ 0x25 ] << 8 ); /* | ( data[ 0x26 ] << 16 ) | ( data[ 0x27 ] << 24 );*/
-		length = data[ 0x28 ] | ( data[ 0x29 ] << 8 ) | ( data[ 0x2A ] << 16 ) | ( data[ 0x2B ] << 24 );
-		loop_start = data[ 0x2C ] | ( data[ 0x2D ] << 8 ) | ( data[ 0x2E ] << 16 ) | ( data[ 0x2F ] << 24 );
-		loop_end = data[ 0x30 ] | ( data[ 0x31 ] << 8 ) | ( data[ 0x32 ] << 16 ) | ( data[ 0x33 ] << 24 );
-		sample_rate = data[ 0x34 ] | ( data[ 0x35 ] << 8 ) | ( data[ 0x36 ] << 16 ) | ( data[ 0x37 ] << 24 );
+        default_pan = dumbfile_igetw( f );
+        default_volume = dumbfile_igetw( f );
+        flags = dumbfile_igetw( f );
+        dumbfile_skip( f, 2 );
+        length = dumbfile_igetl( f );
+        loop_start = dumbfile_igetl( f );
+        loop_end = dumbfile_igetl( f );
+        sample_rate = dumbfile_igetl( f );
 
 		if ( default_pan > 0x7FFF || default_volume > 0x7FFF )
 			return -1;
@@ -85,9 +87,6 @@
 		default_volume = default_volume * 64 / 32767;
 	}
 
-	/*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
-		return -1;*/
-
 	if ( ! length ) {
 		sample->flags &= ~IT_SAMPLE_EXISTS;
 		return 0;
@@ -138,43 +137,49 @@
 	if ( ! sample->data )
 		return -1;
 
-	memcpy( sample->data, data + header_length, length_bytes );
+    if ( dumbfile_seek( f, start + header_length, DFS_SEEK_SET ) )
+        return -1;
 
+    dumbfile_getnc( sample->data, length_bytes, f );
+
 	return 0;
 }
 
-static int it_riff_am_process_pattern( IT_PATTERN * pattern, const unsigned char * data, int len, int ver )
+static int it_riff_am_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len, int ver )
 {
-	int nrows, row, pos;
+    int nrows, row;
+    long start, end;
 	unsigned flags;
+    int p, q, r;
 	IT_ENTRY * entry;
 
-	nrows = data[0] + 1;
+    nrows = dumbfile_getc( f ) + 1;
 
 	pattern->n_rows = nrows;
 
-	data += 1;
 	len -= 1;
 
 	pattern->n_entries = 0;
 
 	row = 0;
-	pos = 0;
 
-	while ( (row < nrows) && (pos < len) ) {
-		if ( ! data[ pos ] ) {
+    start = dumbfile_pos( f );
+    end = start + len;
+
+    while ( (row < nrows) && (dumbfile_pos( f ) < end) ) {
+        p = dumbfile_getc( f );
+        if ( ! p ) {
 			++ row;
-			++ pos;
 			continue;
 		}
 
-		flags = data[ pos++ ] & 0xE0;
+        flags = p & 0xE0;
 
-		if (flags) {
+        if (flags) {
 			++ pattern->n_entries;
-			if (flags & 0x80) pos += 2;
-			if (flags & 0x40) pos += 2;
-			if (flags & 0x20) pos ++;
+            if (flags & 0x80) dumbfile_skip( f, 2 );
+            if (flags & 0x40) dumbfile_skip( f, 2 );
+            if (flags & 0x20) dumbfile_skip( f, 1 );
 		}
 	}
 
@@ -188,20 +193,22 @@
 	entry = pattern->entry;
 
 	row = 0;
-	pos = 0;
 
-	while ( ( row < nrows ) && ( pos < len ) )
+    dumbfile_seek( f, start, DFS_SEEK_SET );
+
+    while ( ( row < nrows ) && ( dumbfile_pos( f ) < end ) )
 	{
-		if ( ! data[ pos ] )
+        p = dumbfile_getc( f );
+
+        if ( ! p )
 		{
 			IT_SET_END_ROW( entry );
 			++ entry;
 			++ row;
-			++ pos;
 			continue;
 		}
 
-		flags = data[ pos++ ];
+        flags = p;
 		entry->channel = flags & 0x1F;
 		entry->mask = 0;
 
@@ -209,31 +216,33 @@
 		{
 			if ( flags & 0x80 )
 			{
-				_dumb_it_xm_convert_effect( data[ pos + 1 ], data[ pos ], entry, 0 );
-				pos += 2;
+                q = dumbfile_getc( f );
+                r = dumbfile_getc( f );
+                _dumb_it_xm_convert_effect( r, q, entry, 0 );
 			}
 
 			if ( flags & 0x40 )
 			{
-				if ( data[ pos ] )
+                q = dumbfile_getc( f );
+                r = dumbfile_getc( f );
+                if ( q )
 				{
 					entry->mask |= IT_ENTRY_INSTRUMENT;
-					entry->instrument = data[ pos ];
+                    entry->instrument = q;
 				}
-				if ( data[ pos + 1 ] )
+                if ( r )
 				{
 					entry->mask |= IT_ENTRY_NOTE;
-					entry->note = data[ pos + 1 ] - 1;
+                    entry->note = r - 1;
 				}
-				pos += 2;
 			}
 
 			if ( flags & 0x20 )
 			{
+                q = dumbfile_getc( f );
 				entry->mask |= IT_ENTRY_VOLPAN;
-				if ( ver == 0 ) entry->volpan = data[ pos ];
-				else entry->volpan = data[ pos ] * 64 / 127;
-				++ pos;
+                if ( ver == 0 ) entry->volpan = q;
+                else entry->volpan = q * 64 / 127;
 			}
 
 			if (entry->mask) entry++;
@@ -253,11 +262,11 @@
 	return 0;
 }
 
-static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( struct riff * stream )
+static DUMB_IT_SIGDATA *it_riff_amff_load_sigdata( DUMBFILE * f, struct riff * stream )
 {
 	DUMB_IT_SIGDATA *sigdata;
 
-	int n, o, found;
+    int n, o, p, found;
 
 	unsigned char * ptr;
 
@@ -290,10 +299,11 @@
 			found |= 2;
 			break;
 
-		case DUMB_ID( 'P', 'A', 'T', 'T' ):
-			ptr = ( unsigned char * ) c->data;
-			if ( ptr[ 0 ] >= sigdata->n_patterns ) sigdata->n_patterns = ptr[ 0 ] + 1;
-			o = ptr[ 1 ] | ( ptr[ 2 ] << 8 ) | ( ptr[ 3 ] << 16 ) | ( ptr[ 4 ] << 24 );
+        case DUMB_ID( 'P', 'A', 'T', 'T' ):
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
+            o = dumbfile_getc( f );
+            if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
+            o = dumbfile_igetl( f );
 			if ( o + 5 > c->size ) goto error_sd;
 			break;
 
@@ -300,13 +310,17 @@
 		case DUMB_ID( 'I', 'N', 'S', 'T' ):
 			{
 				if ( c->size < 0xE1 ) goto error;
-				ptr = ( unsigned char * ) c->data;
-				if ( ptr[ 1 ] >= sigdata->n_samples ) sigdata->n_samples = ptr[ 1 ] + 1;
-				if ( c->size >= 0x121 && ( ptr[ 0xE1 ] == 'S' && ptr[ 0xE2 ] == 'A' &&
-					ptr[ 0xE3 ] == 'M' && ptr[ 0xE4 ] == 'P' ) )
-				{
-					unsigned size = ptr[ 0xE5 ] | ( ptr[ 0xE6 ] << 8 ) | ( ptr[ 0xE7 ] << 16 ) | ( ptr[ 0xE8 ] << 24 );
-					if ( size + 0xE1 + 8 > c->size ) goto error;
+                if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_sd;
+                o = dumbfile_getc( f );
+                if ( o >= sigdata->n_samples ) sigdata->n_samples = o + 1;
+                if ( c->size >= 0x121 )
+                {
+                    if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_sd;
+                    if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
+                    {
+                        unsigned size = dumbfile_igetl( f );
+                        if ( size + 0xE1 + 8 > c->size ) goto error_sd;
+                    }
 				}
 			}
 			break;
@@ -347,24 +361,28 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'M', 'A', 'I', 'N' ):
-			ptr = ( unsigned char * ) c->data;
-			memcpy( sigdata->name, c->data, 64 );
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            dumbfile_getnc( sigdata->name, 64, f );
 			sigdata->name[ 64 ] = 0;
 			sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
-			if ( ! ( ptr[ 0x40 ] & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
-			if ( ( ptr[ 0x40 ] & ~3 ) || ! ( ptr[ 0x40 ] & 2 ) ) goto error_usd; // unknown flags
-			sigdata->n_pchannels = ptr[ 0x41 ];
-			sigdata->speed = ptr[ 0x42 ];
-			sigdata->tempo = ptr[ 0x43 ];
+            o = dumbfile_getc( f );
+            if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
+            if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
+            sigdata->n_pchannels = dumbfile_getc( f );
+            sigdata->speed = dumbfile_getc( f );
+            sigdata->tempo = dumbfile_getc( f );
 
-			sigdata->global_volume = ptr[ 0x48 ];
+            dumbfile_skip( f, 4 );
 
+            sigdata->global_volume = dumbfile_getc( f );
+
 			if ( c->size < 0x48 + sigdata->n_pchannels ) goto error_usd;
 
 			for ( o = 0; o < sigdata->n_pchannels; ++o )
 			{
-				sigdata->channel_pan[ o ] = ptr[ 0x49 + o ];
-				if ( ptr[ 0x49 + o ] >= 128 )
+                p = dumbfile_getc( f );
+                sigdata->channel_pan[ o ] = p;
+                if ( p >= 128 )
 				{
 					sigdata->channel_volume[ o ] = 0;
 				}
@@ -394,37 +412,40 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'O', 'R', 'D', 'R' ):
-			ptr = ( unsigned char * ) c->data;
-			sigdata->n_orders = ptr[ 0 ] + 1;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            sigdata->n_orders = dumbfile_getc( f ) + 1;
 			if ( sigdata->n_orders + 1 > c->size ) goto error_usd;
 			sigdata->order = malloc( sigdata->n_orders );
 			if ( ! sigdata->order ) goto error_usd;
-			memcpy( sigdata->order, ptr + 1, sigdata->n_orders );
+            dumbfile_getnc( sigdata->order, sigdata->n_orders, f );
 			break;
 
 		case DUMB_ID( 'P', 'A', 'T', 'T' ):
-			ptr = ( unsigned char * ) c->data;
-			o = ptr[ 1 ] | ( ptr[ 2 ] << 8 ) | ( ptr[ 3 ] << 16 ) | ( ptr[ 4 ] << 24 );
-			if ( it_riff_am_process_pattern( sigdata->pattern + ptr[ 0 ], ptr + 5, o, 0 ) ) goto error_usd;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            o = dumbfile_getc( f );
+            p = dumbfile_igetl( f );
+            if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 0 ) ) goto error_usd;
 			break;
 
 		case DUMB_ID( 'I', 'N', 'S', 'T' ):
 			{
 				IT_SAMPLE * sample;
-				ptr = ( unsigned char * ) c->data;
-				sample = sigdata->sample + ptr[ 1 ];
-				if ( c->size >= 0x121 && ( ptr[ 0xE1 ] == 'S' && ptr[ 0xE2 ] == 'A' &&
-					ptr[ 0xE3 ] == 'M' && ptr[ 0xE4 ] == 'P' ) )
-				{
-					unsigned size = ptr[ 0xE5 ] | ( ptr[ 0xE6 ] << 8 ) | ( ptr[ 0xE7 ] << 16 ) | ( ptr[ 0xE8 ] << 24 );
-					if ( it_riff_am_process_sample( sample, ptr + 0xE1 + 8, size, 0 ) ) goto error_usd;
+                if ( dumbfile_seek( f, c->offset + 1, DFS_SEEK_SET ) ) goto error_usd;
+                sample = sigdata->sample + dumbfile_getc( f );
+                if ( c->size >= 0x121 )
+                {
+                    if ( dumbfile_seek( f, c->offset + 0xE1, DFS_SEEK_SET ) ) goto error_usd;
+                    if ( dumbfile_mgetl( f ) == DUMB_ID('S','A','M','P') )
+                    {
+                        unsigned size = dumbfile_igetl( f );
+                        if ( it_riff_am_process_sample( sample, f, size, 0 ) ) goto error_usd;
+                        break;
+                    }
 				}
-				else
-				{
-					memcpy( sample->name, ptr + 2, 28 );
-					sample->name[ 28 ] = 0;
-				}
-			}
+                dumbfile_seek( f, c->offset + 2, DFS_SEEK_SET );
+                dumbfile_getnc( sample->name, 28, f );
+                sample->name[ 28 ] = 0;
+            }
 			break;
 		}
 	}
@@ -442,7 +463,7 @@
 	return NULL;
 }
 
-static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( struct riff * stream )
+static DUMB_IT_SIGDATA *it_riff_am_load_sigdata( DUMBFILE * f, struct riff * stream )
 {
 	DUMB_IT_SIGDATA *sigdata;
 
@@ -450,7 +471,7 @@
 
 	unsigned char * ptr;
 
-	if ( ! stream ) goto error;
+    if ( ! f || ! stream ) goto error;
 
 	if ( stream->type != DUMB_ID( 'A', 'M', ' ', ' ' ) ) goto error;
 
@@ -480,15 +501,16 @@
 			break;
 
 		case DUMB_ID( 'P', 'A', 'T', 'T' ):
-			ptr = ( unsigned char * ) c->data;
-			if ( ptr[ 0 ] >= sigdata->n_patterns ) sigdata->n_patterns = ptr[ 0 ] + 1;
-			o = ptr[ 1 ] | ( ptr[ 2 ] << 8 ) | ( ptr[ 3 ] << 16 ) | ( ptr[ 4 ] << 24 );
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_sd;
+            o = dumbfile_getc( f );
+            if ( o >= sigdata->n_patterns ) sigdata->n_patterns = o + 1;
+            o = dumbfile_igetl( f );
 			if ( o + 5 > c->size ) goto error_sd;
 			break;
 
 		case DUMB_ID( 'R', 'I', 'F', 'F' ):
 			{
-				struct riff * str = ( struct riff * ) c->data;
+                struct riff * str = c->nested;
 				switch ( str->type )
 				{
 				case DUMB_ID( 'A', 'I', ' ', ' ' ):
@@ -502,12 +524,14 @@
 								struct riff * temp;
 								unsigned size;
 								unsigned sample_found;
-								ptr = ( unsigned char * ) chk->data;
-								size = ptr[ 0 ] | ( ptr[ 1 ] << 8 ) | ( ptr[ 2 ] << 16 ) | ( ptr[ 3 ] << 24 );
-								if ( size < 0x142 ) goto error;
+                                if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_sd;
+                                size = dumbfile_igetl( f );
+								if ( size < 0x142 ) goto error_sd;
 								sample_found = 0;
-								if ( ptr[ 5 ] >= sigdata->n_samples ) sigdata->n_samples = ptr[ 5 ] + 1;
-								temp = riff_parse( ptr + 4 + size, chk->size - size - 4, 1 );
+                                dumbfile_skip( f, 1 );
+                                p = dumbfile_getc( f );
+                                if ( p >= sigdata->n_samples ) sigdata->n_samples = p + 1;
+                                temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
 								if ( temp )
 								{
 									if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
@@ -519,7 +543,7 @@
 												if ( sample_found )
 												{
 													riff_free( temp );
-													goto error;
+                                                    goto error_sd;
 												}
 												sample_found = 1;
 											}
@@ -570,25 +594,29 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'I', 'N', 'I', 'T' ):
-			ptr = ( unsigned char * ) c->data;
-			memcpy( sigdata->name, c->data, 64 );
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            dumbfile_getnc( sigdata->name, 64, f );
 			sigdata->name[ 64 ] = 0;
 			sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_WAS_AN_S3M;
-			if ( ! ( ptr[ 0x40 ] & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
-			if ( ( ptr[ 0x40 ] & ~3 ) || ! ( ptr[ 0x40 ] & 2 ) ) goto error_usd; // unknown flags
-			sigdata->n_pchannels = ptr[ 0x41 ];
-			sigdata->speed = ptr[ 0x42 ];
-			sigdata->tempo = ptr[ 0x43 ];
+            o = dumbfile_getc( f );
+            if ( ! ( o & 1 ) ) sigdata->flags |= IT_LINEAR_SLIDES;
+            if ( ( o & ~3 ) || ! ( o & 2 ) ) goto error_usd; // unknown flags
+            sigdata->n_pchannels = dumbfile_getc( f );
+            sigdata->speed = dumbfile_getc( f );
+            sigdata->tempo = dumbfile_getc( f );
 
-			sigdata->global_volume = ptr[ 0x48 ];
+            dumbfile_skip( f, 4 );
 
+            sigdata->global_volume = dumbfile_getc( f );
+
 			if ( c->size < 0x48 + sigdata->n_pchannels ) goto error_usd;
 
 			for ( o = 0; o < sigdata->n_pchannels; ++o )
 			{
-				if ( ptr[ 0x49 + o ] <= 128 )
+                p = dumbfile_getc( f );
+                if ( p <= 128 )
 				{
-					sigdata->channel_pan[ o ] = ptr[ 0x49 + o ] / 2;
+                    sigdata->channel_pan[ o ] = p / 2;
 				}
 				else
 				{
@@ -620,23 +648,24 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'O', 'R', 'D', 'R' ):
-			ptr = ( unsigned char * ) c->data;
-			sigdata->n_orders = ptr[ 0 ] + 1;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            sigdata->n_orders = dumbfile_getc( f ) + 1;
 			if ( sigdata->n_orders + 1 > c->size ) goto error_usd;
 			sigdata->order = malloc( sigdata->n_orders );
 			if ( ! sigdata->order ) goto error_usd;
-			memcpy( sigdata->order, ptr + 1, sigdata->n_orders );
+            dumbfile_getnc( sigdata->order, sigdata->n_orders, f );
 			break;
 
 		case DUMB_ID( 'P', 'A', 'T', 'T' ):
-			ptr = ( unsigned char * ) c->data;
-			o = ptr[ 1 ] | ( ptr[ 2 ] << 8 ) | ( ptr[ 3 ] << 16 ) | ( ptr[ 4 ] << 24 );
-			if ( it_riff_am_process_pattern( sigdata->pattern + ptr[ 0 ], ptr + 5, o, 1 ) ) goto error_usd;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            o = dumbfile_getc( f );
+            p = dumbfile_igetl( f );
+            if ( it_riff_am_process_pattern( sigdata->pattern + o, f, p, 1 ) ) goto error_usd;
 			break;
 
 		case DUMB_ID( 'R', 'I', 'F', 'F' ):
 			{
-				struct riff * str = ( struct riff * ) c->data;
+                struct riff * str = c->nested;
 				switch ( str->type )
 				{
 				case DUMB_ID('A', 'I', ' ', ' '):
@@ -651,11 +680,13 @@
 								unsigned size;
 								unsigned sample_found;
 								IT_SAMPLE * sample;
-								ptr = ( unsigned char * ) chk->data;
-								size = ptr[ 0 ] | ( ptr[ 1 ] << 8 ) | ( ptr[ 2 ] << 16 ) | ( ptr[ 3 ] << 24 );
-								temp = riff_parse( ptr + 4 + size, chk->size - size - 4, 1 );
+                                if ( dumbfile_seek( f, chk->offset, DFS_SEEK_SET ) ) goto error_usd;
+                                size = dumbfile_igetl( f );
+                                dumbfile_skip( f, 1 );
+                                p = dumbfile_getc( f );
+                                temp = riff_parse( f, chk->offset + 4 + size, chk->size - size - 4, 1 );
 								sample_found = 0;
-								sample = sigdata->sample + ptr[ 5 ];
+                                sample = sigdata->sample + p;
 								if ( temp )
 								{
 									if ( temp->type == DUMB_ID( 'A', 'S', ' ', ' ' ) )
@@ -670,7 +701,12 @@
 													riff_free( temp );
 													goto error_usd;
 												}
-												if ( it_riff_am_process_sample( sigdata->sample + ptr[ 5 ], ( unsigned char * ) c->data, c->size, 1 ) )
+                                                if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) )
+                                                {
+                                                    riff_free( temp );
+                                                    goto error_usd;
+                                                }
+                                                if ( it_riff_am_process_sample( sample, f, c->size, 1 ) )
 												{
 													riff_free( temp );
 													goto error_usd;
@@ -683,7 +719,8 @@
 								}
 								if ( ! sample_found )
 								{
-									memcpy( sample->name, ptr + 6, 32 );
+                                    dumbfile_seek( f, chk->offset + 6, DFS_SEEK_SET );
+                                    dumbfile_getnc( sample->name, 32, f );
 									sample->name[ 32 ] = 0;
 								}
 							}
@@ -708,7 +745,7 @@
 	return NULL;
 }
 
-DUH *dumb_read_riff_amff( struct riff * stream )
+DUH *dumb_read_riff_amff( DUMBFILE * f, struct riff * stream )
 {
 	sigdata_t *sigdata;
 	long length;
@@ -715,7 +752,7 @@
 
 	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
 
-	sigdata = it_riff_amff_load_sigdata( stream );
+    sigdata = it_riff_amff_load_sigdata( f, stream );
 
 	if (!sigdata)
 		return NULL;
@@ -732,13 +769,13 @@
 	}
 }
 
-DUH *dumb_read_riff_am( struct riff * stream )
+DUH *dumb_read_riff_am( DUMBFILE * f, struct riff * stream )
 {
 	sigdata_t *sigdata;
 
 	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
 
-	sigdata = it_riff_am_load_sigdata( stream );
+    sigdata = it_riff_am_load_sigdata( f, stream );
 
 	if (!sigdata)
 		return NULL;
--- a/dumb/src/it/readany.c
+++ b/dumb/src/it/readany.c
@@ -28,221 +28,34 @@
 #define strnicmp strncasecmp
 #endif
 
-typedef struct BUFFERED_MOD BUFFERED_MOD;
+enum { maximum_signature_size = 0x30 };
 
-struct BUFFERED_MOD
-{
-    unsigned char *buffered;
-    long ptr, len;
-};
-
-
-
-static int buffer_mod_skip(void *f, long n)
-{
-    BUFFERED_MOD *bm = f;
-    if (bm->buffered) {
-        bm->ptr += n;
-        if (bm->ptr >= bm->len) {
-            free(bm->buffered);
-            bm->buffered = NULL;
-            return (bm->len - bm->ptr);
-        }
-        return 0;
-    }
-    return n ? -1 : 0;
-}
-
-
-
-static int buffer_mod_getc(void *f)
-{
-    BUFFERED_MOD *bm = f;
-    if (bm->buffered) {
-        int rv = bm->buffered[bm->ptr++];
-        if (bm->ptr >= bm->len) {
-            free(bm->buffered);
-            bm->buffered = NULL;
-        }
-        return rv;
-    }
-    return -1;
-}
-
-
-
-static long buffer_mod_getnc(char *ptr, long n, void *f)
-{
-    BUFFERED_MOD *bm = f;
-    if (bm->buffered) {
-        int left = bm->len - bm->ptr;
-        if (n >= left) {
-            memcpy(ptr, bm->buffered + bm->ptr, left);
-            free(bm->buffered);
-            bm->buffered = NULL;
-            return left;
-        }
-        memcpy(ptr, bm->buffered + bm->ptr, n);
-        bm->ptr += n;
-        return n;
-    }
-    return 0;
-}
-
-
-
-static void buffer_mod_close(void *f)
-{
-    BUFFERED_MOD *bm = f;
-    if (bm->buffered) free(bm->buffered);
-    free(f);
-}
-
-
-
-static DUMBFILE_SYSTEM buffer_mod_dfs = {
-    NULL,
-    &buffer_mod_skip,
-    &buffer_mod_getc,
-    &buffer_mod_getnc,
-    &buffer_mod_close
-};
-
-
-
-static DUMBFILE *dumbfile_buffer_mod(DUMBFILE *f, unsigned char const* * signature, unsigned long * signature_size)
-{
-    long read;
-    BUFFERED_MOD *bm = malloc(sizeof(*bm));
-    if (!bm) return NULL;
-
-    bm->buffered = malloc(32768);
-    if (!bm->buffered) {
-        free(bm);
-        return NULL;
-    }
-
-    bm->len = 0;
-    *signature_size = 0;
-
-    read = dumbfile_getnc(bm->buffered, 32768, f);
-
-    if (read >= 0) {
-        bm->len += read;
-        *signature_size += read;
-
-        while (read >= 32768) {
-            bm->buffered = realloc(bm->buffered, *signature_size + 32768);
-            if (!bm->buffered) {
-                free(bm);
-                return 0;
-            }
-            read = dumbfile_getnc(bm->buffered + *signature_size, 32768, f);
-            if (read >= 0) {
-                bm->len += read;
-                *signature_size += read;
-            }
-        }
-    }
-
-    if (*signature_size) {
-        bm->ptr = 0;
-        *signature = bm->buffered;
-    } else {
-        free(bm->buffered);
-        bm->buffered = NULL;
-    }
-
-    return dumbfile_open_ex(bm, &buffer_mod_dfs);
-}
-
-
-
-typedef struct tdumbfile_mem_status
-{
-    const unsigned char * ptr;
-    unsigned offset, size;
-} dumbfile_mem_status;
-
-
-
-static int dumbfile_mem_skip(void * f, long n)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    s->offset += n;
-    if (s->offset > s->size)
-    {
-        s->offset = s->size;
-        return 1;
-    }
-
-    return 0;
-}
-
-
-
-static int dumbfile_mem_getc(void * f)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    if (s->offset < s->size)
-    {
-        return *(s->ptr + s->offset++);
-    }
-    return -1;
-}
-
-
-
-static long dumbfile_mem_getnc(char * ptr, long n, void * f)
-{
-    dumbfile_mem_status * s = (dumbfile_mem_status *) f;
-    long max = s->size - s->offset;
-    if (max > n) max = n;
-    if (max)
-    {
-        memcpy(ptr, s->ptr + s->offset, max);
-        s->offset += max;
-    }
-    return max;
-}
-
-
-
-static DUMBFILE_SYSTEM mem_dfs = {
-    NULL, // open
-    &dumbfile_mem_skip,
-    &dumbfile_mem_getc,
-    &dumbfile_mem_getnc,
-    NULL // close
-};
-
-
-
 DUH *dumb_read_any_quick(DUMBFILE *f, int restrict, int subsong)
 {
-    unsigned char const* signature;
+    unsigned char signature[ maximum_signature_size ];
     unsigned long signature_size;
-    DUMBFILE * rem;
     DUH * duh = NULL;
 
-    rem = dumbfile_buffer_mod( f, &signature, &signature_size );
-    if ( !rem ) return NULL;
+    signature_size = dumbfile_get_size(f);
 
+    signature_size = dumbfile_getnc( signature, maximum_signature_size, f );
+    dumbfile_seek( f, 0, DFS_SEEK_SET );
+
     if (signature_size >= 4 &&
         signature[0] == 'I' && signature[1] == 'M' &&
         signature[2] == 'P' && signature[3] == 'M')
     {
-        duh = dumb_read_it_quick( rem );
+        duh = dumb_read_it_quick( f );
     }
     else if (signature_size >= 17 && !memcmp(signature, "Extended Module: ", 17))
     {
-        duh = dumb_read_xm_quick( rem );
+        duh = dumb_read_xm_quick( f );
     }
     else if (signature_size >= 0x30 &&
         signature[0x2C] == 'S' && signature[0x2D] == 'C' &&
         signature[0x2E] == 'R' && signature[0x2F] == 'M')
     {
-        duh = dumb_read_s3m_quick( rem );
+        duh = dumb_read_s3m_quick( f );
     }
     else if (signature_size >= 30 &&
         /*signature[28] == 0x1A &&*/ signature[29] == 2 &&
@@ -250,80 +63,67 @@
         ! strnicmp( ( const char * ) signature + 20, "BMOD2STM", 8 ) ||
         ! strnicmp( ( const char * ) signature + 20, "WUZAMOD!", 8 ) ) )
     {
-        duh = dumb_read_stm_quick( rem );
+        duh = dumb_read_stm_quick( f );
     }
     else if (signature_size >= 2 &&
         ((signature[0] == 0x69 && signature[1] == 0x66) ||
         (signature[0] == 0x4A && signature[1] == 0x4E)))
     {
-        duh = dumb_read_669_quick( rem );
+        duh = dumb_read_669_quick( f );
     }
     else if (signature_size >= 0x30 &&
         signature[0x2C] == 'P' && signature[0x2D] == 'T' &&
         signature[0x2E] == 'M' && signature[0x2F] == 'F')
     {
-        duh = dumb_read_ptm_quick( rem );
+        duh = dumb_read_ptm_quick( f );
     }
     else if (signature_size >= 4 &&
         signature[0] == 'P' && signature[1] == 'S' &&
         signature[2] == 'M' && signature[3] == ' ')
     {
-        duh = dumb_read_psm_quick( rem, subsong );
+        duh = dumb_read_psm_quick( f, subsong );
     }
     else if (signature_size >= 4 &&
         signature[0] == 'P' && signature[1] == 'S' &&
         signature[2] == 'M' && signature[3] == 254)
     {
-        duh = dumb_read_old_psm_quick( rem );
+        duh = dumb_read_old_psm_quick( f );
     }
     else if (signature_size >= 3 &&
         signature[0] == 'M' && signature[1] == 'T' &&
         signature[2] == 'M')
     {
-        duh = dumb_read_mtm_quick( rem );
+        duh = dumb_read_mtm_quick( f );
     }
     else if ( signature_size >= 4 &&
         signature[0] == 'R' && signature[1] == 'I' &&
         signature[2] == 'F' && signature[3] == 'F')
     {
-        duh = dumb_read_riff_quick( rem );
+        duh = dumb_read_riff_quick( f );
     }
     else if ( signature_size >= 24 &&
         !memcmp( signature, "ASYLUM Music Format", 19 ) &&
         !memcmp( signature + 19, " V1.0", 5 ) )
     {
-        duh = dumb_read_asy_quick( rem );
+        duh = dumb_read_asy_quick( f );
     }
     else if ( signature_size >= 3 &&
         signature[0] == 'A' && signature[1] == 'M' &&
         signature[2] == 'F')
     {
-        duh = dumb_read_amf_quick( rem );
+        duh = dumb_read_amf_quick( f );
     }
     else if ( signature_size >= 8 &&
         !memcmp( signature, "OKTASONG", 8 ) )
     {
-        duh = dumb_read_okt_quick( rem );
+        duh = dumb_read_okt_quick( f );
     }
 
     if ( !duh )
     {
-        dumbfile_mem_status memdata;
-		DUMBFILE * memf;
-
-        memdata.ptr = signature;
-        memdata.offset = 0;
-        memdata.size = signature_size;
-
-        memf = dumbfile_open_ex(&memdata, &mem_dfs);
-        if ( memf )
-        {
-            duh = dumb_read_mod_quick( memf, restrict );
-            dumbfile_close( memf );
-        }
+        dumbfile_seek( f, 0, DFS_SEEK_SET );
+        duh = dumb_read_mod_quick( f, restrict );
     }
-
-    dumbfile_close( rem );
 
     return duh;
 }
--- a/dumb/src/it/readdsmf.c
+++ b/dumb/src/it/readdsmf.c
@@ -24,20 +24,22 @@
 #include "internal/it.h"
 #include "internal/riff.h"
 
-static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, const unsigned char * data, int len )
+static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, DUMBFILE * f, int len )
 {
 	int flags;
 
-	memcpy( sample->filename, data, 13 );
+    dumbfile_getnc( sample->filename, 13, f );
 	sample->filename[ 14 ] = 0;
 	
-	flags = data[ 13 ] | ( data[ 14 ] << 8 );
-	sample->default_volume = data[ 15 ];
-	sample->length = data[ 16 ] | ( data[ 17 ] << 8 ) | ( data[ 18 ] << 16 ) | ( data[ 19 ] << 24 );
-	sample->loop_start = data[ 20 ] | ( data[ 21 ] << 8 ) | ( data[ 22 ] << 16 ) | ( data[ 23 ] << 24 );
-	sample->loop_end = data[ 24 ] | ( data[ 25 ] << 8 ) | ( data[ 26 ] << 16 ) | ( data[ 27 ] << 24 );
-	sample->C5_speed = ( data[ 32 ] | ( data[ 33 ] << 8 ) ) * 2;
-	memcpy( sample->name, data + 36, 28 );
+    flags = dumbfile_igetw( f );
+    sample->default_volume = dumbfile_getc( f );
+    sample->length = dumbfile_igetl( f );
+    sample->loop_start = dumbfile_igetl( f );
+    sample->loop_end = dumbfile_igetl( f );
+    dumbfile_skip( f, 32 - 28 );
+    sample->C5_speed = dumbfile_igetw( f ) * 2;
+    dumbfile_skip( f, 36 - 34 );
+    dumbfile_getnc( sample->name, 28, f );
 	sample->name[ 28 ] = 0;
 
 	/*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
@@ -80,7 +82,7 @@
 	if ( ! sample->data )
 		return -1;
 
-	memcpy( sample->data, data + 64, sample->length );
+    dumbfile_getnc( sample->data, sample->length, f );
 
 	if ( ! ( flags & 2 ) )
 	{
@@ -91,16 +93,17 @@
 	return 0;
 }
 
-static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, const unsigned char * data, int len )
+static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len )
 {
-	int length, row, pos;
+    int length, row;
 	unsigned flags;
+    long start, end;
+    int p, q, r;
 	IT_ENTRY * entry;
 
-	length = data[ 0 ] | ( data[ 1 ] << 8 );
+    length = dumbfile_igetw( f );
 	if ( length > len ) return -1;
 
-	data += 2;
 	len = length - 2;
 
 	pattern->n_rows = 64;
@@ -107,23 +110,25 @@
 	pattern->n_entries = 64;
 
 	row = 0;
-	pos = 0;
 
-	while ( (row < 64) && (pos < len) ) {
-		if ( ! data[ pos ] ) {
+    start = dumbfile_pos( f );
+    end = start + len;
+
+    while ( (row < 64) && (dumbfile_pos( f ) < end) ) {
+        p = dumbfile_getc( f );
+        if ( ! p ) {
 			++ row;
-			++ pos;
 			continue;
 		}
 
-		flags = data[ pos++ ] & 0xF0;
+        flags = p & 0xF0;
 
 		if (flags) {
 			++ pattern->n_entries;
-			if (flags & 0x80) pos ++;
-			if (flags & 0x40) pos ++;
-			if (flags & 0x20) pos ++;
-			if (flags & 0x10) pos += 2;
+            if (flags & 0x80) dumbfile_skip( f, 1 );
+            if (flags & 0x40) dumbfile_skip( f, 1 );
+            if (flags & 0x20) dumbfile_skip( f, 1 );
+            if (flags & 0x10) dumbfile_skip( f, 2 );
 		}
 	}
 
@@ -135,20 +140,21 @@
 	entry = pattern->entry;
 
 	row = 0;
-	pos = 0;
 
-	while ( ( row < 64 ) && ( pos < len ) )
+    if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1;
+
+    while ( ( row < 64 ) && ( dumbfile_pos( f ) < end ) )
 	{
-		if ( ! data[ pos ] )
+        p = dumbfile_getc( f );
+        if ( ! p )
 		{
 			IT_SET_END_ROW( entry );
 			++ entry;
 			++ row;
-			++ pos;
 			continue;
 		}
 
-		flags = data[ pos++ ];
+        flags = p;
 		entry->channel = flags & 0x0F;
 		entry->mask = 0;
 
@@ -156,35 +162,35 @@
 		{
 			if ( flags & 0x80 )
 			{
-				if ( data[ pos ] )
+                q = dumbfile_getc( f );
+                if ( q )
 				{
 					entry->mask |= IT_ENTRY_NOTE;
-					entry->note = data[ pos ] - 1;
+                    entry->note = q - 1;
 				}
-				++ pos;
 			}
 
 			if ( flags & 0x40 )
 			{
-				if ( data[ pos ] )
+                q = dumbfile_getc( f );
+                if ( q )
 				{
 					entry->mask |= IT_ENTRY_INSTRUMENT;
-					entry->instrument = data[ pos ];
+                    entry->instrument = q;
 				}
-				++ pos;
 			}
 
 			if ( flags & 0x20 )
 			{
 				entry->mask |= IT_ENTRY_VOLPAN;
-				entry->volpan = data[ pos ];
-				++ pos;
+                entry->volpan = dumbfile_getc( f );
 			}
 
 			if ( flags & 0x10 )
 			{
-				_dumb_it_xm_convert_effect( data[ pos ], data[ pos + 1 ], entry, 0 );
-				pos += 2;
+                q = dumbfile_getc( f );
+                r = dumbfile_getc( f );
+                _dumb_it_xm_convert_effect( q, r, entry, 0 );
 			}
 
 			if (entry->mask) entry++;
@@ -204,7 +210,7 @@
 	return 0;
 }
 
-static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( struct riff * stream )
+static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( DUMBFILE * f, struct riff * stream )
 {
 	DUMB_IT_SIGDATA *sigdata;
 
@@ -280,27 +286,29 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'S', 'O', 'N', 'G' ):
-			ptr = ( unsigned char * ) c->data;
-			memcpy( sigdata->name, c->data, 28 );
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            dumbfile_getnc( sigdata->name, 28, f );
 			sigdata->name[ 28 ] = 0;
 			sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
-			sigdata->n_orders = ptr[ 36 ] | ( ptr[ 37 ] << 8 );
+            dumbfile_skip( f, 36 - 28 );
+            sigdata->n_orders = dumbfile_igetw( f );
 			//sigdata->n_samples = ptr[ 38 ] | ( ptr[ 39 ] << 8 ); // whatever
 			//sigdata->n_patterns = ptr[ 40 ] | ( ptr[ 41 ] << 8 );
-			sigdata->n_pchannels = ptr[ 42 ] | ( ptr[ 43 ] << 8 );
-			sigdata->global_volume = ptr[ 44 ];
-			sigdata->mixing_volume = ptr[ 45 ];
-			sigdata->speed = ptr[ 46 ];
-			sigdata->tempo = ptr[ 47 ];
+            dumbfile_skip( f, 42 - 38 );
+            sigdata->n_pchannels = dumbfile_igetw( f );
+            sigdata->global_volume = dumbfile_getc( f );
+            sigdata->mixing_volume = dumbfile_getc( f );
+            sigdata->speed = dumbfile_getc( f );
+            sigdata->tempo = dumbfile_getc( f );
 
 			for ( o = 0; o < 16; ++o )
 			{
-				sigdata->channel_pan[ o ] = ptr[ 48 + o ] / 2;
+                sigdata->channel_pan[ o ] = dumbfile_getc( f ) / 2;
 			}
 
 			sigdata->order = malloc( 128 );
 			if ( ! sigdata->order ) goto error_usd;
-			memcpy( sigdata->order, ptr + 64, 128 );
+            dumbfile_getnc( sigdata->order, 128, f );
 
 			break;
 		}
@@ -328,12 +336,14 @@
 		switch ( c->type )
 		{
 		case DUMB_ID( 'P', 'A', 'T', 'T' ):
-			if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, ( unsigned char * ) c->data, c->size ) ) goto error_usd;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            if ( it_riff_dsmf_process_pattern( sigdata->pattern + sigdata->n_patterns, f, c->size ) ) goto error_usd;
 			++ sigdata->n_patterns;
 			break;
 
 		case DUMB_ID( 'I', 'N', 'S', 'T' ):
-			if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, ( unsigned char * ) c->data, c->size ) ) goto error_usd;
+            if ( dumbfile_seek( f, c->offset, DFS_SEEK_SET ) ) goto error_usd;
+            if ( it_riff_dsmf_process_sample( sigdata->sample + sigdata->n_samples, f, c->size ) ) goto error_usd;
 			++ sigdata->n_samples;
 			break;
 		}
@@ -352,13 +362,13 @@
 	return NULL;
 }
 
-DUH *dumb_read_riff_dsmf( struct riff * stream )
+DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream )
 {
 	sigdata_t *sigdata;
 
 	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
 
-	sigdata = it_riff_dsmf_load_sigdata( stream );
+    sigdata = it_riff_dsmf_load_sigdata( f, stream );
 
 	if (!sigdata)
 		return NULL;
--- a/dumb/src/it/readmod.c
+++ b/dumb/src/it/readmod.c
@@ -270,194 +270,8 @@
 
 
 
-typedef struct BUFFERED_MOD BUFFERED_MOD;
-
-struct BUFFERED_MOD
-{
-	unsigned char *buffered;
-	long ptr, len;
-	DUMBFILE *remaining;
-};
-
-
-
-static int buffer_mod_skip(void *f, long n)
-{
-	BUFFERED_MOD *bm = f;
-	if (bm->buffered) {
-		bm->ptr += n;
-		if (bm->ptr >= bm->len) {
-			free(bm->buffered);
-			bm->buffered = NULL;
-			return dumbfile_skip(bm->remaining, bm->ptr - bm->len);
-		}
-		return 0;
-	}
-	return dumbfile_skip(bm->remaining, n);
-}
-
-
-
-static int buffer_mod_getc(void *f)
-{
-	BUFFERED_MOD *bm = f;
-	if (bm->buffered) {
-		int rv = bm->buffered[bm->ptr++];
-		if (bm->ptr >= bm->len) {
-			free(bm->buffered);
-			bm->buffered = NULL;
-		}
-		return rv;
-	}
-	return dumbfile_getc(bm->remaining);
-}
-
-
-
-static long buffer_mod_getnc(char *ptr, long n, void *f)
-{
-	BUFFERED_MOD *bm = f;
-	if (bm->buffered) {
-		int left = bm->len - bm->ptr;
-		if (n >= left) {
-			memcpy(ptr, bm->buffered + bm->ptr, left);
-			free(bm->buffered);
-			bm->buffered = NULL;
-			if (n - left) {
-				int rv = dumbfile_getnc(ptr + left, n - left, bm->remaining);
-				return left + MAX(rv, 0);
-			} else {
-				return left;
-			}
-		}
-		memcpy(ptr, bm->buffered + bm->ptr, n);
-		bm->ptr += n;
-		return n;
-	}
-	return dumbfile_getnc(ptr, n, bm->remaining);
-}
-
-
-
-static void buffer_mod_close(void *f)
-{
-	BUFFERED_MOD *bm = f;
-	if (bm->buffered) free(bm->buffered);
-	/* Do NOT close bm->remaining */
-	free(f);
-}
-
-
-
-DUMBFILE_SYSTEM buffer_mod_dfs = {
-	NULL,
-	&buffer_mod_skip,
-	&buffer_mod_getc,
-	&buffer_mod_getnc,
-	&buffer_mod_close
-};
-
-
-
 #define MOD_FFT_OFFSET (20 + 31*(22+2+1+1+2+2) + 1 + 1 + 128)
 
-static DUMBFILE *dumbfile_buffer_mod(DUMBFILE *f, unsigned long *fft)
-{
-	BUFFERED_MOD *bm = malloc(sizeof(*bm));
-	if (!bm) return NULL;
-
-	bm->buffered = malloc(MOD_FFT_OFFSET + 4);
-	if (!bm->buffered) {
-		free(bm);
-		return NULL;
-	}
-
-	bm->len = dumbfile_getnc(bm->buffered, MOD_FFT_OFFSET + 4, f);
-
-	if (bm->len > 0) {
-		if (bm->len >= MOD_FFT_OFFSET + 4)
-			*fft = (unsigned long)bm->buffered[MOD_FFT_OFFSET  ] << 24
-			     | (unsigned long)bm->buffered[MOD_FFT_OFFSET+1] << 16
-			     | (unsigned long)bm->buffered[MOD_FFT_OFFSET+2] << 8
-			     | (unsigned long)bm->buffered[MOD_FFT_OFFSET+3];
-		else
-			*fft = 0;
-		bm->ptr = 0;
-	} else {
-		free(bm->buffered);
-		bm->buffered = NULL;
-	}
-
-	bm->remaining = f;
-
-	return dumbfile_open_ex(bm, &buffer_mod_dfs);
-}
-
-static DUMBFILE *dumbfile_buffer_mod_2(DUMBFILE *f, int n_samples, IT_SAMPLE * sample, long *total_sample_size, long *remain)
-{
-	long read;
-	int sample_number;
-	BUFFERED_MOD *bm = malloc(sizeof(*bm));
-	unsigned char *ptr;
-	if (!bm) return NULL;
-
-	bm->buffered = malloc(32768);
-	if (!bm->buffered) {
-		free(bm);
-		return NULL;
-	}
-
-	bm->len = 0;
-	*remain = 0;
-
-	read = dumbfile_getnc(bm->buffered, 32768, f);
-
-	if (read >= 0) {
-		bm->len += read;
-		*remain += read;
-
-		while (read >= 32768) {
-			bm->buffered = realloc(bm->buffered, *remain + 32768);
-			if (!bm->buffered) {
-				free(bm);
-				return 0;
-			}
-			read = dumbfile_getnc(bm->buffered + *remain, 32768, f);
-			if (read >= 0) {
-				bm->len += read;
-				*remain += read;
-			}
-		}
-	}
-
-	if (*remain) {
-		bm->ptr = 0;
-		ptr = bm->buffered + *remain;
-		sample_number = n_samples - 1;
-		*total_sample_size = 0;
-		while (ptr > bm->buffered && sample_number >= 0) {
-			if (sample[sample_number].flags & IT_SAMPLE_EXISTS) {
-				ptr -= (sample[sample_number].length + 1) / 2 + 5 + 16;
-				if (ptr >= bm->buffered && !memcmp(ptr, "ADPCM", 5)) { /* BAH */
-					*total_sample_size += (sample[sample_number].length + 1) / 2 + 5 + 16;
-				} else {
-					*total_sample_size += sample[sample_number].length;
-					ptr -= sample[sample_number].length - ((sample[sample_number].length + 1) / 2 + 5 + 16);
-				}
-			}
-			sample_number--;
-		}
-	} else {
-		free(bm->buffered);
-		bm->buffered = NULL;
-	}
-
-	bm->remaining = f;
-
-	return dumbfile_open_ex(bm, &buffer_mod_dfs);
-}
-
-
 static DUMB_IT_SIGDATA *it_mod_load_sigdata(DUMBFILE *f, int restrict)
 {
 	DUMB_IT_SIGDATA *sigdata;
@@ -464,15 +278,19 @@
 	int n_channels;
 	int i;
 	unsigned long fft;
-	DUMBFILE *rem = NULL;
 
-	f = dumbfile_buffer_mod(f, &fft);
-	if (!f)
-		return NULL;
+    if ( dumbfile_seek(f, MOD_FFT_OFFSET, DFS_SEEK_SET) )
+        return NULL;
 
+    fft = dumbfile_mgetl(f);
+    if (dumbfile_error(f))
+        return NULL;
+
+    if ( dumbfile_seek(f, 0, DFS_SEEK_SET) )
+        return NULL;
+
 	sigdata = malloc(sizeof(*sigdata));
 	if (!sigdata) {
-		dumbfile_close(f);
 		return NULL;
 	}
 
@@ -483,8 +301,7 @@
 	*/
 	if (dumbfile_getnc(sigdata->name, 20, f) < 20) {
 		free(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}
 	sigdata->name[20] = 0;
 
@@ -570,8 +387,7 @@
 	if ( ( restrict & 1 ) && sigdata->n_samples == 15 )
 	{
 		free(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}
 
 	sigdata->n_pchannels = n_channels ? n_channels : 8; /* special case for 0, see above */
@@ -579,8 +395,7 @@
 	sigdata->sample = malloc(sigdata->n_samples * sizeof(*sigdata->sample));
 	if (!sigdata->sample) {
 		free(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}
 
 	sigdata->song_message = NULL;
@@ -598,8 +413,7 @@
 	for (i = 0; i < sigdata->n_samples; i++) {
 		if (it_mod_read_sample_header(&sigdata->sample[i], f)) {
 			_dumb_it_unload_sigdata(sigdata);
-			dumbfile_close(f);
-			return NULL;
+            return NULL;
 		}
 	}
 
@@ -609,8 +423,7 @@
 
 /*	if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
 		_dumb_it_unload_sigdata(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}*/
 
 	//if (sigdata->restart_position >= sigdata->n_orders)
@@ -619,13 +432,11 @@
 	sigdata->order = malloc(128); /* We may need to scan the extra ones! */
 	if (!sigdata->order) {
 		_dumb_it_unload_sigdata(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}
 	if (dumbfile_getnc(sigdata->order, 128, f) < 128) {
 		_dumb_it_unload_sigdata(sigdata);
-		dumbfile_close(f);
-		return NULL;
+        return NULL;
 	}
 
 	if (sigdata->n_orders <= 0 || sigdata->n_orders > 128) { // is this right?
@@ -650,15 +461,41 @@
 
     if ( ( restrict & 2 ) )
 	{
-		long total_sample_size;
-		long remain;
-		rem = f;
-		f = dumbfile_buffer_mod_2(rem, sigdata->n_samples, sigdata->sample, &total_sample_size, &remain);
-		if (!f) {
-			_dumb_it_unload_sigdata(sigdata);
-			dumbfile_close(rem);
-			return NULL;
-		}
+        unsigned char buffer[5];
+        long sample_number;
+        long total_sample_size;
+        long offset = dumbfile_pos(f);
+        long remain = dumbfile_get_size(f) - offset;
+        if ( dumbfile_seek(f, 0, SEEK_END) ) {
+            _dumb_it_unload_sigdata(sigdata);
+            return NULL;
+        }
+        sample_number = sigdata->n_samples - 1;
+        total_sample_size = 0;
+        while (dumbfile_pos(f) > offset && sample_number >= 0) {
+            if (sigdata->sample[sample_number].flags & IT_SAMPLE_EXISTS) {
+                if ( dumbfile_seek(f, -((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16), DFS_SEEK_CUR) ||
+                     dumbfile_getnc(buffer, 5, f) < 5 ) {
+                    _dumb_it_unload_sigdata(sigdata);
+                    return NULL;
+                }
+                if ( !memcmp( buffer, "ADPCM", 5 ) ) { /* BAH */
+                    total_sample_size += (sigdata->sample[sample_number].length + 1) / 2 + 5 + 16;
+                    if ( dumbfile_seek(f, -5, DFS_SEEK_CUR) ) {
+                        _dumb_it_unload_sigdata(sigdata);
+                        return NULL;
+                    }
+                } else {
+                    total_sample_size += sigdata->sample[sample_number].length;
+                    if ( dumbfile_seek(f, -(sigdata->sample[sample_number].length - ((sigdata->sample[sample_number].length + 1) / 2 + 5 + 16) + 5), DFS_SEEK_CUR) ) {
+                        _dumb_it_unload_sigdata(sigdata);
+                        return NULL;
+                    }
+                }
+            }
+            --sample_number;
+        }
+
 		if (remain > total_sample_size) {
 			sigdata->n_patterns = ( remain - total_sample_size + 4 ) / ( 256 * sigdata->n_pchannels );
 			if (fft == DUMB_ID('M',0,0,0) || fft == DUMB_ID('8',0,0,0)) {
@@ -665,8 +502,6 @@
 				remain -= sigdata->n_patterns * 256 * sigdata->n_pchannels;
 				if (dumbfile_skip(f, remain - total_sample_size)) {
 					_dumb_it_unload_sigdata(sigdata);
-					dumbfile_close(f);
-					dumbfile_close(rem);
 					return NULL;
 				}
 			}
@@ -684,8 +519,6 @@
 
 	if ( sigdata->n_patterns <= 0 ) {
 		_dumb_it_unload_sigdata(sigdata);
-		dumbfile_close(f);
-		if (rem) dumbfile_close(rem);
 		return NULL;
 	}
 
@@ -698,8 +531,6 @@
 	sigdata->pattern = malloc(sigdata->n_patterns * sizeof(*sigdata->pattern));
 	if (!sigdata->pattern) {
 		_dumb_it_unload_sigdata(sigdata);
-		dumbfile_close(f);
-		if (rem) dumbfile_close(rem);
 		return NULL;
 	}
 	for (i = 0; i < sigdata->n_patterns; i++)
@@ -710,8 +541,6 @@
 		unsigned char *buffer = malloc(256 * sigdata->n_pchannels); /* 64 rows * 4 bytes */
 		if (!buffer) {
 			_dumb_it_unload_sigdata(sigdata);
-			dumbfile_close(f);
-			if (rem) dumbfile_close(rem);
 			return NULL;
 		}
 		for (i = 0; i < sigdata->n_patterns; i++) {
@@ -718,8 +547,6 @@
 			if (it_mod_read_pattern(&sigdata->pattern[i], f, n_channels, buffer) != 0) {
 				free(buffer);
 				_dumb_it_unload_sigdata(sigdata);
-				dumbfile_close(f);
-				if (rem) dumbfile_close(rem);
 				return NULL;
 			}
 		}
@@ -730,8 +557,6 @@
 	for (i = 0; i < sigdata->n_samples; i++) {
 		if (it_mod_read_sample_data(&sigdata->sample[i], f, fft)) {
 			_dumb_it_unload_sigdata(sigdata);
-			dumbfile_close(f);
-			if (rem) dumbfile_close(rem);
 			return NULL;
 		}
 	}
@@ -753,10 +578,6 @@
 			}
 		}
 	}*/
-
-	dumbfile_close(f); /* Destroy the BUFFERED_MOD DUMBFILE we were using. */
-	if (rem) dumbfile_close(rem); /* And the BUFFERED_MOD DUMBFILE used to pre-read the signature. */
-	/* The DUMBFILE originally passed to our function is intact. */
 
 	/* Now let's initialise the remaining variables, and we're done! */
 	sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX | IT_STEREO;
--- a/dumb/src/it/readriff.c
+++ b/dumb/src/it/readriff.c
@@ -22,9 +22,9 @@
 #include "internal/riff.h"
 
 
-DUH *dumb_read_riff_amff( struct riff * stream );
-DUH *dumb_read_riff_am( struct riff * stream );
-DUH *dumb_read_riff_dsmf( struct riff * stream );
+DUH *dumb_read_riff_amff( DUMBFILE * f, struct riff * stream );
+DUH *dumb_read_riff_am( DUMBFILE * f, struct riff * stream );
+DUH *dumb_read_riff_dsmf( DUMBFILE * f, struct riff * stream );
 
 /* dumb_read_riff_quick(): reads a RIFF file into a DUH struct, returning a
  * pointer to the DUH struct. When you have finished with it, you must pass
@@ -34,37 +34,21 @@
 {
 	DUH * duh;
 	struct riff * stream;
+    long size;
 
-	{
-		unsigned char * buffer = 0;
-		unsigned size = 0;
-		unsigned read;
-		do
-		{
-			buffer = realloc( buffer, 32768 + size );
-			if ( ! buffer ) return 0;
-			read = dumbfile_getnc( buffer + size, 32768, f );
-			if ( read < 0 )
-			{
-				free( buffer );
-				return 0;
-			}
-			size += read;
-		}
-		while ( read == 32768 );
-		stream = riff_parse( buffer, size, 1 );
-		if ( ! stream ) stream = riff_parse( buffer, size, 0 );
-		free( buffer );
-	}
+    size = dumbfile_get_size(f);
 
+    stream = riff_parse( f, 0, size, 1 );
+    if ( ! stream ) stream = riff_parse( f, 0, size, 0 );
+
 	if ( ! stream ) return 0;
 
 	if ( stream->type == DUMB_ID( 'A', 'M', ' ', ' ' ) )
-		duh = dumb_read_riff_am( stream );
+        duh = dumb_read_riff_am( f, stream );
 	else if ( stream->type == DUMB_ID( 'A', 'M', 'F', 'F' ) )
-		duh = dumb_read_riff_amff( stream );
+        duh = dumb_read_riff_amff( f, stream );
 	else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) )
-		duh = dumb_read_riff_dsmf( stream );
+        duh = dumb_read_riff_dsmf( f, stream );
 	else duh = 0;
 
 	riff_free( stream );
--- a/dumb/src/it/reads3m.c
+++ b/dumb/src/it/reads3m.c
@@ -24,26 +24,6 @@
 #include "dumb.h"
 #include "internal/it.h"
 
-//#define S3M_BROKEN_OVERLAPPED_SAMPLES
-
-/** WARNING: this is duplicated in itread.c */
-static int it_seek(DUMBFILE *f, long offset)
-{
-	long pos = dumbfile_pos(f);
-
-	if (pos > offset) {
-		return -1;
-	}
-
-	if (pos < offset)
-		if (dumbfile_skip(f, offset - pos))
-			return -1;
-
-	return 0;
-}
-
-
-
 static int it_s3m_read_sample_header(IT_SAMPLE *sample, long *offset, unsigned char *pack, int cwtv, DUMBFILE *f)
 {
 	unsigned char type;
@@ -214,7 +194,7 @@
 
 
 
-static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer, int maxlen)
+static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
 {
 	int length;
 	int buflen = 0;
@@ -246,18 +226,13 @@
 	 * against buffer overflow, this method should work with all sensibly
 	 * written S3M files. If you find one for which it does not work, please
 	 * let me know at entheh@users.sf.net so I can look at it.
+     *
+     * "for a good reason" ? What's this nonsense? -kode54
+     *
 	 */
 
-	/* Discard the length. */
-	/* read at most length bytes, in case of retarded crap */
 	length = dumbfile_igetw(f);
 	
-	if (maxlen)
-	{
-		maxlen -= 2;
-		if (length > maxlen) length = maxlen;
-	}
-
 	if (dumbfile_error(f) || !length)
 		return -1;
 
@@ -673,45 +648,11 @@
 		return NULL;
 	}
 
-	/* Voila, I must deal with a very dumb S3M myself. This file refers to the same file offset twice
-	 * for two different patterns. Solution: Eliminate it.
-	 */
-
 	for (n = 0; n < n_components; n++) {
-		if (component[n].type == S3M_COMPONENT_PATTERN) {
-			int m;
-			for (m = n + 1; m < n_components; m++) {
-				if (component[m].type == S3M_COMPONENT_PATTERN) {
-					if (component[n].offset == component[m].offset) {
-						int o, pattern;
-						pattern = component[m].n;
-						n_components--;
-						for (o = m; o < n_components; o++) {
-							component[o] = component[o + 1];
-						}
-						for (o = 0; o < sigdata->n_orders; o++) {
-							if (sigdata->order[o] == pattern) {
-								sigdata->order[o] = component[n].n;
-							}
-						}
-						sigdata->pattern[pattern].n_rows = 64;
-						sigdata->pattern[pattern].n_entries = 0;
-						m--;
-					} else
-						break;
-				}
-			}
-		}
-	}
-
-	for (n = 0; n < n_components; n++) {
 		long offset;
 		int m;
-#ifdef S3M_BROKEN_OVERLAPPED_SAMPLES
-		int last;
-#endif
 
-		if (it_seek(f, component[n].offset)) {
+        if (dumbfile_seek(f, component[n].offset, DFS_SEEK_SET)) {
 			free(buffer);
 			free(component);
 			_dumb_it_unload_sigdata(sigdata);
@@ -721,7 +662,7 @@
 		switch (component[n].type) {
 
 			case S3M_COMPONENT_PATTERN:
-				if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer, (n + 1 < n_components) ? (component[n+1].offset - component[n].offset) : 0)) {
+                if (it_s3m_read_pattern(&sigdata->pattern[component[n].n], f, buffer)) {
 					free(buffer);
 					free(component);
 					_dumb_it_unload_sigdata(sigdata);
@@ -759,41 +700,9 @@
 
 		m = component[n].sampfirst;
 
-#ifdef S3M_BROKEN_OVERLAPPED_SAMPLES
-		last = -1;
-#endif
-
 		while (m >= 0) {
 			// XXX
-#ifdef S3M_BROKEN_OVERLAPPED_SAMPLES
-			if ( last >= 0 ) {
-				if ( dumbfile_pos( f ) > component[m].offset ) {
-					IT_SAMPLE * s1 = &sigdata->sample[component[last].n];
-					IT_SAMPLE * s2 = &sigdata->sample[component[m].n];
-					if ( ( s1->flags | s2->flags ) & ( IT_SAMPLE_16BIT | IT_SAMPLE_STEREO ) ) {
-						free(buffer);
-						free(component);
-						_dumb_it_unload_sigdata(sigdata);
-						return NULL;
-					}
-					if ( component[m].offset >= component[last].offset &&
-						component[m].offset + s2->length <= component[last].offset + s1->length ) {
-						s2->left = malloc( s2->length );
-						if ( ! s2->left ) {
-							free(buffer);
-							free(component);
-							_dumb_it_unload_sigdata(sigdata);
-							return NULL;
-						}
-						memcpy( s2->left, ( const char * ) s1->left + component[m].offset - component[last].offset, s2->length );
-						last = -1;
-					}
-				}
-			} else last = 0;
-
-			if ( last >= 0 ) {
-#endif
-				if (it_seek(f, component[m].offset)) {
+                if (dumbfile_seek(f, component[m].offset, DFS_SEEK_SET)) {
 					free(buffer);
 					free(component);
 					_dumb_it_unload_sigdata(sigdata);
@@ -806,11 +715,6 @@
 					_dumb_it_unload_sigdata(sigdata);
 					return NULL;
 				}
-
-#ifdef S3M_BROKEN_OVERLAPPED_SAMPLES
-				last = m;
-			}
-#endif
 
 			m = component[m].sampnext;
 		}
--- a/dumb/src/it/readstm.c
+++ b/dumb/src/it/readstm.c
@@ -31,22 +31,6 @@
 #define strnicmp strncasecmp
 #endif
 
-/** WARNING: this is duplicated in itread.c */
-static int it_seek(DUMBFILE *f, long offset)
-{
-	long pos = dumbfile_pos(f);
-
-	if (pos > offset) {
-		return -1;
-	}
-
-	if (pos < offset)
-		if (dumbfile_skip(f, offset - pos))
-			return -1;
-
-	return 0;
-}
-
 static int it_stm_read_sample_header( IT_SAMPLE *sample, DUMBFILE *f, unsigned short *offset )
 {
 	dumbfile_getnc( sample->filename, 12, f );
--- a/dumb/src/it/readxm.c
+++ b/dumb/src/it/readxm.c
@@ -453,13 +453,29 @@
 }
 
 
+/* These two can be stubs since this implementation doesn't use seeking */
+static int limit_xm_seek(void *f, long n)
+{
+    return 1;
+}
 
+
+
+static long limit_xm_get_size(void *f)
+{
+    return 0;
+}
+
+
+
 DUMBFILE_SYSTEM limit_xm_dfs = {
 	NULL,
 	&limit_xm_skip,
 	&limit_xm_getc,
 	&limit_xm_getnc,
-	&limit_xm_close
+    &limit_xm_close,
+    &limit_xm_seek,
+    &limit_xm_get_size
 };
 
 static DUMBFILE *dumbfile_limit_xm(DUMBFILE *f)