/* Extended Module Player * Copyright (C) 1996-1999 Claudio Matsuoka and Hipolito Carraro Jr * * This file is part of the Extended Module Player and is distributed * under the terms of the GNU General Public License. See doc/COPYING * for more information. */ #define NOT_IMPLEMENTED #define DO_TONEPORTA() { \ if (note-- && note < 0x60 && (uint32)xc->ins < xxh->ins) \ xc->s_end = note_to_period (note + XXI[XXIM.ins[note]].xpo + \ XXIM.xpo[note] /*, XXI[XXIM.ins[note]].fin*/, \ xxh->flg & XXM_FLG_LINEAR); \ xc->s_sgn = xc->period < xc->s_end ? 1 : -1; \ } /* Values for multi-retrig */ static struct retrig_t rval[] = { { 0, 1, 1 }, { -1, 1, 1 }, { -2, 1, 1 }, { -4, 1, 1 }, { -8, 1, 1 }, { -16, 1, 1 }, { 0, 2, 3 }, { 0, 1, 2 }, { 0, 1, 1 }, { 1, 1, 1 }, { 2, 1, 1 }, { 4, 1, 1 }, { 8, 1, 1 }, { 16, 1, 1 }, { 0, 3, 2 }, { 0, 2, 1 }, { 0, 0, 1 } /* Note cut */ }; /* * gotos are wonderful if you know what you're doing */ void process_fx (int chn, uint8 note, uint8 fxt, uint8 fxp, struct xmp_channel *xc) { int h, l; switch (fxt) { case FX_ARPEGGIO: if (!fxp) break; xc->a_val[1] = 100 * MSN (fxp); xc->a_val[2] = 100 * LSN (fxp); break; case FX_PORTA_UP: /* Portamento up */ fx_porta_up: if (xmp_ctl->fetch & XMP_CTL_FINEFX) { switch (MSN (fxp)) { case 0xf: xc->porta = fxp; fxp &= 0x0f; goto ex_f_porta_up; case 0xe: xc->porta = fxp; fxp &= 0x0e; fxp |= 0x10; goto fx_xf_porta; } if (!fxp) { if ((fxp = xc->porta) != 0) goto fx_porta_up; } } SET (PITCHBEND); if ((xc->porta = fxp) != 0) xc->f_val = -fxp; else if (xc->f_val > 0) xc->f_val *= -1; break; case FX_PORTA_DN: /* Portamento down */ fx_porta_dn: if (xmp_ctl->fetch & XMP_CTL_FINEFX) { switch (MSN (fxp)) { case 0xf: xc->porta = fxp; fxp &= 0x0f; goto ex_f_porta_dn; case 0xe: xc->porta = fxp; fxp &= 0x0e; fxp |= 0x20; goto fx_xf_porta; } if (!fxp) { if ((fxp = xc->porta) != 0) goto fx_porta_dn; } } SET (PITCHBEND); if ((xc->porta = fxp) != 0) xc->f_val = fxp; else if (xc->f_val < 0) xc->f_val *= -1; break; case FX_TONEPORTA: /* Tone portamento */ if (!TEST (IS_VALID)) break; DO_TONEPORTA (); if (fxp) xc->s_val = fxp; SET (TONEPORTA); break; case FX_VIBRATO: /* Vibrato */ SET (VIBRATO); if (LSN (fxp)) xc->y_depth = LSN (fxp); if (MSN (fxp)) xc->y_rate = MSN (fxp); break; case FX_TONE_VSLIDE: /* Toneporta + vol slide */ if (!TEST (IS_VALID)) break; DO_TONEPORTA (); SET (TONEPORTA); goto fx_volslide; case FX_VIBRA_VSLIDE: /* Vibrato + vol slide */ SET (VIBRATO); goto fx_volslide; case FX_TREMOLO: /* Tremolo */ SET (TREMOLO); if (MSN (fxp)) xc->t_rate = MSN (fxp); if (LSN (fxp)) xc->t_depth = LSN (fxp); break; case FX_SETPAN: /* Set pan */ SET (NEW_PAN); xc->pan = fxp; break; case FX_OFFSET: /* Set sample offset */ SET (OFFSET); if (fxp) xc->offset = fxp << 8; break; case FX_VOLSLIDE: /* Volume slide */ fx_volslide: if (xmp_ctl->fetch & XMP_CTL_FINEFX) { h = MSN (fxp); l = LSN (fxp); if (h == 0xf && l != 0) { xc->volslide = fxp; fxp &= 0x0f; goto ex_f_vslide_dn; } else if (h == 0xe && l != 0) { xc->volslide = fxp; fxp &= 0x0f; goto ex_f_vslide_dn; /* FIXME */ } else if (l == 0xf && h != 0) { xc->volslide = fxp; fxp >>= 4; goto ex_f_vslide_up; } else if (l == 0xe && h != 0) { xc->volslide = fxp; fxp >>= 4; goto ex_f_vslide_up; /* FIXME */ } else if (!fxp) { if ((fxp = xc->volslide) != 0) goto fx_volslide; } } SET (VOL_SLIDE); if ((xc->volslide = fxp)) xc->v_val = MSN (fxp) - LSN (fxp); break; case FX_VOLSLIDE_2: /* Secondary volume slide */ SET (VOL_SLIDE_2); if (fxp) xc->v_val2 = MSN (fxp) - LSN (fxp); break; case FX_VOLSLIDE_UP: /* Vol slide with uint8 arg */ xc->v_val = fxp; SET (VOL_SLIDE); break; case FX_VOLSLIDE_DN: /* Vol slide with uint8 arg */ xc->v_val = -fxp; SET (VOL_SLIDE); break; case FX_F_VSLIDE: /* Fine volume slide */ SET (FINE_VOLS); if ((xc->fvolslide = fxp)) xc->v_fval = MSN (fxp) - LSN (fxp); break; case FX_JUMP: /* Order jump */ flow.pbreak = 1; flow.jump = fxp; break; case FX_VOLSET: /* Volume set */ RESET (RESET_VOL); SET (NEW_VOL); xc->volume = fxp; break; case FX_BREAK: /* Pattern break */ flow.pbreak = 1; flow.jumpline = 10 * MSN (fxp) + LSN (fxp); break; case FX_EXTENDED: /* Extended effect */ fxt = fxp >> 4; fxp &= 0x0f; switch (fxt) { case EX_F_PORTA_UP: /* Fine portamento up */ ex_f_porta_up: SET (FINE_BEND); if (fxp) xc->f_fval = -fxp * 4; else if (xc->f_val > 0) xc->f_val *= -1; break; case EX_F_PORTA_DN: /* Fine portamento down */ ex_f_porta_dn: SET (FINE_BEND); if (fxp) xc->f_fval = fxp * 4; else if (xc->f_val < 0) xc->f_val *= -1; break; case EX_GLISS: /* Glissando toggle */ xc->gliss = fxp; break; case EX_VIBRATO_WF: /* Set vibrato waveform */ xc->y_type = fxp & 3; break; case EX_FINETUNE: /* Set finetune */ fxp <<= 4; goto fx_finetune; case EX_PATTERN_LOOP: /* Loop pattern */ if (fxp) { if (flow.loop_stack[chn]) { if (--flow.loop_stack[chn]) flow.loop_chn = ++chn; /* #?# **** FIXME **** */ else if (xmp_ctl->fetch & XMP_CTL_S3MLOOP) flow.loop_row[chn] = flow.row_cnt + 1; } else if (flow.loop_row[chn] <= flow.row_cnt) { flow.loop_stack[chn] = fxp; flow.loop_chn = ++chn; } } else flow.loop_row[chn] = flow.row_cnt; break; case EX_TREMOLO_WF: /* Set tremolo waveform */ xc->t_type = fxp & 3; break; case EX_RETRIG: /* Retrig note */ xc->retrig = xc->rcount = fxp ? fxp + 1 : xc->rval; xc->rval = xc->retrig; xc->rtype = 0; break; case EX_F_VSLIDE_UP: /* Fine volume slide up */ ex_f_vslide_up: SET (FINE_VOLS); if (fxp) xc->v_fval = fxp; break; case EX_F_VSLIDE_DN: /* Fine volume slide down */ ex_f_vslide_dn: SET (FINE_VOLS); if (fxp) xc->v_fval = -fxp; break; case EX_CUT: /* Cut note */ xc->retrig = xc->rcount = fxp + 1; xc->rtype = 0x10; break; case EX_DELAY: /* Note delay */ xc->delay = fxp + 1; break; case EX_PATT_DELAY: /* Pattern delay */ flow.delay = fxp; break; } break; case FX_TEMPO: /* Set tempo */ if (fxp) { if (fxp <= 0x20) tempo = fxp; else tick_time = xmp_ctl->rrate / (xmp_bpm = fxp); } break; case FX_S3M_TEMPO: if (fxp) tempo = fxp; break; case FX_GLOBALVOL: /* Set global volume */ xmp_ctl->volume = fxp > xmp_ctl->volbase ? xmp_ctl->volbase : fxp; break; case FX_G_VOLSLIDE: /* Global volume slide */ gvol_flag = 1; if (xmp_ctl->fetch & XMP_CTL_FINEFX) { h = MSN (fxp); l = LSN (fxp); if (h == 0xf && l != 0) { fxp = 0x01; /* FIXME: file global vslide */ } else if (l == 0xf && h != 0) { fxp = 0x10; /* FIXME: file global vslide */ } } if (fxp) gvol_slide = MSN (fxp) - LSN (fxp); break; case FX_KEYOFF: /* Key off */ xc->keyoff = fxp; break; case FX_ENVPOS: /* Set envelope position */ NOT_IMPLEMENTED; break; case FX_MASTER_PAN: /* Set master pan */ xc->masterpan = fxp; break; case FX_PANSLIDE: /* Pan slide */ SET (PAN_SLIDE); if (fxp) xc->p_val = MSN (fxp) - LSN (fxp); break; case FX_MULTI_RETRIG: /* Multi retrig */ xc->retrig = xc->rcount = LSN (fxp) ? LSN (fxp) + 1 : xc->rval; xc->rval = xc->retrig; xc->rtype = MSN (fxp); break; case FX_TREMOR: /* Tremor */ xc->tremor = fxp; xc->tcnt_up = MSN (fxp); xc->tcnt_dn = -1; break; case FX_XF_PORTA: /* Extra fine portamento */ fx_xf_porta: SET (FINE_BEND); switch (MSN (fxp)) { case 1: xc->f_fval = -LSN (fxp); break; case 2: xc->f_fval = LSN (fxp); break; } break; case FX_TRK_VOL: /* Track volume setting */ if (fxp <= xmp_ctl->volbase) xc->mastervol = fxp; break; case FX_TRK_VSLIDE: /* Track volume slide */ fx_trk_vslide: if (xmp_ctl->fetch & XMP_CTL_FINEFX) { h = MSN (fxp); l = LSN (fxp); if (h == 0xf && l != 0) { xc->trkvsld = fxp; fxp &= 0x0f; goto fx_trk_fvslide; } else if (h == 0xe && l != 0) { xc->trkvsld = fxp; fxp &= 0x0f; goto fx_trk_fvslide; /* FIXME */ } else if (l == 0xf && h != 0) { xc->trkvsld = fxp; fxp &= 0xf0; goto fx_trk_fvslide; } else if (l == 0xe && h != 0) { xc->trkvsld = fxp; fxp &= 0xf0; goto fx_trk_fvslide; /* FIXME */ } else if (!fxp) { if ((fxp = xc->trkvsld) != 0) goto fx_trk_vslide; } } SET (TRK_VSLIDE); if ((xc->trkvsld = fxp)) xc->trk_val = MSN (fxp) - LSN (fxp); break; case FX_TRK_FVSLIDE: /* Track fine volume slide */ fx_trk_fvslide: SET (TRK_FVSLIDE); if (fxp) xc->trk_fval = MSN (fxp) - LSN (fxp); break; case FX_FINETUNE: fx_finetune: SET (FINETUNE); xc->finetune = (int16)(fxp - 0x80); break; case FX_IT_INSTFUNC: switch (fxp) { case 0: /* Past note cut */ xmp_drv_pastnote (chn, XXM_NNA_CUT); break; case 1: /* Past note off */ xmp_drv_pastnote (chn, XXM_NNA_OFF); break; case 2: /* Past note fade */ xmp_drv_pastnote (chn, XXM_NNA_FADE); break; case 3: /* Set NNA to note cut */ xmp_drv_setnna (chn, XXM_NNA_CUT); break; case 4: /* Set NNA to continue */ xmp_drv_setnna (chn, XXM_NNA_CONT); break; case 5: /* Set NNA to note off */ xmp_drv_setnna (chn, XXM_NNA_OFF); break; case 6: /* Set NNA to note fade */ xmp_drv_setnna (chn, XXM_NNA_FADE); break; case 7: /* Turn off volume envelope */ break; case 8: /* Turn on volume envelope */ break; } break; case FX_FLT_CUTOFF: xc->cutoff = fxp; break; case FX_FLT_RESN: xc->resonance = fxp; break; case FX_CHORUS: xxc[chn].cho = fxp; break; case FX_REVERB: xxc[chn].rvb = fxp; break; } }