예제 #1
0
/* Effects marked with 'special' are handled specifically in itrender.c */
void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry)
{
const int log = 0;

	if ((!effect && !value) || (effect >= XM_N_EFFECTS))
		return;

if (log) printf("%c%02X", (effect<10)?('0'+effect):('A'+effect-10), value);

	/* Linearisation of the effect number... */
	if (effect == XM_E) {
		effect = EBASE + HIGH(value);
		value = LOW(value);
	} else if (effect == XM_X) {
		effect = XBASE + HIGH(value);
		value = LOW(value);
	}

if (log) printf(" - %2d %02X", effect, value);

#if 0 // This should be handled in itrender.c!
	/* update effect memory */
	switch (xm_has_memory[effect]) {
		case 1:
			if (!value)
				value = memory[entry->channel][effect];
			else
				memory[entry->channel][effect] = value;
			break;

		case 2:
			if (!HIGH(value))
				SET_HIGH(value, HIGH(memory[entry->channel][effect]));
			else
				SET_HIGH(memory[entry->channel][effect], HIGH(value));

			if (!LOW(value))
				SET_LOW(value, LOW(memory[entry->channel][effect]));
			else
				SET_LOW(memory[entry->channel][effect], LOW(value));
			break;
	}
#endif

	/* convert effect */
	entry->mask |= IT_ENTRY_EFFECT;
	switch (effect) {

		case XM_APPREGIO:           effect = IT_ARPEGGIO;           break;
		case XM_VIBRATO:            effect = IT_VIBRATO;            break;
		case XM_TONE_PORTAMENTO:    effect = IT_TONE_PORTAMENTO;    break; /** TODO: glissando control */
		case XM_TREMOLO:            effect = IT_TREMOLO;            break;
		case XM_SET_PANNING:        effect = IT_SET_PANNING;        break;
		case XM_SAMPLE_OFFSET:      effect = IT_SET_SAMPLE_OFFSET;  break;
		case XM_POSITION_JUMP:      effect = IT_JUMP_TO_ORDER;      break;
		case XM_MULTI_RETRIG:       effect = IT_RETRIGGER_NOTE;     break;
		case XM_TREMOR:             effect = IT_TREMOR;             break;
		case XM_PORTAMENTO_UP:      effect = IT_XM_PORTAMENTO_UP;   break;
		case XM_PORTAMENTO_DOWN:    effect = IT_XM_PORTAMENTO_DOWN; break;
		case XM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break; /* special */
		case XM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break; /* special */
		case XM_VOLSLIDE_VIBRATO:   effect = IT_VOLSLIDE_VIBRATO;   break; /* special */

		case XM_PATTERN_BREAK:
			effect = IT_BREAK_TO_ROW;
			value = BCD_TO_NORMAL(value);
			break;

		case XM_VOLUME_SLIDE: /* special */
			effect = IT_VOLUME_SLIDE;
			value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value));
			break;

		case XM_PANNING_SLIDE:
			effect = IT_PANNING_SLIDE;
			value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value));
			//value = HIGH(value) ? EFFECT_VALUE(0, HIGH(value)) : EFFECT_VALUE(LOW(value), 0);
			break;

		case XM_GLOBAL_VOLUME_SLIDE: /* special */
			effect = IT_GLOBAL_VOLUME_SLIDE;
			value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value));
			break;

		case XM_SET_TEMPO_BPM:
			effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
			break;

		case XM_SET_GLOBAL_VOLUME:
			effect = IT_SET_GLOBAL_VOLUME;
			value *= 2;
			break;

		case XM_KEY_OFF:
			effect = IT_XM_KEY_OFF;
			break;

		case XM_SET_ENVELOPE_POSITION:
			effect = IT_XM_SET_ENVELOPE_POSITION;
			break;

		case EBASE+XM_E_SET_FILTER:            effect = SBASE+IT_S_SET_FILTER;            break;
		case EBASE+XM_E_SET_GLISSANDO_CONTROL: effect = SBASE+IT_S_SET_GLISSANDO_CONTROL; break; /** TODO */
		case EBASE+XM_E_SET_FINETUNE:          effect = SBASE+IT_S_FINETUNE;              break; /** TODO */
		case EBASE+XM_E_SET_LOOP:              effect = SBASE+IT_S_PATTERN_LOOP;          break;
		case EBASE+XM_E_NOTE_CUT:              effect = SBASE+IT_S_DELAYED_NOTE_CUT;      break;
		case EBASE+XM_E_NOTE_DELAY:            effect = SBASE+IT_S_NOTE_DELAY;            break;
		case EBASE+XM_E_PATTERN_DELAY:         effect = SBASE+IT_S_PATTERN_DELAY;         break;
		case EBASE+XM_E_FINE_VOLSLIDE_UP:      effect = IT_XM_FINE_VOLSLIDE_UP;           break;
		case EBASE+XM_E_FINE_VOLSLIDE_DOWN:    effect = IT_XM_FINE_VOLSLIDE_DOWN;         break;

		case EBASE + XM_E_FINE_PORTA_UP:
			effect = IT_PORTAMENTO_UP;
			value = EFFECT_VALUE(0xF, value);
			break;

		case EBASE + XM_E_FINE_PORTA_DOWN:
			effect = IT_PORTAMENTO_DOWN;
			value = EFFECT_VALUE(0xF, value);
			break;

		case EBASE + XM_E_RETRIG_NOTE:
			effect = IT_XM_RETRIGGER_NOTE;
			value = EFFECT_VALUE(0, value);
			break;

		case EBASE + XM_E_SET_VIBRATO_CONTROL:
			effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM;
			value &= ~4; /** TODO: value&4 -> don't retrig wave */
			break;

		case EBASE + XM_E_SET_TREMOLO_CONTROL:
			effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM;
			value &= ~4; /** TODO: value&4 -> don't retrig wave */
			break;

		case XBASE + XM_X_EXTRAFINE_PORTA_UP:
			effect = IT_PORTAMENTO_UP;
			value = EFFECT_VALUE(0xE, value);
			break;

		case XBASE + XM_X_EXTRAFINE_PORTA_DOWN:
			effect = IT_PORTAMENTO_DOWN;
			value = EFFECT_VALUE(0xE, value);
			break;

		default:
			/* user effect (often used in demos for synchronisation) */
			entry->mask &= ~IT_ENTRY_EFFECT;
	}

if (log) printf(" - %2d %02X", effect, value);

	/* Inverse linearisation... */
	if (effect >= SBASE && effect < SBASE+16) {
		value = EFFECT_VALUE(effect-SBASE, value);
		effect = IT_S;
	}

if (log) printf(" - %c%02X\n", 'A'+effect-1, value);

	entry->effect = effect;
	entry->effectvalue = value;
}
예제 #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;
}
예제 #3
0
파일: ptmeffect.c 프로젝트: codefoco/dumb
void _dumb_it_ptm_convert_effect(int effect, int value, IT_ENTRY *entry) {
    if (effect >= PTM_N_EFFECTS)
        return;

    /* Linearisation of the effect number... */
    if (effect == PTM_E) {
        effect = PTM_EBASE + HIGH(value);
        value = LOW(value);
    }

    /* convert effect */
    entry->mask |= IT_ENTRY_EFFECT;
    switch (effect) {

    case PTM_APPREGIO:
        effect = IT_ARPEGGIO;
        break;
    case PTM_PORTAMENTO_UP:
        effect = IT_PORTAMENTO_UP;
        break;
    case PTM_PORTAMENTO_DOWN:
        effect = IT_PORTAMENTO_DOWN;
        break;
    case PTM_TONE_PORTAMENTO:
        effect = IT_TONE_PORTAMENTO;
        break;
    case PTM_VIBRATO:
        effect = IT_VIBRATO;
        break;
    case PTM_VOLSLIDE_TONEPORTA:
        effect = IT_VOLSLIDE_TONEPORTA;
        break;
    case PTM_VOLSLIDE_VIBRATO:
        effect = IT_VOLSLIDE_VIBRATO;
        break;
    case PTM_TREMOLO:
        effect = IT_TREMOLO;
        break;
    case PTM_SAMPLE_OFFSET:
        effect = IT_SET_SAMPLE_OFFSET;
        break;
    case PTM_VOLUME_SLIDE:
        effect = IT_VOLUME_SLIDE;
        break;
    case PTM_POSITION_JUMP:
        effect = IT_JUMP_TO_ORDER;
        break;
    case PTM_SET_CHANNEL_VOLUME:
        effect = IT_SET_CHANNEL_VOLUME;
        break;
    case PTM_PATTERN_BREAK:
        effect = IT_BREAK_TO_ROW;
        break;
    case PTM_SET_GLOBAL_VOLUME:
        effect = IT_SET_GLOBAL_VOLUME;
        break;
    case PTM_RETRIGGER:
        effect = IT_RETRIGGER_NOTE;
        break;
    case PTM_FINE_VIBRATO:
        effect = IT_FINE_VIBRATO;
        break;

    /* TODO properly */
    case PTM_NOTE_SLIDE_UP:
        effect = IT_PTM_NOTE_SLIDE_UP;
        break;
    case PTM_NOTE_SLIDE_DOWN:
        effect = IT_PTM_NOTE_SLIDE_DOWN;
        break;
    case PTM_NOTE_SLIDE_UP_RETRIG:
        effect = IT_PTM_NOTE_SLIDE_UP_RETRIG;
        break;
    case PTM_NOTE_SLIDE_DOWN_RETRIG:
        effect = IT_PTM_NOTE_SLIDE_DOWN_RETRIG;
        break;

    case PTM_SET_TEMPO_BPM:
        effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO);
        break;

    case PTM_EBASE + PTM_E_SET_FINETUNE:
        effect = SBASE + IT_S_FINETUNE;
        break; /** TODO */
    case PTM_EBASE + PTM_E_SET_LOOP:
        effect = SBASE + IT_S_PATTERN_LOOP;
        break;
    case PTM_EBASE + PTM_E_NOTE_CUT:
        effect = SBASE + IT_S_DELAYED_NOTE_CUT;
        break;
    case PTM_EBASE + PTM_E_NOTE_DELAY:
        effect = SBASE + IT_S_NOTE_DELAY;
        break;
    case PTM_EBASE + PTM_E_PATTERN_DELAY:
        effect = SBASE + IT_S_PATTERN_DELAY;
        break;
    case PTM_EBASE + PTM_E_SET_PANNING:
        effect = SBASE + IT_S_SET_PAN;
        break;

    case PTM_EBASE + PTM_E_FINE_VOLSLIDE_UP:
        effect = IT_VOLUME_SLIDE;
        value = EFFECT_VALUE(value, 0xF);
        break;

    case PTM_EBASE + PTM_E_FINE_VOLSLIDE_DOWN:
        effect = IT_VOLUME_SLIDE;
        value = EFFECT_VALUE(0xF, value);
        break;

    case PTM_EBASE + PTM_E_FINE_PORTA_UP:
        effect = IT_PORTAMENTO_UP;
        value = EFFECT_VALUE(0xF, value);
        break;

    case PTM_EBASE + PTM_E_FINE_PORTA_DOWN:
        effect = IT_PORTAMENTO_DOWN;
        value = EFFECT_VALUE(0xF, value);
        break;

    case PTM_EBASE + PTM_E_RETRIG_NOTE:
        effect = IT_XM_RETRIGGER_NOTE;
        value = EFFECT_VALUE(0, value);
        break;

    case PTM_EBASE + PTM_E_SET_VIBRATO_CONTROL:
        effect = SBASE + IT_S_SET_VIBRATO_WAVEFORM;
        value &= ~4; /** TODO: value&4 -> don't retrig wave */
        break;

    case PTM_EBASE + PTM_E_SET_TREMOLO_CONTROL:
        effect = SBASE + IT_S_SET_TREMOLO_WAVEFORM;
        value &= ~4; /** TODO: value&4 -> don't retrig wave */
        break;

    default:
        /* user effect (often used in demos for synchronisation) */
        entry->mask &= ~IT_ENTRY_EFFECT;
    }

    /* Inverse linearisation... */
    if (effect >= SBASE && effect < SBASE + 16) {
        value = EFFECT_VALUE(effect - SBASE, value);
        effect = IT_S;
    }

    entry->effect = effect;
    entry->effectvalue = value;
}