/* 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; }
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; }
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; }