blob: a635039babe84ff6952de000f4f80ca50b0e6d1d [file] [log] [blame]
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +00001/* _______ ____ __ ___ ___
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
31unsigned 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
53void _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 */
67static 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 */
79void _dumb_it_xm_convert_effect(int effect, int value, IT_ENTRY *entry)
80{
Daniel Stenberg4cc0b972005-05-07 22:10:35 +000081#ifdef SIMULATOR
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +000082const int log = 0;
Daniel Stenberg4cc0b972005-05-07 22:10:35 +000083#endif
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +000084
85 if ((!effect && !value) || (effect >= XM_N_EFFECTS))
86 return;
87
Daniel Stenberg4cc0b972005-05-07 22:10:35 +000088#ifdef SIMULATOR
Tomas Salfischberger88a89e02005-06-14 19:04:47 +000089if (log) DEBUGF("%c%02X", (effect<10)?('0'+effect):('A'+effect-10), value);
Daniel Stenberg4cc0b972005-05-07 22:10:35 +000090#endif
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +000091
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 Stenberg4cc0b972005-05-07 22:10:35 +0000101#ifdef SIMULATOR
Tomas Salfischberger88a89e02005-06-14 19:04:47 +0000102if (log) DEBUGF(" - %2d %02X", effect, value);
Daniel Stenberg4cc0b972005-05-07 22:10:35 +0000103#endif
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +0000104
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 Stenberg4cc0b972005-05-07 22:10:35 +0000236#ifdef SIMULATOR
Tomas Salfischberger88a89e02005-06-14 19:04:47 +0000237if (log) DEBUGF(" - %2d %02X", effect, value);
Daniel Stenberg4cc0b972005-05-07 22:10:35 +0000238#endif
239
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +0000240 /* Inverse linearisation... */
241 if (effect >= SBASE && effect < SBASE+16) {
242 value = EFFECT_VALUE(effect-SBASE, value);
243 effect = IT_S;
244 }
245
Daniel Stenberg4cc0b972005-05-07 22:10:35 +0000246#ifdef SIMULATOR
Tomas Salfischberger88a89e02005-06-14 19:04:47 +0000247if (log) DEBUGF(" - %c%02X\n", 'A'+effect-1, value);
Daniel Stenberg4cc0b972005-05-07 22:10:35 +0000248#endif
249
Michiel Van Der Kolk27be5bc2005-03-17 20:50:03 +0000250 entry->effect = effect;
251 entry->effectvalue = value;
252}