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