1 /* Extended Module Player
2 * Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <stdarg.h>
28
29 #include "format.h"
30 #include "virtual.h"
31 #include "mixer.h"
32
33 const char *xmp_version = XMP_VERSION;
34 const unsigned int xmp_vercode = XMP_VERCODE;
35
xmp_create_context()36 xmp_context xmp_create_context()
37 {
38 struct context_data *ctx;
39
40 ctx = (struct context_data *)calloc(1, sizeof(struct context_data));
41 if (ctx == NULL) {
42 return NULL;
43 }
44
45 ctx->state = XMP_STATE_UNLOADED;
46 ctx->m.defpan = 100;
47 ctx->s.numvoc = SMIX_NUMVOC;
48
49 return (xmp_context)ctx;
50 }
51
xmp_free_context(xmp_context opaque)52 void xmp_free_context(xmp_context opaque)
53 {
54 struct context_data *ctx = (struct context_data *)opaque;
55
56 if (ctx->state > XMP_STATE_UNLOADED)
57 xmp_release_module(opaque);
58
59 free(opaque);
60 }
61
set_position(struct context_data * ctx,int pos,int dir)62 static void set_position(struct context_data *ctx, int pos, int dir)
63 {
64 struct player_data *p = &ctx->p;
65 struct module_data *m = &ctx->m;
66 struct xmp_module *mod = &m->mod;
67 struct flow_control *f = &p->flow;
68 int seq;
69 int has_marker;
70
71 /* If dir is 0, we can jump to a different sequence */
72 if (dir == 0) {
73 seq = libxmp_get_sequence(ctx, pos);
74 } else {
75 seq = p->sequence;
76 }
77
78 if (seq == 0xff) {
79 return;
80 }
81
82 has_marker = HAS_QUIRK(QUIRK_MARKER);
83
84 if (seq >= 0) {
85 int start = m->seq_data[seq].entry_point;
86
87 p->sequence = seq;
88
89 if (pos >= 0) {
90 int pat;
91
92 while (has_marker && mod->xxo[pos] == 0xfe) {
93 if (dir < 0) {
94 if (pos > start) {
95 pos--;
96 }
97 } else {
98 pos++;
99 }
100 }
101 pat = mod->xxo[pos];
102
103 if (pat < mod->pat) {
104 if (has_marker && pat == 0xff) {
105 return;
106 }
107
108 if (pos > p->scan[seq].ord) {
109 f->end_point = 0;
110 } else {
111 f->num_rows = mod->xxp[pat]->rows;
112 f->end_point = p->scan[seq].num;
113 f->jumpline = 0;
114 }
115 }
116 }
117
118 if (pos < mod->len) {
119 if (pos == 0) {
120 p->pos = -1;
121 } else {
122 p->pos = pos;
123 }
124 }
125 }
126 }
127
xmp_next_position(xmp_context opaque)128 int xmp_next_position(xmp_context opaque)
129 {
130 struct context_data *ctx = (struct context_data *)opaque;
131 struct player_data *p = &ctx->p;
132 struct module_data *m = &ctx->m;
133
134 if (ctx->state < XMP_STATE_PLAYING)
135 return -XMP_ERROR_STATE;
136
137 if (p->pos < m->mod.len)
138 set_position(ctx, p->pos + 1, 1);
139
140 return p->pos;
141 }
142
xmp_prev_position(xmp_context opaque)143 int xmp_prev_position(xmp_context opaque)
144 {
145 struct context_data *ctx = (struct context_data *)opaque;
146 struct player_data *p = &ctx->p;
147 struct module_data *m = &ctx->m;
148
149 if (ctx->state < XMP_STATE_PLAYING)
150 return -XMP_ERROR_STATE;
151
152 if (p->pos == m->seq_data[p->sequence].entry_point) {
153 set_position(ctx, -1, -1);
154 } else if (p->pos > m->seq_data[p->sequence].entry_point) {
155 set_position(ctx, p->pos - 1, -1);
156 }
157 return p->pos < 0 ? 0 : p->pos;
158 }
159
xmp_set_position(xmp_context opaque,int pos)160 int xmp_set_position(xmp_context opaque, int pos)
161 {
162 struct context_data *ctx = (struct context_data *)opaque;
163 struct player_data *p = &ctx->p;
164 struct module_data *m = &ctx->m;
165
166 if (ctx->state < XMP_STATE_PLAYING)
167 return -XMP_ERROR_STATE;
168
169 if (pos >= m->mod.len)
170 return -XMP_ERROR_INVALID;
171
172 set_position(ctx, pos, 0);
173
174 return p->pos;
175 }
176
xmp_set_row(xmp_context opaque,int row)177 int xmp_set_row(xmp_context opaque, int row)
178 {
179 struct context_data *ctx = (struct context_data *)opaque;
180 struct player_data *p = &ctx->p;
181 struct module_data *m = &ctx->m;
182 struct xmp_module *mod = &m->mod;
183 struct flow_control *f = &p->flow;
184 int pos = p->pos;
185 int pattern = mod->xxo[pos];
186
187 if (pos < 0 || pos >= mod->len) {
188 pos = 0;
189 }
190
191 if (ctx->state < XMP_STATE_PLAYING)
192 return -XMP_ERROR_STATE;
193
194 if (row >= mod->xxp[pattern]->rows)
195 return -XMP_ERROR_INVALID;
196
197 /* See set_position. */
198 if (p->pos < 0)
199 p->pos = 0;
200 p->ord = p->pos;
201 p->row = row;
202 p->frame = -1;
203 f->num_rows = mod->xxp[mod->xxo[p->ord]]->rows;
204
205 return row;
206 }
207
xmp_stop_module(xmp_context opaque)208 void xmp_stop_module(xmp_context opaque)
209 {
210 struct context_data *ctx = (struct context_data *)opaque;
211 struct player_data *p = &ctx->p;
212
213 if (ctx->state < XMP_STATE_PLAYING)
214 return;
215
216 p->pos = -2;
217 }
218
xmp_restart_module(xmp_context opaque)219 void xmp_restart_module(xmp_context opaque)
220 {
221 struct context_data *ctx = (struct context_data *)opaque;
222 struct player_data *p = &ctx->p;
223
224 if (ctx->state < XMP_STATE_PLAYING)
225 return;
226
227 p->loop_count = 0;
228 p->pos = -1;
229 }
230
xmp_seek_time(xmp_context opaque,int time)231 int xmp_seek_time(xmp_context opaque, int time)
232 {
233 struct context_data *ctx = (struct context_data *)opaque;
234 struct player_data *p = &ctx->p;
235 struct module_data *m = &ctx->m;
236 int i, t;
237
238 if (ctx->state < XMP_STATE_PLAYING)
239 return -XMP_ERROR_STATE;
240
241 for (i = m->mod.len - 1; i >= 0; i--) {
242 int pat = m->mod.xxo[i];
243 if (pat >= m->mod.pat) {
244 continue;
245 }
246 if (libxmp_get_sequence(ctx, i) != p->sequence) {
247 continue;
248 }
249 t = m->xxo_info[i].time;
250 if (time >= t) {
251 set_position(ctx, i, 1);
252 break;
253 }
254 }
255 if (i < 0) {
256 xmp_set_position(opaque, 0);
257 }
258
259 return p->pos < 0 ? 0 : p->pos;
260 }
261
xmp_channel_mute(xmp_context opaque,int chn,int status)262 int xmp_channel_mute(xmp_context opaque, int chn, int status)
263 {
264 struct context_data *ctx = (struct context_data *)opaque;
265 struct player_data *p = &ctx->p;
266 int ret;
267
268 if (ctx->state < XMP_STATE_PLAYING)
269 return -XMP_ERROR_STATE;
270
271 if (chn < 0 || chn >= XMP_MAX_CHANNELS) {
272 return -XMP_ERROR_INVALID;
273 }
274
275 ret = p->channel_mute[chn];
276
277 if (status >= 2) {
278 p->channel_mute[chn] = !p->channel_mute[chn];
279 } else if (status >= 0) {
280 p->channel_mute[chn] = status;
281 }
282
283 return ret;
284 }
285
xmp_channel_vol(xmp_context opaque,int chn,int vol)286 int xmp_channel_vol(xmp_context opaque, int chn, int vol)
287 {
288 struct context_data *ctx = (struct context_data *)opaque;
289 struct player_data *p = &ctx->p;
290 int ret;
291
292 if (ctx->state < XMP_STATE_PLAYING)
293 return -XMP_ERROR_STATE;
294
295 if (chn < 0 || chn >= XMP_MAX_CHANNELS) {
296 return -XMP_ERROR_INVALID;
297 }
298
299 ret = p->channel_vol[chn];
300
301 if (vol >= 0 && vol <= 100) {
302 p->channel_vol[chn] = vol;
303 }
304
305 return ret;
306 }
307
308 #ifdef USE_VERSIONED_SYMBOLS
309 LIBXMP_EXPORT extern int xmp_set_player_v40__(xmp_context, int, int);
310 LIBXMP_EXPORT extern int xmp_set_player_v41__(xmp_context, int, int)
311 __attribute__((alias("xmp_set_player_v40__")));
312 LIBXMP_EXPORT extern int xmp_set_player_v43__(xmp_context, int, int)
313 __attribute__((alias("xmp_set_player_v40__")));
314 LIBXMP_EXPORT extern int xmp_set_player_v44__(xmp_context, int, int)
315 __attribute__((alias("xmp_set_player_v40__")));
316
317 asm(".symver xmp_set_player_v40__, xmp_set_player@XMP_4.0");
318 asm(".symver xmp_set_player_v41__, xmp_set_player@XMP_4.1");
319 asm(".symver xmp_set_player_v43__, xmp_set_player@XMP_4.3");
320 asm(".symver xmp_set_player_v44__, xmp_set_player@@XMP_4.4");
321
322 #define xmp_set_player__ xmp_set_player_v40__
323 #else
324 #define xmp_set_player__ xmp_set_player
325 #endif
326
xmp_set_player__(xmp_context opaque,int parm,int val)327 int xmp_set_player__(xmp_context opaque, int parm, int val)
328 {
329 struct context_data *ctx = (struct context_data *)opaque;
330 struct player_data *p = &ctx->p;
331 struct module_data *m = &ctx->m;
332 struct mixer_data *s = &ctx->s;
333 int ret = -XMP_ERROR_INVALID;
334
335
336 if (parm == XMP_PLAYER_SMPCTL || parm == XMP_PLAYER_DEFPAN) {
337 /* these should be set before loading the module */
338 if (ctx->state >= XMP_STATE_LOADED) {
339 return -XMP_ERROR_STATE;
340 }
341 } else if (parm == XMP_PLAYER_VOICES) {
342 /* these should be set before start playing */
343 if (ctx->state >= XMP_STATE_PLAYING) {
344 return -XMP_ERROR_STATE;
345 }
346 } else if (ctx->state < XMP_STATE_PLAYING) {
347 return -XMP_ERROR_STATE;
348 }
349
350 switch (parm) {
351 case XMP_PLAYER_AMP:
352 if (val >= 0 && val <= 3) {
353 s->amplify = val;
354 ret = 0;
355 }
356 break;
357 case XMP_PLAYER_MIX:
358 if (val >= -100 && val <= 100) {
359 s->mix = val;
360 ret = 0;
361 }
362 break;
363 case XMP_PLAYER_INTERP:
364 if (val >= XMP_INTERP_NEAREST && val <= XMP_INTERP_SPLINE) {
365 s->interp = val;
366 ret = 0;
367 }
368 break;
369 case XMP_PLAYER_DSP:
370 s->dsp = val;
371 ret = 0;
372 break;
373 case XMP_PLAYER_FLAGS: {
374 p->player_flags = val;
375 ret = 0;
376 break; }
377
378 /* 4.1 */
379 case XMP_PLAYER_CFLAGS: {
380 int vblank = p->flags & XMP_FLAGS_VBLANK;
381 p->flags = val;
382 if (vblank != (p->flags & XMP_FLAGS_VBLANK))
383 libxmp_scan_sequences(ctx);
384 ret = 0;
385 break; }
386 case XMP_PLAYER_SMPCTL:
387 m->smpctl = val;
388 ret = 0;
389 break;
390 case XMP_PLAYER_VOLUME:
391 if (val >= 0 && val <= 200) {
392 p->master_vol = val;
393 ret = 0;
394 }
395 break;
396 case XMP_PLAYER_SMIX_VOLUME:
397 if (val >= 0 && val <= 200) {
398 p->smix_vol = val;
399 ret = 0;
400 }
401 break;
402
403 /* 4.3 */
404 case XMP_PLAYER_DEFPAN:
405 if (val >= 0 && val <= 100) {
406 m->defpan = val;
407 ret = 0;
408 }
409 break;
410
411 /* 4.4 */
412 case XMP_PLAYER_MODE:
413 p->mode = val;
414 libxmp_set_player_mode(ctx);
415 libxmp_scan_sequences(ctx);
416 ret = 0;
417 break;
418 case XMP_PLAYER_VOICES:
419 s->numvoc = val;
420 break;
421 }
422
423 return ret;
424 }
425
426 #ifdef USE_VERSIONED_SYMBOLS
427 LIBXMP_EXPORT extern int xmp_get_player_v40__(xmp_context, int);
428 LIBXMP_EXPORT extern int xmp_get_player_v41__(xmp_context, int)
429 __attribute__((alias("xmp_get_player_v40__")));
430 LIBXMP_EXPORT extern int xmp_get_player_v42__(xmp_context, int)
431 __attribute__((alias("xmp_get_player_v40__")));
432 LIBXMP_EXPORT extern int xmp_get_player_v43__(xmp_context, int)
433 __attribute__((alias("xmp_get_player_v40__")));
434 LIBXMP_EXPORT extern int xmp_get_player_v44__(xmp_context, int)
435 __attribute__((alias("xmp_get_player_v40__")));
436
437 asm(".symver xmp_get_player_v40__, xmp_get_player@XMP_4.0");
438 asm(".symver xmp_get_player_v41__, xmp_get_player@XMP_4.1");
439 asm(".symver xmp_get_player_v42__, xmp_get_player@XMP_4.2");
440 asm(".symver xmp_get_player_v43__, xmp_get_player@XMP_4.3");
441 asm(".symver xmp_get_player_v44__, xmp_get_player@@XMP_4.4");
442
443 #define xmp_get_player__ xmp_get_player_v40__
444 #else
445 #define xmp_get_player__ xmp_get_player
446 #endif
447
xmp_get_player__(xmp_context opaque,int parm)448 int xmp_get_player__(xmp_context opaque, int parm)
449 {
450 struct context_data *ctx = (struct context_data *)opaque;
451 struct player_data *p = &ctx->p;
452 struct module_data *m = &ctx->m;
453 struct mixer_data *s = &ctx->s;
454 int ret = -XMP_ERROR_INVALID;
455
456 if (parm == XMP_PLAYER_SMPCTL || parm == XMP_PLAYER_DEFPAN) {
457 // can read these at any time
458 } else if (parm != XMP_PLAYER_STATE && ctx->state < XMP_STATE_PLAYING) {
459 return -XMP_ERROR_STATE;
460 }
461
462 switch (parm) {
463 case XMP_PLAYER_AMP:
464 ret = s->amplify;
465 break;
466 case XMP_PLAYER_MIX:
467 ret = s->mix;
468 break;
469 case XMP_PLAYER_INTERP:
470 ret = s->interp;
471 break;
472 case XMP_PLAYER_DSP:
473 ret = s->dsp;
474 break;
475 case XMP_PLAYER_FLAGS:
476 ret = p->player_flags;
477 break;
478
479 /* 4.1 */
480 case XMP_PLAYER_CFLAGS:
481 ret = p->flags;
482 break;
483 case XMP_PLAYER_SMPCTL:
484 ret = m->smpctl;
485 break;
486 case XMP_PLAYER_VOLUME:
487 ret = p->master_vol;
488 break;
489 case XMP_PLAYER_SMIX_VOLUME:
490 ret = p->smix_vol;
491 break;
492
493 /* 4.2 */
494 case XMP_PLAYER_STATE:
495 ret = ctx->state;
496 break;
497
498 /* 4.3 */
499 case XMP_PLAYER_DEFPAN:
500 ret = m->defpan;
501 break;
502
503 /* 4.4 */
504 case XMP_PLAYER_MODE:
505 ret = p->mode;
506 break;
507 case XMP_PLAYER_MIXER_TYPE:
508 ret = XMP_MIXER_STANDARD;
509 if (p->flags & XMP_FLAGS_A500) {
510 if (IS_AMIGA_MOD()) {
511 #ifdef LIBXMP_PAULA_SIMULATOR
512 if (p->filter) {
513 ret = XMP_MIXER_A500F;
514 } else {
515 ret = XMP_MIXER_A500;
516 }
517 #endif
518 }
519 }
520 break;
521 case XMP_PLAYER_VOICES:
522 ret = s->numvoc;
523 break;
524 }
525
526 return ret;
527 }
528
xmp_get_format_list()529 const char **xmp_get_format_list()
530 {
531 return format_list();
532 }
533
xmp_inject_event(xmp_context opaque,int channel,struct xmp_event * e)534 void xmp_inject_event(xmp_context opaque, int channel, struct xmp_event *e)
535 {
536 struct context_data *ctx = (struct context_data *)opaque;
537 struct player_data *p = &ctx->p;
538
539 if (ctx->state < XMP_STATE_PLAYING)
540 return;
541
542 memcpy(&p->inject_event[channel], e, sizeof(struct xmp_event));
543 p->inject_event[channel]._flag = 1;
544 }
545
xmp_set_instrument_path(xmp_context opaque,char * path)546 int xmp_set_instrument_path(xmp_context opaque, char *path)
547 {
548 struct context_data *ctx = (struct context_data *)opaque;
549 struct module_data *m = &ctx->m;
550
551 if (m->instrument_path != NULL)
552 free(m->instrument_path);
553
554 m->instrument_path = strdup(path);
555 if (m->instrument_path == NULL) {
556 return -XMP_ERROR_SYSTEM;
557 }
558
559 return 0;
560 }
561
xmp_set_tempo_factor(xmp_context opaque,double val)562 int xmp_set_tempo_factor(xmp_context opaque, double val)
563 {
564 struct context_data *ctx = (struct context_data *)opaque;
565 struct player_data *p = &ctx->p;
566 struct module_data *m = &ctx->m;
567 struct mixer_data *s = &ctx->s;
568 int ticksize;
569
570 if (val <= 0.0) {
571 return -1;
572 }
573
574 val *= 10;
575 ticksize = s->freq * m->time_factor * m->rrate / p->bpm / 1000 * sizeof(int);
576 if (ticksize > XMP_MAX_FRAMESIZE) {
577 return -1;
578 }
579 m->time_factor = val;
580
581 return 0;
582 }
583