Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 1 | /* _______ ____ __ ___ ___ |
| 2 | * \ _ \ \ / \ / \ \ / / ' ' ' |
| 3 | * | | \ \ | | || | \/ | . . |
| 4 | * | | | | | | || ||\ /| | |
| 5 | * | | | | | | || || \/ | | ' ' ' |
| 6 | * | | | | | | || || | | . . |
| 7 | * | |_/ / \ \__// || | | |
| 8 | * /_______/ynamic \____/niversal /__\ /____\usic /| . . ibliotheque |
| 9 | * / \ |
| 10 | * / . \ |
| 11 | * xmeffect.c - Code for converting MOD/XM / / \ \ |
| 12 | * effects to IT effects. | < / \_ |
| 13 | * | \/ /\ / |
| 14 | * By Julien Cugniere. Ripped out of readxm.c \_ / > / |
| 15 | * by entheh. | \ / / |
| 16 | * | ' / |
| 17 | * \__/ |
| 18 | */ |
| 19 | |
| 20 | |
| 21 | |
| 22 | #include <stdlib.h> |
| 23 | #include <string.h> |
| 24 | |
| 25 | #include "dumb.h" |
| 26 | #include "internal/it.h" |
| 27 | |
| 28 | |
| 29 | |
| 30 | #if 0 |
| 31 | unsigned char **_dumb_malloc2(int w, int h) |
| 32 | { |
| 33 | unsigned char **line = malloc(h * sizeof(*line)); |
| 34 | int i; |
| 35 | if (!line) return NULL; |
| 36 | |
| 37 | line[0] = malloc(w * h * sizeof(*line[0])); |
| 38 | if (!line[0]) { |
| 39 | free(line); |
| 40 | return NULL; |
| 41 | } |
| 42 | |
| 43 | for (i = 1; i < h; i++) |
| 44 | line[i] = line[i-1] + w; |
| 45 | |
| 46 | memset(line[0], 0, w*h); |
| 47 | |
| 48 | return line; |
| 49 | } |
| 50 | |
| 51 | |
| 52 | |
| 53 | void _dumb_free2(unsigned char **line) |
| 54 | { |
| 55 | if (line) { |
| 56 | if (line[0]) |
| 57 | free(line[0]); |
| 58 | free(line); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | |
| 63 | |
| 64 | /* Effects having a memory. 2 means that the two parts of the effectvalue |
| 65 | * should be handled separately. |
| 66 | */ |
| 67 | static const char xm_has_memory[] = { |
| 68 | /* 0 1 2 3 4 5 6 7 8 9 A B C D (E) F G H K L P R T (X) */ |
| 69 | 0, 1, 1, 1, 2, 1, 1, 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, |
| 70 | |
| 71 | /* E0 E1 E2 E3 E4 E5 E6 E7 E9 EA EB EC ED EE X1 X2 */ |
| 72 | 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
| 73 | }; |
| 74 | #endif |
| 75 | |
| 76 | |
| 77 | |
| 78 | /* Effects marked with 'special' are handled specifically in itrender.c */ |
| 79 | void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry) |
| 80 | { |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 81 | #ifdef SIMULATOR |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 82 | const int log = 0; |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 83 | #endif |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 84 | |
| 85 | if ((!effect && !value) || (effect >= XM_N_EFFECTS)) |
| 86 | return; |
| 87 | |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 88 | #ifdef SIMULATOR |
Tomas Salfischberger | 88a89e0 | 2005-06-14 19:04:47 +0000 | [diff] [blame^] | 89 | if (log) DEBUGF("%c%02X", (effect<10)?('0'+effect):('A'+effect-10), value); |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 90 | #endif |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 91 | |
| 92 | /* Linearisation of the effect number... */ |
| 93 | if (effect == XM_E) { |
| 94 | effect = EBASE + HIGH(value); |
| 95 | value = LOW(value); |
| 96 | } else if (effect == XM_X) { |
| 97 | effect = XBASE + HIGH(value); |
| 98 | value = LOW(value); |
| 99 | } |
| 100 | |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 101 | #ifdef SIMULATOR |
Tomas Salfischberger | 88a89e0 | 2005-06-14 19:04:47 +0000 | [diff] [blame^] | 102 | if (log) DEBUGF(" - %2d %02X", effect, value); |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 103 | #endif |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 104 | |
| 105 | #if 0 // This should be handled in itrender.c! |
| 106 | /* update effect memory */ |
| 107 | switch (xm_has_memory[effect]) { |
| 108 | case 1: |
| 109 | if (!value) |
| 110 | value = memory[entry->channel][effect]; |
| 111 | else |
| 112 | memory[entry->channel][effect] = value; |
| 113 | break; |
| 114 | |
| 115 | case 2: |
| 116 | if (!HIGH(value)) |
| 117 | SET_HIGH(value, HIGH(memory[entry->channel][effect])); |
| 118 | else |
| 119 | SET_HIGH(memory[entry->channel][effect], HIGH(value)); |
| 120 | |
| 121 | if (!LOW(value)) |
| 122 | SET_LOW(value, LOW(memory[entry->channel][effect])); |
| 123 | else |
| 124 | SET_LOW(memory[entry->channel][effect], LOW(value)); |
| 125 | break; |
| 126 | } |
| 127 | #endif |
| 128 | |
| 129 | /* convert effect */ |
| 130 | entry->mask |= IT_ENTRY_EFFECT; |
| 131 | switch (effect) { |
| 132 | |
| 133 | case XM_APPREGIO: effect = IT_ARPEGGIO; break; |
| 134 | case XM_VIBRATO: effect = IT_VIBRATO; break; |
| 135 | case XM_TONE_PORTAMENTO: effect = IT_TONE_PORTAMENTO; break; /** TODO: glissando control */ |
| 136 | case XM_TREMOLO: effect = IT_TREMOLO; break; |
| 137 | case XM_SET_PANNING: effect = IT_SET_PANNING; break; |
| 138 | case XM_SAMPLE_OFFSET: effect = IT_SET_SAMPLE_OFFSET; break; |
| 139 | case XM_POSITION_JUMP: effect = IT_JUMP_TO_ORDER; break; |
| 140 | case XM_MULTI_RETRIG: effect = IT_RETRIGGER_NOTE; break; |
| 141 | case XM_TREMOR: effect = IT_TREMOR; break; |
| 142 | case XM_PORTAMENTO_UP: effect = IT_XM_PORTAMENTO_UP; break; |
| 143 | case XM_PORTAMENTO_DOWN: effect = IT_XM_PORTAMENTO_DOWN; break; |
| 144 | case XM_SET_CHANNEL_VOLUME: effect = IT_SET_CHANNEL_VOLUME; break; /* special */ |
| 145 | case XM_VOLSLIDE_TONEPORTA: effect = IT_VOLSLIDE_TONEPORTA; break; /* special */ |
| 146 | case XM_VOLSLIDE_VIBRATO: effect = IT_VOLSLIDE_VIBRATO; break; /* special */ |
| 147 | |
| 148 | case XM_PATTERN_BREAK: |
| 149 | effect = IT_BREAK_TO_ROW; |
| 150 | value = BCD_TO_NORMAL(value); |
| 151 | break; |
| 152 | |
| 153 | case XM_VOLUME_SLIDE: /* special */ |
| 154 | effect = IT_VOLUME_SLIDE; |
| 155 | value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value)); |
| 156 | break; |
| 157 | |
| 158 | case XM_PANNING_SLIDE: |
| 159 | effect = IT_PANNING_SLIDE; |
| 160 | value = HIGH(value) ? EFFECT_VALUE(0, HIGH(value)) : EFFECT_VALUE(LOW(value), 0); |
| 161 | break; |
| 162 | |
| 163 | case XM_GLOBAL_VOLUME_SLIDE: /* special */ |
| 164 | effect = IT_GLOBAL_VOLUME_SLIDE; |
| 165 | value = HIGH(value) ? EFFECT_VALUE(HIGH(value), 0) : EFFECT_VALUE(0, LOW(value)); |
| 166 | break; |
| 167 | |
| 168 | case XM_SET_TEMPO_BPM: |
| 169 | effect = (value < 0x20) ? (IT_SET_SPEED) : (IT_SET_SONG_TEMPO); |
| 170 | break; |
| 171 | |
| 172 | case XM_SET_GLOBAL_VOLUME: |
| 173 | effect = IT_SET_GLOBAL_VOLUME; |
| 174 | value *= 2; |
| 175 | break; |
| 176 | |
| 177 | case XM_KEY_OFF: |
| 178 | /** WARNING: In FT2, the value seems to do something... Oh well, |
| 179 | * this is undocumented anyway! |
| 180 | */ |
| 181 | entry->mask &= ~IT_ENTRY_EFFECT; |
| 182 | entry->mask |= IT_ENTRY_NOTE; |
| 183 | entry->note = IT_NOTE_OFF; |
| 184 | break; |
| 185 | |
| 186 | case EBASE+XM_E_SET_FILTER: effect = SBASE+IT_S_SET_FILTER; break; |
| 187 | case EBASE+XM_E_SET_GLISSANDO_CONTROL: effect = SBASE+IT_S_SET_GLISSANDO_CONTROL; break; /** TODO */ |
| 188 | case EBASE+XM_E_SET_FINETUNE: effect = SBASE+IT_S_FINETUNE; break; /** TODO */ |
| 189 | case EBASE+XM_E_SET_LOOP: effect = SBASE+IT_S_PATTERN_LOOP; break; |
| 190 | case EBASE+XM_E_NOTE_CUT: effect = SBASE+IT_S_DELAYED_NOTE_CUT; break; |
| 191 | case EBASE+XM_E_NOTE_DELAY: effect = SBASE+IT_S_NOTE_DELAY; break; |
| 192 | case EBASE+XM_E_PATTERN_DELAY: effect = SBASE+IT_S_PATTERN_DELAY; break; |
| 193 | case EBASE+XM_E_FINE_VOLSLIDE_UP: effect = IT_XM_FINE_VOLSLIDE_UP; break; |
| 194 | case EBASE+XM_E_FINE_VOLSLIDE_DOWN: effect = IT_XM_FINE_VOLSLIDE_DOWN; break; |
| 195 | |
| 196 | case EBASE + XM_E_FINE_PORTA_UP: |
| 197 | effect = IT_PORTAMENTO_UP; |
| 198 | value = EFFECT_VALUE(0xF, value); |
| 199 | break; |
| 200 | |
| 201 | case EBASE + XM_E_FINE_PORTA_DOWN: |
| 202 | effect = IT_PORTAMENTO_DOWN; |
| 203 | value = EFFECT_VALUE(0xF, value); |
| 204 | break; |
| 205 | |
| 206 | case EBASE + XM_E_RETRIG_NOTE: |
| 207 | effect = IT_XM_RETRIGGER_NOTE; |
| 208 | value = EFFECT_VALUE(0, value); |
| 209 | break; |
| 210 | |
| 211 | case EBASE + XM_E_SET_VIBRATO_CONTROL: |
| 212 | effect = SBASE+IT_S_SET_VIBRATO_WAVEFORM; |
| 213 | value &= ~4; /** TODO: value&4 -> don't retrig wave */ |
| 214 | break; |
| 215 | |
| 216 | case EBASE + XM_E_SET_TREMOLO_CONTROL: |
| 217 | effect = SBASE+IT_S_SET_TREMOLO_WAVEFORM; |
| 218 | value &= ~4; /** TODO: value&4 -> don't retrig wave */ |
| 219 | break; |
| 220 | |
| 221 | case XBASE + XM_X_EXTRAFINE_PORTA_UP: |
| 222 | effect = IT_PORTAMENTO_UP; |
| 223 | value = EFFECT_VALUE(0xE, value); |
| 224 | break; |
| 225 | |
| 226 | case XBASE + XM_X_EXTRAFINE_PORTA_DOWN: |
| 227 | effect = IT_PORTAMENTO_DOWN; |
| 228 | value = EFFECT_VALUE(0xE, value); |
| 229 | break; |
| 230 | |
| 231 | default: |
| 232 | /* user effect (often used in demos for synchronisation) */ |
| 233 | entry->mask &= ~IT_ENTRY_EFFECT; |
| 234 | } |
| 235 | |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 236 | #ifdef SIMULATOR |
Tomas Salfischberger | 88a89e0 | 2005-06-14 19:04:47 +0000 | [diff] [blame^] | 237 | if (log) DEBUGF(" - %2d %02X", effect, value); |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 238 | #endif |
| 239 | |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 240 | /* Inverse linearisation... */ |
| 241 | if (effect >= SBASE && effect < SBASE+16) { |
| 242 | value = EFFECT_VALUE(effect-SBASE, value); |
| 243 | effect = IT_S; |
| 244 | } |
| 245 | |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 246 | #ifdef SIMULATOR |
Tomas Salfischberger | 88a89e0 | 2005-06-14 19:04:47 +0000 | [diff] [blame^] | 247 | if (log) DEBUGF(" - %c%02X\n", 'A'+effect-1, value); |
Daniel Stenberg | 4cc0b97 | 2005-05-07 22:10:35 +0000 | [diff] [blame] | 248 | #endif |
| 249 | |
Michiel Van Der Kolk | 27be5bc | 2005-03-17 20:50:03 +0000 | [diff] [blame] | 250 | entry->effect = effect; |
| 251 | entry->effectvalue = value; |
| 252 | } |