shithub: dumb

Download patch

ref: 95afd4ca875c3f3983de167afcc7deda682a8c8d
parent: dae50fa2a1a66a8658827483bdc8a7aae48e019b
author: Chris Moeller <kode54@gmail.com>
date: Mon Jan 11 03:59:11 EST 2010

{11/20/2005 7:14:42 PM~11/20/2005 7:14:44 PM}

git-tfs-id: [http://localhost:8080/tfs/DefaultCollection/]$/foobar2000/files/plugins.root;C50

--- a/dumb/src/it/readam.c
+++ b/dumb/src/it/readam.c
@@ -9,7 +9,7 @@
  *                                                      /  \
  *                                                     / .  \
  * readam.c - Code to read a RIFF AM module           / / \  \
- *             from an open file.                    | <  /   \_
+ *             from a parsed RIFF structure.         | <  /   \_
  *                                                   |  \/ /\   /
  * By Chris Moeller.                                  \_  /  > /
  *                                                      | \ / /
@@ -131,6 +131,8 @@
 		}
 	}
 
+	length_bytes = sample->length << ( ( flags & 0x04 ) >> 2 );
+
 	sample->left = malloc( length_bytes );
 	if ( ! sample->left )
 		return -1;
@@ -346,7 +348,7 @@
 			ptr = ( unsigned char * ) c->data;
 			memcpy( sigdata->name, c->data, 64 );
 			sigdata->name[ 64 ] = 0;
-			sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_WAS_AN_S3M;
+			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 ];
@@ -569,7 +571,7 @@
 			ptr = ( unsigned char * ) c->data;
 			memcpy( sigdata->name, c->data, 64 );
 			sigdata->name[ 64 ] = 0;
-			sigdata->flags = IT_STEREO | IT_OLD_EFFECTS | IT_WAS_AN_S3M;
+			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 ];
--- /dev/null
+++ b/dumb/src/it/readdsmf.c
@@ -1,0 +1,375 @@
+/*  _______         ____    __         ___    ___
+ * \    _  \       \    /  \  /       \   \  /   /       '   '  '
+ *  |  | \  \       |  |    ||         |   \/   |         .      .
+ *  |  |  |  |      |  |    ||         ||\  /|  |
+ *  |  |  |  |      |  |    ||         || \/ |  |         '  '  '
+ *  |  |  |  |      |  |    ||         ||    |  |         .      .
+ *  |  |_/  /        \  \__//          ||    |  |
+ * /_______/ynamic    \____/niversal  /__\  /____\usic   /|  .  . ibliotheque
+ *                                                      /  \
+ *                                                     / .  \
+ * readam.c - Code to read a RIFF DSMF module         / / \  \
+ *             from a parsed RIFF structure.         | <  /   \_
+ *                                                   |  \/ /\   /
+ * By Chris Moeller.                                  \_  /  > /
+ *                                                      | \ / /
+ *                                                      |  ' /
+ *                                                       \__/
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "dumb.h"
+#include "internal/it.h"
+#include "internal/riff.h"
+
+static int it_riff_dsmf_process_sample( IT_SAMPLE * sample, const unsigned char * data, int len )
+{
+	int flags;
+
+	memcpy( sample->filename, data, 13 );
+	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 );
+	sample->name[ 28 ] = 0;
+
+	/*if ( data[ 0x38 ] || data[ 0x39 ] || data[ 0x3A ] || data[ 0x3B ] )
+		return -1;*/
+
+	if ( ! sample->length ) {
+		sample->flags &= ~IT_SAMPLE_EXISTS;
+		return 0;
+	}
+
+	if ( flags & ~( 2 | 1 ) )
+		return -1;
+
+	if ( sample->length + 64 > len )
+		return -1;
+
+	sample->flags = IT_SAMPLE_EXISTS;
+
+	sample->default_pan = 0;
+	sample->global_volume = 64;
+	sample->vibrato_speed = 0;
+	sample->vibrato_depth = 0;
+	sample->vibrato_rate = 0;
+	sample->vibrato_waveform = IT_VIBRATO_SINE;
+	sample->max_resampling_quality = -1;
+
+	if ( flags & 1 )
+	{
+		if (((unsigned int)sample->loop_end <= (unsigned int)sample->length) &&
+			((unsigned int)sample->loop_start < (unsigned int)sample->loop_end))
+		{
+			sample->length = sample->loop_end;
+			sample->flags |= IT_SAMPLE_LOOP;
+			if ( flags & 0x10 ) sample->flags |= IT_SAMPLE_PINGPONG_LOOP;
+		}
+	}
+
+	sample->left = malloc( sample->length );
+	if ( ! sample->left )
+		return -1;
+
+	memcpy( sample->left, data + 64, sample->length );
+
+	if ( ! ( flags & 2 ) )
+	{
+		for ( flags = 0; flags < sample->length; ++flags )
+			( ( signed char * ) sample->left ) [ flags ] ^= 0x80;
+	}
+
+	return 0;
+}
+
+static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, const unsigned char * data, int len )
+{
+	int length, row, pos;
+	unsigned flags;
+	IT_ENTRY * entry;
+
+	length = data[ 0 ] | ( data[ 1 ] << 8 );
+	if ( length > len ) return -1;
+
+	data += 2;
+	len = length - 2;
+
+	pattern->n_rows = 64;
+	pattern->n_entries = 64;
+
+	row = 0;
+	pos = 0;
+
+	while ( (row < 64) && (pos < len) ) {
+		if ( ! data[ pos ] ) {
+			++ row;
+			++ pos;
+			continue;
+		}
+
+		flags = data[ pos++ ] & 0xF0;
+
+		if (flags) {
+			++ pattern->n_entries;
+			if (flags & 0x80) pos ++;
+			if (flags & 0x40) pos ++;
+			if (flags & 0x20) pos ++;
+			if (flags & 0x10) pos += 2;
+		}
+	}
+
+	if ( pattern->n_entries == 64 ) return 0;
+
+	pattern->entry = malloc( pattern->n_entries * sizeof( * pattern->entry ) );
+	if ( ! pattern->entry ) return -1;
+
+	entry = pattern->entry;
+
+	row = 0;
+	pos = 0;
+
+	while ( ( row < 64 ) && ( pos < len ) )
+	{
+		if ( ! data[ pos ] )
+		{
+			IT_SET_END_ROW( entry );
+			++ entry;
+			++ row;
+			++ pos;
+			continue;
+		}
+
+		flags = data[ pos++ ];
+		entry->channel = flags & 0x0F;
+		entry->mask = 0;
+
+		if ( flags & 0xF0 )
+		{
+			if ( flags & 0x80 )
+			{
+				if ( data[ pos ] )
+				{
+					entry->mask |= IT_ENTRY_NOTE;
+					entry->note = data[ pos ] - 1;
+				}
+				++ pos;
+			}
+
+			if ( flags & 0x40 )
+			{
+				if ( data[ pos ] )
+				{
+					entry->mask |= IT_ENTRY_INSTRUMENT;
+					entry->instrument = data[ pos ];
+				}
+				++ pos;
+			}
+
+			if ( flags & 0x20 )
+			{
+				entry->mask |= IT_ENTRY_VOLPAN;
+				entry->volpan = data[ pos ];
+				++ pos;
+			}
+
+			if ( flags & 0x10 )
+			{
+				_dumb_it_xm_convert_effect( data[ pos ], data[ pos + 1 ], entry, 0 );
+				pos += 2;
+			}
+
+			if (entry->mask) entry++;
+		}
+	}
+
+	while ( row < 64 )
+	{
+		IT_SET_END_ROW( entry );
+		++ entry;
+		++ row;
+	}
+
+	pattern->n_entries = entry - pattern->entry;
+	if ( ! pattern->n_entries ) return -1;
+
+	return 0;
+}
+
+static DUMB_IT_SIGDATA *it_riff_dsmf_load_sigdata( struct riff * stream )
+{
+	DUMB_IT_SIGDATA *sigdata;
+
+	int n, o, p, found;
+
+	unsigned char * ptr;
+
+	if ( ! stream ) goto error;
+
+	if ( stream->type != DUMB_ID( 'D', 'S', 'M', 'F' ) ) goto error;
+
+	sigdata = malloc(sizeof(*sigdata));
+	if ( ! sigdata ) goto error;
+
+	sigdata->n_patterns = 0;
+	sigdata->n_samples = 0;
+	sigdata->name[0] = 0;
+
+	found = 0;
+
+	for ( n = 0; n < stream->chunk_count; ++n )
+	{
+		struct riff_chunk * c = stream->chunks + n;
+		switch( c->type )
+		{
+		case DUMB_ID( 'S' ,'O' ,'N' ,'G' ):
+			/* initialization data */
+			if ( ( found ) || ( c->size < 192 ) ) goto error_sd;
+			found = 1;
+			break;
+
+		case DUMB_ID( 'P', 'A', 'T', 'T' ):
+			++ sigdata->n_patterns;
+			break;
+
+		case DUMB_ID( 'I', 'N', 'S', 'T' ):
+			++ sigdata->n_samples;
+			break;
+		}
+	}
+
+	if ( !found || !sigdata->n_samples || !sigdata->n_patterns ) goto error_sd;
+
+	if ( sigdata->n_samples > 255 || sigdata->n_patterns > 255 ) goto error_sd;
+
+	sigdata->song_message = NULL;
+	sigdata->order = NULL;
+	sigdata->instrument = NULL;
+	sigdata->sample = NULL;
+	sigdata->pattern = NULL;
+	sigdata->midi = NULL;
+	sigdata->checkpoint = NULL;
+
+	sigdata->mixing_volume = 48;
+	sigdata->pan_separation = 128;
+
+	sigdata->n_instruments = 0;
+	sigdata->n_orders = 0;
+
+	memset(sigdata->channel_volume, 64, DUMB_IT_N_CHANNELS);
+
+	for (n = 0; n < DUMB_IT_N_CHANNELS; n += 4) {
+		sigdata->channel_pan[n  ] = 16;
+		sigdata->channel_pan[n+1] = 48;
+		sigdata->channel_pan[n+2] = 48;
+		sigdata->channel_pan[n+3] = 16;
+	}
+
+	for ( n = 0; n < stream->chunk_count; ++n )
+	{
+		struct riff_chunk * c = stream->chunks + n;
+		switch ( c->type )
+		{
+		case DUMB_ID( 'S', 'O', 'N', 'G' ):
+			ptr = ( unsigned char * ) c->data;
+			memcpy( sigdata->name, c->data, 28 );
+			sigdata->name[ 28 ] = 0;
+			sigdata->flags = IT_WAS_AN_XM | IT_WAS_A_MOD | IT_STEREO | IT_OLD_EFFECTS | IT_COMPATIBLE_GXX;
+			sigdata->n_orders = ptr[ 36 ] | ( ptr[ 37 ] << 8 );
+			//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 ];
+
+			for ( o = 0; o < 16; ++o )
+			{
+				sigdata->channel_pan[ o ] = ptr[ 48 + o ] / 2;
+			}
+
+			sigdata->order = malloc( 128 );
+			if ( ! sigdata->order ) goto error_usd;
+			memcpy( sigdata->order, ptr + 64, 128 );
+
+			break;
+		}
+	}
+
+	sigdata->pattern = malloc( sigdata->n_patterns * sizeof( *sigdata->pattern ) );
+	if ( ! sigdata->pattern ) goto error_usd;
+	for ( n = 0; n < sigdata->n_patterns; ++n )
+		sigdata->pattern[ n ].entry = NULL;
+
+	sigdata->sample = malloc( sigdata->n_samples * sizeof( *sigdata->sample ) );
+	if ( ! sigdata->sample ) goto error_usd;
+	for ( n = 0; n < sigdata->n_samples; ++n )
+	{
+		IT_SAMPLE * sample = sigdata->sample + n;
+		sample->right = sample->left = NULL;
+	}
+
+	sigdata->n_samples = 0;
+	sigdata->n_patterns = 0;
+
+	for ( n = 0; n < stream->chunk_count; ++n )
+	{
+		struct riff_chunk * c = stream->chunks + n;
+		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;
+			++ 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;
+			++ sigdata->n_samples;
+			break;
+		}
+	}
+
+	_dumb_it_fix_invalid_orders( sigdata );
+
+	return sigdata;
+
+error_usd:
+	_dumb_it_unload_sigdata( sigdata );
+	goto error;
+error_sd:
+	free( sigdata );
+error:
+	return NULL;
+}
+
+DUH *dumb_read_riff_dsmf( struct riff * stream )
+{
+	sigdata_t *sigdata;
+	long length;
+
+	DUH_SIGTYPE_DESC *descptr = &_dumb_sigtype_it;
+
+	sigdata = it_riff_dsmf_load_sigdata( stream );
+
+	if (!sigdata)
+		return NULL;
+
+	length = 0;/*_dumb_it_build_checkpoints(sigdata, 0);*/
+
+	{
+		const char *tag[2][2];
+		tag[0][0] = "TITLE";
+		tag[0][1] = ((DUMB_IT_SIGDATA *)sigdata)->name;
+		tag[1][0] = "FORMAT";
+		tag[1][1] = "RIFF DSMF";
+		return make_duh( length, 2, ( const char * const (*) [ 2 ] ) tag, 1, & descptr, & sigdata );
+	}
+}
--- a/dumb/src/it/readmod.c
+++ b/dumb/src/it/readmod.c
@@ -224,6 +224,10 @@
 				}
 			}
 		}
+		else
+		{
+			i = dumbfile_getnc(sample->left, sample->length, f);
+		}
 		if (i < sample->length)
 		{
 			if (i <= 0)
--- a/dumb/src/it/readriff.c
+++ b/dumb/src/it/readriff.c
@@ -24,6 +24,7 @@
 
 DUH *dumb_read_riff_amff( struct riff * stream );
 DUH *dumb_read_riff_am( struct riff * stream );
+DUH *dumb_read_riff_dsmf( struct riff * stream );
 
 /* dumb_read_riff(): reads a RIFF file into a DUH struct, returning a pointer
  * to the DUH struct. When you have finished with it, you must pass the
@@ -62,8 +63,8 @@
 		duh = dumb_read_riff_am( stream );
 	else if ( stream->type == DUMB_ID( 'A', 'M', 'F', 'F' ) )
 		duh = dumb_read_riff_amff( stream );
-	/* else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) )
-		duh = dumb_read_riff_dsmf( stream ); */
+	else if ( stream->type == DUMB_ID( 'D', 'S', 'M', 'F' ) )
+		duh = dumb_read_riff_dsmf( stream );
 	else duh = 0;
 
 	riff_free( stream );
--- a/dumb/vc6/dumb/dumb.vcproj
+++ b/dumb/vc6/dumb/dumb.vcproj
@@ -202,7 +202,7 @@
 				AssemblerListingLocation="$(IntDir)\"
 				ObjectFile="$(IntDir)\"
 				ProgramDataBaseFileName="$(IntDir)\"
-				WarningLevel="3"
+				WarningLevel="4"
 				SuppressStartupBanner="true"
 				CompileAs="0"
 			/>
@@ -1484,6 +1484,10 @@
 				</File>
 				<File
 					RelativePath="..\..\src\it\readam.c"
+					>
+				</File>
+				<File
+					RelativePath="..\..\src\it\readdsmf.c"
 					>
 				</File>
 				<File