Beispiel #1
0
static int it_asy_read_pattern( IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer )
{
	int pos;
	int channel;
	int row;
	IT_ENTRY *entry;

	pattern->n_rows = 64;

	if ( dumbfile_getnc( buffer, 64 * 8 * 4, f ) != 64 * 8 * 4 )
		return -1;

	/* compute number of entries */
	pattern->n_entries = 64; /* Account for the row end markers */
	pos = 0;
	for ( row = 0; row < 64; ++row ) {
		for ( channel = 0; channel < 8; ++channel ) {
			if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] )
				++pattern->n_entries;
			pos += 4;
		}
	}

	pattern->entry = malloc( pattern->n_entries * sizeof( *pattern->entry ) );
	if ( !pattern->entry )
		return -1;

	entry = pattern->entry;
	pos = 0;
	for ( row = 0; row < 64; ++row ) {
		for ( channel = 0; channel < 8; ++channel ) {
			if ( buffer[ pos + 0 ] | buffer[ pos + 1 ] | buffer[ pos + 2 ] | buffer[ pos + 3 ] ) {
				entry->channel = channel;
				entry->mask = 0;

				if ( buffer[ pos + 0 ] && buffer[ pos + 0 ] < 96 ) {
					entry->note = buffer[ pos + 0 ];
					entry->mask |= IT_ENTRY_NOTE;
				}

				if ( buffer[ pos + 1 ] && buffer[ pos + 1 ] <= 64 ) {
					entry->instrument = buffer[ pos + 1 ];
					entry->mask |= IT_ENTRY_INSTRUMENT;
				}

				_dumb_it_xm_convert_effect( buffer[ pos + 2 ], buffer[ pos + 3 ], entry, 1 );

				if ( entry->mask ) ++entry;
			}
			pos += 4;
		}
		IT_SET_END_ROW( entry );
		++entry;
	}

	pattern->n_entries = (int)(entry - pattern->entry);

	return 0;
}
Beispiel #2
0
static int it_okt_read_pattern(IT_PATTERN *pattern, const unsigned char *data, int length, int n_channels)
{
	int pos;
	int channel;
	int row;
	int n_rows;
	IT_ENTRY *entry;

	if (length < 2) return -1;

	n_rows = (data[0] << 8) | data[1];
	if (!n_rows) n_rows = 64;

	if (length < 2 + (n_rows * n_channels * 4)) return -1;

	pattern->n_rows = n_rows;

	/* compute number of entries */
	pattern->n_entries = n_rows; /* Account for the row end markers */
	pos = 2;
	for (row = 0; row < pattern->n_rows; row++) {
		for (channel = 0; channel < n_channels; channel++) {
			if (data[pos+0] | data[pos+2])
				pattern->n_entries++;
			pos += 4;
		}
	}

	pattern->entry = (IT_ENTRY *) malloc(pattern->n_entries * sizeof(*pattern->entry));
	if (!pattern->entry)
		return -1;

	entry = pattern->entry;
	pos = 2;
	for (row = 0; row < n_rows; row++) {
		for (channel = 0; channel < n_channels; channel++) {
			if (data[pos+0] | data[pos+2]) {
				entry->channel = channel;
				entry->mask = 0;

				if (data[pos+0] > 0 && data[pos+0] <= 36) {
					entry->mask |= IT_ENTRY_NOTE | IT_ENTRY_INSTRUMENT;

					entry->note = data[pos+0] + 35;
					entry->instrument = data[pos+1] + 1;
				}

				entry->effect = 0;
				entry->effectvalue = data[pos+3];

				switch (data[pos+2]) {
				case  2: if (data[pos+3]) entry->effect = IT_PORTAMENTO_DOWN; break; // XXX code calls this rs_portu, but it's adding to the period, which decreases the pitch
				case 13: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN; break;
				case 21: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_DOWN_ROW; break;

				case  1: if (data[pos+3]) entry->effect = IT_PORTAMENTO_UP; break;   // XXX same deal here, increasing the pitch
				case 17: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP; break;
				case 30: if (data[pos+3]) entry->effect = IT_OKT_NOTE_SLIDE_UP_ROW; break;

				case 10: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_3; break;
				case 11: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_4; break;
				case 12: if (data[pos+3]) entry->effect = IT_OKT_ARPEGGIO_5; break;

				case 15: entry->effect = IT_S; entry->effectvalue = EFFECT_VALUE(IT_S_SET_FILTER, data[pos+3] & 0x0F); break;

				case 25: entry->effect = IT_JUMP_TO_ORDER; break;

				case 27: entry->note = IT_NOTE_OFF; entry->mask |= IT_ENTRY_NOTE; break;

				case 28: entry->effect = IT_SET_SPEED; break;

				case 31:
					if ( data[pos+3] <= 0x40 ) entry->effect = IT_SET_CHANNEL_VOLUME;
					else if ( data[pos+3] <= 0x50 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x40; }
					else if ( data[pos+3] <= 0x60 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP;   entry->effectvalue = data[pos+3] - 0x50; }
					else if ( data[pos+3] <= 0x70 ) { entry->effect = IT_OKT_VOLUME_SLIDE_DOWN; entry->effectvalue = data[pos+3] - 0x50; }
					else if ( data[pos+3] <= 0x80 ) { entry->effect = IT_OKT_VOLUME_SLIDE_UP;   entry->effectvalue = data[pos+3] - 0x60; }
					break;
				}

				if ( entry->effect ) entry->mask |= IT_ENTRY_EFFECT;

				entry++;
			}
			pos += 4;
		}
		IT_SET_END_ROW(entry);
		entry++;
	}

	return 0;
}
Beispiel #3
0
static int it_xm_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, int n_channels, unsigned char *buffer, int version)
{
	int size;
	int pos;
	int channel;
	int row;
	int effect, effectvalue;
	IT_ENTRY *entry;

	/* pattern header size */
	if (dumbfile_igetl(f) != ( version == 0x0102 ? 0x08 : 0x09 ) ) {
		TRACE("XM error: unexpected pattern header size\n");
		return -1;
	}

	/* pattern data packing type */
	if (dumbfile_getc(f) != 0) {
		TRACE("XM error: unexpected pattern packing type\n");
		return -1;
	}

	if ( version == 0x0102 )
		pattern->n_rows = dumbfile_getc(f) + 1;
	else
		pattern->n_rows = dumbfile_igetw(f);  /* 1..256 */
	size = dumbfile_igetw(f);
	pattern->n_entries = 0;

	if (dumbfile_error(f))
		return -1;

	if (size == 0)
		return 0;

	if (size > 1280 * n_channels) {
		TRACE("XM error: pattern data size > %d bytes\n", 1280 * n_channels);
		return -1;
	}

    if (dumbfile_getnc((char *)buffer, size, f) < size)
		return -1;

	/* compute number of entries */
	pattern->n_entries = 0;
	pos = channel = row = 0;
	while (pos < size) {
		if (!(buffer[pos] & XM_ENTRY_PACKED) || (buffer[pos] & 31))
			pattern->n_entries++;

		channel++;
		if (channel >= n_channels) {
			channel = 0;
			row++;
			pattern->n_entries++;
		}

		if (buffer[pos] & XM_ENTRY_PACKED) {
			static const char offset[] = { 0, 1, 1, 2, 1, 2, 2, 3,   1, 2, 2, 3, 2, 3, 3, 4,
			                               1, 2, 2, 3, 2, 3, 3, 4,   2, 3, 3, 4, 3, 4, 4, 5 };
			pos += 1 + offset[buffer[pos] & 31];
		} else {
			pos += 5;
		}
	}

	if (row > pattern->n_rows) {
		TRACE("XM error: wrong number of rows in pattern data\n");
		return -1;
	}

	/* Whoops, looks like some modules may be short, a few channels, maybe even rows... */

	while (row < pattern->n_rows)
	{
		pattern->n_entries++;
		row++;
	}

	pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));
	if (!pattern->entry)
		return -1;

	/* read the entries */
	entry = pattern->entry;
	pos = channel = row = 0;
	while (pos < size) {
		unsigned char mask;

		if (buffer[pos] & XM_ENTRY_PACKED)
			mask = buffer[pos++] & 31;
		else
			mask = 31;

		if (mask) {
			ASSERT(entry < pattern->entry + pattern->n_entries);

			entry->channel = channel;
			entry->mask = 0;

			if (mask & XM_ENTRY_NOTE) {
				int note = buffer[pos++]; /* 1-96 <=> C0-B7 */
				entry->note = (note == XM_NOTE_OFF) ? (IT_NOTE_OFF) : (note-1);
				entry->mask |= IT_ENTRY_NOTE;
			}

			if (mask & XM_ENTRY_INSTRUMENT) {
				entry->instrument = buffer[pos++]; /* 1-128 */
				entry->mask |= IT_ENTRY_INSTRUMENT;
			}

			if (mask & XM_ENTRY_VOLUME)
				it_xm_convert_volume(buffer[pos++], entry);

			effect = effectvalue = 0;
			if (mask & XM_ENTRY_EFFECT)      effect = buffer[pos++];
			if (mask & XM_ENTRY_EFFECTVALUE) effectvalue = buffer[pos++];
			_dumb_it_xm_convert_effect(effect, effectvalue, entry, 0);

			entry++;
		}

		channel++;
		if (channel >= n_channels) {
			channel = 0;
			row++;
			IT_SET_END_ROW(entry);
			entry++;
		}
	}

	while (row < pattern->n_rows)
	{
		row++;
		IT_SET_END_ROW(entry);
		entry++;
	}

	return 0;
}
Beispiel #4
0
static int it_riff_dsmf_process_pattern( IT_PATTERN * pattern, DUMBFILE * f, int len )
{
    int length, row;
    unsigned flags;
    long start, end;
    int p, q, r;
    IT_ENTRY * entry;

    length = dumbfile_igetw( f );
    if ( length > len ) return -1;

    len = length - 2;

    pattern->n_rows = 64;
    pattern->n_entries = 64;

    row = 0;

    start = dumbfile_pos( f );
    end = start + len;

    while ( (row < 64) && !dumbfile_error( f ) && (dumbfile_pos( f ) < end) ) {
        p = dumbfile_getc( f );
        if ( ! p ) {
            ++ row;
            continue;
        }

        flags = p & 0xF0;

        if (flags) {
            ++ pattern->n_entries;
            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 );
        }
    }

    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;

    if ( dumbfile_seek( f, start, DFS_SEEK_SET ) ) return -1;

    while ( ( row < 64 ) && !dumbfile_error( f ) && ( dumbfile_pos( f ) < end ) )
    {
        p = dumbfile_getc( f );
        if ( ! p )
        {
            IT_SET_END_ROW( entry );
            ++ entry;
            ++ row;
            continue;
        }

        flags = p;
        entry->channel = flags & 0x0F;
        entry->mask = 0;

        if ( flags & 0xF0 )
        {
            if ( flags & 0x80 )
            {
                q = dumbfile_getc( f );
                if ( q )
                {
                    entry->mask |= IT_ENTRY_NOTE;
                    entry->note = q - 1;
                }
            }

            if ( flags & 0x40 )
            {
                q = dumbfile_getc( f );
                if ( q )
                {
                    entry->mask |= IT_ENTRY_INSTRUMENT;
                    entry->instrument = q;
                }
            }

            if ( flags & 0x20 )
            {
                entry->mask |= IT_ENTRY_VOLPAN;
                entry->volpan = dumbfile_getc( f );
            }

            if ( flags & 0x10 )
            {
                q = dumbfile_getc( f );
                r = dumbfile_getc( f );
                _dumb_it_xm_convert_effect( q, r, entry, 0 );
            }

            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;
}
Beispiel #5
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 = (int)(entry - pattern->entry);
	if ( ! pattern->n_entries ) return -1;

	return 0;
}
Beispiel #6
0
static int it_s3m_read_pattern(IT_PATTERN *pattern, DUMBFILE *f, unsigned char *buffer)
{
	int buflen = 0;
	int bufpos = 0;

	IT_ENTRY *entry;

	unsigned char channel;

	/* Haha, this is hilarious!
	 *
	 * Well, after some experimentation, it seems that different S3M writers
	 * define the format in different ways. The S3M docs say that the first
	 * two bytes hold the "length of [the] packed pattern", and the packed
	 * pattern data follow. Judging by the contents of ARMANI.S3M, packaged
	 * with ScreamTracker itself, the measure of length _includes_ the two
	 * bytes used to store the length; in other words, we should read
	 * (length - 2) more bytes. However, aryx.s3m, packaged with ModPlug
	 * Tracker, excludes these two bytes, so (length) more bytes must be
	 * read.
	 *
	 * Call me crazy, but I just find it insanely funny that the format was
	 * misunderstood in this way :D
	 *
	 * Now we can't just risk reading two extra bytes, because then we
	 * overshoot, and DUMBFILEs don't support backward seeking (for a good
	 * reason). Luckily, there is a way. We can read the data little by
	 * little, and stop when we have 64 rows in memory. Provided we protect
	 * 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 [email protected] so I can look at it.
	 */

	/* Discard the length. */
	dumbfile_skip(f, 2);

	if (dumbfile_error(f))
		return -1;

	pattern->n_rows = 0;
	pattern->n_entries = 0;

	/* Read in the pattern data, little by little, and work out how many
	 * entries we need room for. Sorry, but this is just so funny...
	 */
	for (;;) {
		unsigned char b = buffer[buflen++] = dumbfile_getc(f);

#if 1
		static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
		channel = b & 31;
		b >>= 5;
		pattern->n_entries++;
		if (b) {
			if (buflen + used[b] >= 65536) return -1;
			dumbfile_getnc(buffer + buflen, used[b], f);
			buflen += used[b];
		} else {
			/* End of row */
			if (++pattern->n_rows == 64) break;
			if (buflen >= 65536) return -1;
		}
#else
		if (b == 0) {
			/* End of row */
			pattern->n_entries++;
			if (++pattern->n_rows == 64) break;
			if (buflen >= 65536) return -1;
		} else {
			static const unsigned char used[8] = {0, 2, 1, 3, 2, 4, 3, 5};
			channel = b & 31;
			b >>= 5;
			if (b) {
				pattern->n_entries++;
				if (buflen + used[b] >= 65536) return -1;
				dumbfile_getnc(buffer + buflen, used[b], f);
				buflen += used[b];
			}
		}
#endif

		/* We have ensured that buflen < 65536 at this point, so it is safe
		 * to iterate and read at least one more byte without checking.
		 * However, now would be a good time to check for errors reading from
		 * the file.
		 */

		if (dumbfile_error(f))
			return -1;
	}

	pattern->entry = malloc(pattern->n_entries * sizeof(*pattern->entry));

	if (!pattern->entry)
		return -1;

	entry = pattern->entry;

	while (bufpos < buflen) {
		unsigned char b = buffer[bufpos++];

#if 1
		if (!(b & ~31))
#else
		if (b == 0)
#endif
		{
			/* End of row */
			IT_SET_END_ROW(entry);
			entry++;
			continue;
		}

		channel = b & 31;

		if (b & 224) {
			entry->mask = 0;
			entry->channel = channel;

			if (b & 32) {
				unsigned char n = buffer[bufpos++];
				if (n != 255) {
					if (n == 254)
						entry->note = IT_NOTE_CUT;
					else
						entry->note = (n >> 4) * 12 + (n & 15);
					entry->mask |= IT_ENTRY_NOTE;
				}

				entry->instrument = buffer[bufpos++];
				if (entry->instrument)
					entry->mask |= IT_ENTRY_INSTRUMENT;
			}

			if (b & 64) {
				entry->volpan = buffer[bufpos++];
				if (entry->volpan != 255)
					entry->mask |= IT_ENTRY_VOLPAN;
			}

			if (b & 128) {
				entry->effect = buffer[bufpos++];
				entry->effectvalue = buffer[bufpos++];
				if (entry->effect != 255) {
					entry->mask |= IT_ENTRY_EFFECT;
					if (entry->effect == IT_BREAK_TO_ROW)
						entry->effectvalue -= (entry->effectvalue >> 4) * 6;
				}