]> 4ch.mooo.com Git - 16.git/blobdiff - 16/ADT2PLAY/a2player.pas
clear
[16.git] / 16 / ADT2PLAY / a2player.pas
diff --git a/16/ADT2PLAY/a2player.pas b/16/ADT2PLAY/a2player.pas
deleted file mode 100755 (executable)
index caed7ab..0000000
+++ /dev/null
@@ -1,4590 +0,0 @@
-unit A2player;
-interface
-
-const
-  MAX_IRQ_FREQ = 1000;
-
-{$i typconst.inc}
-
-const
-  ef_Arpeggio          = 0;
-  ef_FSlideUp          = 1;
-  ef_FSlideDown        = 2;
-  ef_TonePortamento    = 3;
-  ef_Vibrato           = 4;
-  ef_TPortamVolSlide   = 5;
-  ef_VibratoVolSlide   = 6;
-  ef_FSlideUpFine      = 7;
-  ef_FSlideDownFine    = 8;
-  ef_SetModulatorVol   = 9;
-  ef_VolSlide          = 10;
-  ef_PositionJump      = 11;
-  ef_SetInsVolume      = 12;
-  ef_PatternBreak      = 13;
-  ef_SetTempo          = 14;
-  ef_SetSpeed          = 15;
-  ef_TPortamVSlideFine = 16;
-  ef_VibratoVSlideFine = 17;
-  ef_SetCarrierVol     = 18;
-  ef_SetWaveform       = 19;
-  ef_VolSlideFine      = 20;
-  ef_RetrigNote        = 21;
-  ef_Tremolo           = 22;
-  ef_Tremor            = 23;
-  ef_ArpggVSlide       = 24;
-  ef_ArpggVSlideFine   = 25;
-  ef_MultiRetrigNote   = 26;
-  ef_FSlideUpVSlide    = 27;
-  ef_FSlideDownVSlide  = 28;
-  ef_FSlUpFineVSlide   = 29;
-  ef_FSlDownFineVSlide = 30;
-  ef_FSlUpVSlF         = 31;
-  ef_FSlDownVSlF       = 32;
-  ef_FSlUpFineVSlF     = 33;
-  ef_FSlDownFineVSlF   = 34;
-  ef_Extended          = 35;
-  ef_Extended2         = 36;
-  ef_SetGlobalVolume   = 37;
-  ef_SwapArpeggio      = 38;
-  ef_SwapVibrato       = 39;
-  ef_ForceInsVolume    = 40;
-  ef_Extended3         = 41;
-  ef_ExtraFineArpeggio = 42;
-  ef_ExtraFineVibrato  = 43;
-  ef_ExtraFineTremolo  = 44;
-  ef_SetCustomSpeedTab = 45;
-  ef_GlobalFSlideUp    = 46;
-  ef_GlobalFSlideDown  = 47;
-  ef_ex_SetTremDepth   = 0;
-  ef_ex_SetVibDepth    = 1;
-  ef_ex_SetAttckRateM  = 2;
-  ef_ex_SetDecayRateM  = 3;
-  ef_ex_SetSustnLevelM = 4;
-  ef_ex_SetRelRateM    = 5;
-  ef_ex_SetAttckRateC  = 6;
-  ef_ex_SetDecayRateC  = 7;
-  ef_ex_SetSustnLevelC = 8;
-  ef_ex_SetRelRateC    = 9;
-  ef_ex_SetFeedback    = 10;
-  ef_ex_SetPanningPos  = 11;
-  ef_ex_PatternLoop    = 12;
-  ef_ex_PatternLoopRec = 13;
-  ef_ex_MacroKOffLoop  = 14;
-  ef_ex_ExtendedCmd    = 15;
-  ef_ex_cmd_RSS        = 0;
-  ef_ex_cmd_ResetVol   = 1;
-  ef_ex_cmd_LockVol    = 2;
-  ef_ex_cmd_UnlockVol  = 3;
-  ef_ex_cmd_LockVP     = 4;
-  ef_ex_cmd_UnlockVP   = 5;
-  ef_ex_cmd_VSlide_mod = 6;
-  ef_ex_cmd_VSlide_car = 7;
-  ef_ex_cmd_VSlide_def = 8;
-  ef_ex_cmd_LockPan    = 9;
-  ef_ex_cmd_UnlockPan  = 10;
-  ef_ex_cmd_VibrOff    = 11;
-  ef_ex_cmd_TremOff    = 12;
-  ef_ex_cmd_FVib_FGFS  = 13;
-  ef_ex_cmd_FTrm_XFGFS = 14;
-  ef_ex_cmd_NoRestart  = 15;
-  ef_ex2_PatDelayFrame = 0;
-  ef_ex2_PatDelayRow   = 1;
-  ef_ex2_NoteDelay     = 2;
-  ef_ex2_NoteCut       = 3;
-  ef_ex2_FineTuneUp    = 4;
-  ef_ex2_FineTuneDown  = 5;
-  ef_ex2_GlVolSlideUp  = 6;
-  ef_ex2_GlVolSlideDn  = 7;
-  ef_ex2_GlVolSlideUpF = 8;
-  ef_ex2_GlVolSlideDnF = 9;
-  ef_ex2_GlVolSldUpXF  = 10;
-  ef_ex2_GlVolSldDnXF  = 11;
-  ef_ex2_VolSlideUpXF  = 12;
-  ef_ex2_VolSlideDnXF  = 13;
-  ef_ex2_FreqSlideUpXF = 14;
-  ef_ex2_FreqSlideDnXF = 15;
-  ef_ex3_SetConnection = 0;
-  ef_ex3_SetMultipM    = 1;
-  ef_ex3_SetKslM       = 2;
-  ef_ex3_SetTremoloM   = 3;
-  ef_ex3_SetVibratoM   = 4;
-  ef_ex3_SetKsrM       = 5;
-  ef_ex3_SetSustainM   = 6;
-  ef_ex3_SetMultipC    = 7;
-  ef_ex3_SetKslC       = 8;
-  ef_ex3_SetTremoloC   = 9;
-  ef_ex3_SetVibratoC   = 10;
-  ef_ex3_SetKsrC       = 11;
-  ef_ex3_SetSustainC   = 12;
-
-const
-  ef_fix1 = $80;
-  ef_fix2 = $90;
-
-const
-  opl3port: Word = $388;
-  error_code: Integer = 0;
-  current_order: Byte = 0;
-  current_pattern: Byte = 0;
-  current_line: Byte = 0;
-  tempo: Byte = 50;
-  speed: Byte = 6;
-  macro_speedup: Word = 1;
-  irq_mode: Boolean = FALSE;
-  max_patterns: Byte = 128;
-  fast_forward: Boolean = FALSE;
-  overall_volume: Byte = 63;
-  global_volume: Byte = 63;
-
-const
-  song_timer: Word = 0;
-  song_timer_tenths: Word = 0;
-
-var
-  timer_temp,timer_det: Word;
-  ticks,tick0,tickD,
-  tickXF: Longint;
-  limit_exceeded: Boolean;
-
-type
-  tFM_INST_DATA = Record
-                    AM_VIB_EG_modulator,
-                    AM_VIB_EG_carrier,
-                    KSL_VOLUM_modulator,
-                    KSL_VOLUM_carrier,
-                    ATTCK_DEC_modulator,
-                    ATTCK_DEC_carrier,
-                    SUSTN_REL_modulator,
-                    SUSTN_REL_carrier,
-                    WAVEFORM_modulator,
-                    WAVEFORM_carrier,
-                    FEEDBACK_FM: Byte;
-                  end;
-type
-  tADTRACK2_INS = Record
-                    fm_data: tFM_INST_DATA;
-                    panning: Byte;
-                    fine_tune: Shortint;
-                    perc_voice: Byte;
-                  end;
-type
-  tARPEGGIO_TABLE = Record
-                      length,
-                      speed,
-                      loop_begin,
-                      loop_length,
-                      keyoff_pos: Byte;
-                      data: array[1..255] of Byte;
-                    end;
-type
-  tVIBRATO_TABLE = Record
-                     length,
-                     speed,
-                     delay,
-                     loop_begin,
-                     loop_length,
-                     keyoff_pos: Byte;
-                     data: array[1..255] of Shortint;
-                   end;
-type
-  tREGISTER_TABLE_DEF = Record
-                          fm_data: tFM_INST_DATA;
-                          freq_slide: Smallint;
-                          panning: Byte;
-                          duration: Byte;
-                        end;
-type
-  tREGISTER_TABLE = Record
-                      length,
-                      loop_begin,
-                      loop_length,
-                      keyoff_pos,
-                      arpeggio_table,
-                      vibrato_table: Byte;
-                      data: array[1..255] of tREGISTER_TABLE_DEF;
-                    end;
-type
-  tMACRO_TABLE = Record
-                   arpeggio: tARPEGGIO_TABLE;
-                   vibrato:  tVIBRATO_TABLE;
-                 end;
-type
-  tFM_PARAMETER_TABLE = Record
-                          adsrw_car,
-                          adsrw_mod: Record
-                                       attck,dec,sustn,rel,
-                                       wform: Byte;
-                                     end;
-                          connect,
-                          feedb,
-                          multipM,kslM,tremM,vibrM,ksrM,sustM,
-                          multipC,kslC,tremC,vibrC,ksrC,sustC: Byte;
-                        end;
-type
-  tADTRACK2_EVENT = Record
-                      note,
-                      instr_def,
-                      effect_def,
-                      effect,
-                      effect_def2,
-                      effect2: Byte;
-                    end;
-
-type
-  tDIS_FMREG_COL = array[0..27] of Boolean;
-
-type
-  tFIXED_SONGDATA = Record
-                      songname:      String[42];
-                      composer:      String[42];
-                      instr_names:   array[1..255] of String[42];
-                      instr_data:    array[1..255] of tADTRACK2_INS;
-                      instr_macros:  array[1..255] of tREGISTER_TABLE;
-                      macro_table:   array[1..255] of tMACRO_TABLE;
-                      pattern_order: array[0..$7f] of Byte;
-                      tempo:         Byte;
-                      speed:         Byte;
-                      common_flag:   Byte;
-                      patt_len:      Word;
-                      nm_tracks:     Byte;
-                      macro_speedup: Word;
-                      flag_4op:      Byte;
-                      lock_flags:    array[1..20]  of Byte;
-                      pattern_names: array[0..$7f] of String[42];
-                      dis_fmreg_col: array[1..255] of tDIS_FMREG_COL;
-                    end;
-type
-  tPLAY_STATUS = (isPlaying,isPaused,isStopped);
-
-type
-  tVARIABLE_DATA = array[0..7]    of
-                   array[1..20]   of
-                   array[0..$0ff] of tADTRACK2_EVENT;
-type
-  tPATTERN_DATA = array[0..15] of tVARIABLE_DATA;
-
-type
-  tDUMMY_BUFF = array[0..PRED(655350)] of Byte;
-
-type
-  tOLD_ADTRACK2_INS = Record
-                        fm_data: tFM_INST_DATA;
-                        panning: Byte;
-                        fine_tune: Shortint;
-                      end;
-type
-  pOLD_FIXED_SONGDATA = ^tOLD_FIXED_SONGDATA;
-  tOLD_FIXED_SONGDATA = Record
-                          songname:      String[42];
-                          composer:      String[42];
-                          instr_names:   array[1..250] of String[32];
-                          instr_data:    array[1..250] of tOLD_ADTRACK2_INS;
-                          pattern_order: array[0..$7f] of Byte;
-                          tempo:         Byte;
-                          speed:         Byte;
-                          common_flag:   Byte;
-                        end;
-type
-  tOLD_CHUNK = Record
-                 note:       Byte;
-                 instr_def:  Byte;
-                 effect_def: Byte;
-                 effect:     Byte;
-               end;
-type
-  tCHUNK = tADTRACK2_EVENT;
-
-type
-  tOLD_VARIABLE_DATA1 = array[0..$0f] of array[0..$3f] of
-                        array[1..9]   of tOLD_CHUNK;
-type
-  tOLD_VARIABLE_DATA2 = array[0..7]   of array[1..18] of
-                        array[0..$3f] of tOLD_CHUNK;
-type
-  tByteSet = Set of Byte;
-
-const
-  INSTRUMENT_SIZE = SizeOf(tADTRACK2_INS);
-  CHUNK_SIZE = SizeOf(tCHUNK);
-  PATTERN_SIZE = 20*256*CHUNK_SIZE;
-
-var
-  time_playing: Real;
-  pattdata: ^tPATTERN_DATA;
-  songdata: tFIXED_SONGDATA;
-  old_songdata: tOLD_FIXED_SONGDATA;
-  old_hash_buffer: tOLD_VARIABLE_DATA1;
-  hash_buffer: tOLD_VARIABLE_DATA2;
-  buffer: array[0..PRED(SizeOf(tVARIABLE_DATA))] of Byte;
-
-const
-  external_irq_hook: procedure = NIL;
-  _delay_counter: Longint = 0;
-  irq_freq: Word = 50;
-  irq_initialized: Boolean = FALSE;
-  timer_fix: Boolean = TRUE;
-  pattern_break: Boolean = FALSE;
-  pattern_delay: Boolean = FALSE;
-  next_line: Byte = 0;
-  play_status: tPLAY_STATUS = isStopped;
-  replay_forbidden: Boolean = TRUE;
-  force_macro_keyon: Boolean = FALSE;
-
-type
-  tDECAY_BAR = Record
-                  dir: Integer;
-                  lvl,max_lvl: Real;
-                end;
-var
-  decay_bar: array[1..96] of tDECAY_BAR;
-
-procedure start_playing;
-procedure set_overall_volume(level: Byte);
-procedure stop_playing;
-procedure init_old_songdata;
-procedure init_songdata;
-procedure init_irq;
-procedure done_irq;
-procedure get_chunk(pattern,line,channel: Byte; var chunk: tADTRACK2_EVENT);
-procedure put_chunk(pattern,line,channel: Byte; chunk: tADTRACK2_EVENT);
-procedure count_order(var entries: Byte);
-procedure timer_poll_proc;
-procedure opl3exp(data: Word);
-
-function  calc_following_order(order: Byte): Integer;
-function  asciiz_string(str: String): String;
-
-implementation
-uses DOS,TimerInt,ParserIO;
-
-const
-  _panning: array[0..2] of Byte = ($30,$10,$20);
-
-const
-  _instr:  array[0..11] of Byte = ($20, $20,
-                                   $40, $40,
-                                   $60, $60,
-                                   $80, $80,
-                                   $0e0,$0e0,
-                                   $0c0,
-                                   $0bd);
-type
-  tTRACK_ADDR = array[1..20] of Word;
-
-const                    { 01 - 02 - 03 - 04 - 05 - 06 - 07 - 08 - 09 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 }
-  _chmm_n: tTRACK_ADDR = ($003,$000,$004,$001,$005,$002,$006,$007,$008,$103,$100,$104,$101,$105,$102,$106,$107,$108,BYTE_NULL,BYTE_NULL);
-  _chmm_m: tTRACK_ADDR = ($008,$000,$009,$001,$00a,$002,$010,$011,$012,$108,$100,$109,$101,$10a,$102,$110,$111,$112,BYTE_NULL,BYTE_NULL);
-  _chmm_c: tTRACK_ADDR = ($00b,$003,$00c,$004,$00d,$005,$013,$014,$015,$10b,$103,$10c,$104,$10d,$105,$113,$114,$115,BYTE_NULL,BYTE_NULL);
-                         {                                                                            BD   SD   TT   TC   HH }
-  _chpm_n: tTRACK_ADDR = ($003,$000,$004,$001,$005,$002,$106,$107,$108,$103,$100,$104,$101,$105,$102,$006,$007,$008,$008,$007);
-  _chpm_m: tTRACK_ADDR = ($008,$000,$009,$001,$00a,$002,$110,$111,$112,$108,$100,$109,$101,$10a,$102,$010,$014,$012,$015,$011);
-  _chpm_c: tTRACK_ADDR = ($00b,$003,$00c,$004,$00d,$005,$113,$114,$115,$10b,$103,$10c,$104,$10d,$105,$013,BYTE_NULL,BYTE_NULL,BYTE_NULL,BYTE_NULL);
-
-var
-  _chan_n: tTRACK_ADDR;
-  _chan_m: tTRACK_ADDR;
-  _chan_c: tTRACK_ADDR;
-
-const
-  keyoff_flag        = $080;
-  fixed_note_flag    = $090;
-  pattern_loop_flag  = $0e0;
-  pattern_break_flag = $0f0;
-
-const
-  def_vibtrem_speed_factor: Byte = 1;
-  def_vibtrem_table_size: Byte = 32;
-  def_vibtrem_table: array[0..255] of Byte = (
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
-    0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
-    253,250,244,235,224,212,197,180,161,141,120,97,74,49,24);
-
-var
-  vibtrem_speed_factor: Byte;
-  vibtrem_table_size: Byte;
-  vibtrem_table: array[0..255] of Byte;
-
-var
-  fmpar_table:   array[1..20] of tFM_PARAMETER_TABLE;
-  volume_lock:   array[1..20] of Boolean;
-  volume_table:  array[1..20] of Word;
-  vscale_table:  array[1..20] of Word;
-  peak_lock:     array[1..20] of Boolean;
-  pan_lock:      array[1..20] of Boolean;
-  event_table:   array[1..20] of tADTRACK2_EVENT;
-  voice_table:   array[1..20] of Byte;
-  modulator_vol: array[1..20] of Byte;
-  carrier_vol:   array[1..20] of Byte;
-  freq_table:    array[1..20] of Word;
-  effect_table:  array[1..20] of Word;
-  effect_table2: array[1..20] of Word;
-  fslide_table:  array[1..20] of Byte;
-  fslide_table2: array[1..20] of Byte;
-  glfsld_table:  array[1..20] of Word;
-  glfsld_table2: array[1..20] of Word;
-  porta_table:   array[1..20] of Record freq: Word; speed: Byte; end;
-  porta_table2:  array[1..20] of Record freq: Word; speed: Byte; end;
-  arpgg_table:   array[1..20] of Record state,note,add1,add2: Byte; end;
-  arpgg_table2:  array[1..20] of Record state,note,add1,add2: Byte; end;
-  vibr_table:    array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
-  vibr_table2:   array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
-  trem_table:    array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
-  trem_table2:   array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
-  retrig_table:  array[1..20] of Byte;
-  retrig_table2: array[1..20] of Byte;
-  tremor_table:  array[1..20] of Record pos: Integer; volume: Word; end;
-  tremor_table2: array[1..20] of Record pos: Integer; volume: Word; end;
-  panning_table: array[1..20] of Byte;
-  last_effect:   array[1..20] of Word;
-  last_effect2:  array[1..20] of Word;
-  volslide_type: array[1..20] of Byte;
-  event_new:     array[1..20] of Boolean;
-  notedel_table: array[1..20] of Byte;
-  notecut_table: array[1..20] of Byte;
-  ftune_table:   array[1..20] of Shortint;
-  keyoff_loop:   array[1..20] of Boolean;
-  macro_table:   array[1..20] of Record
-                                   fmreg_pos,arpg_pos,vib_pos: Word;
-                                   fmreg_count,fmreg_duration,arpg_count,
-                                   vib_count,vib_delay: Byte;
-                                   vib_paused: Boolean;
-                                   fmreg_table,arpg_table,vib_table: Byte;
-                                   arpg_note: Byte;
-                                   vib_freq: Word;
-                                 end;
-
-  loopbck_table: array[1..20] of Byte;
-  loop_table:    array[1..20,0..255] of Byte;
-  misc_register: Byte;
-
-const
-  current_tremolo_depth: Byte = 0;
-  current_vibrato_depth: Byte = 0;
-
-var
-  speed_update,lockvol,panlock,lockVP: Boolean;
-  tremolo_depth,vibrato_depth: Byte;
-  volume_scaling,percussion_mode: Boolean;
-  last_order: Byte;
-  reset_chan: array[1..20] of Boolean;
-
-procedure opl2out(reg,data: Word); assembler;
-asm
-        mov     ax,reg
-        mov     dx,word ptr [opl3port]
-        or      ah,ah
-        jz      @@1
-        add     dx,2
-@@1:    out     dx,al
-        mov     ecx,6
-@@2:    in      al,dx
-        loop    @@2
-        inc     dl
-        mov     ax,data
-        out     dx,al
-        dec     dl
-        mov     ecx,36
-@@3:    in      al,dx
-        loop    @@3
-end;
-
-procedure opl3out(reg,data: Word); assembler;
-asm
-        mov     ax,reg
-        mov     dx,word ptr [opl3port]
-        or      ah,ah
-        jz      @@1
-        add     dx,2
-@@1:    out     dx,al
-        inc     dl
-        mov     ax,data
-        out     dx,al
-        dec     dl
-        mov     ecx,26
-@@2:    in      al,dx
-        loop    @@2
-end;
-
-procedure opl3exp(data: Word); assembler;
-asm
-        mov     ax,data
-        mov     dx,word ptr [opl3port]
-        add     dx,2
-        out     dx,al
-        mov     ecx,6
-@@1:    in      al,dx
-        loop    @@1
-        inc     dl
-        mov     al,ah
-        out     dx,al
-        mov     ecx,36
-@@2:    in      al,dx
-        loop    @@2
-end;
-
-const
-  FreqStart = $156;
-  FreqEnd   = $2ae;
-  FreqRange = FreqEnd-FreqStart;
-
-function nFreq(note: Byte): Word; assembler;
-
-const
-  Fnum: array[0..11] of Word = (
-    $157,$16b,$181,$198,$1b0,$1ca,$1e5,$202,$220,$241,$263,$287);
-
-asm
-        push    ebx
-        push    ecx
-        xor     ebx,ebx
-        mov     al,[note]
-        xor     ah,ah
-        cmp     ax,12*8
-        jae     @@1
-        push    eax
-        mov     bl,12
-        div     bl
-        mov     bl,ah
-        xor     bh,bh
-        shl     bx,1
-        pop     eax
-        mov     cl,12
-        div     cl
-        xor     ah,ah
-        shl     ax,10
-        add     ax,word ptr [Fnum+ebx]
-        jmp     @@2
-@@1:    mov     ax,7
-        shl     ax,10
-        add     ax,FreqEnd
-@@2:    pop     ecx
-        pop     ebx
-end;
-
-function calc_freq_shift_up(freq,shift: Word): Word; assembler;
-asm
-        push    ebx
-        push    ecx
-        push    edx
-        mov     cx,freq
-        mov     ax,shift
-        mov     bx,cx
-        and     bx,0000001111111111b
-        mov     dx,cx
-        and     dx,0001110000000000b
-        add     bx,ax
-        and     cx,1110000000000000b
-        shr     dx,10
-        cmp     bx,FreqEnd
-        jb      @@2
-        cmp     dx,7
-        jnz     @@1
-        mov     bx,FreqEnd
-        jmp     @@2
-@@1:    sub     bx,FreqRange
-        inc     dx
-@@2:    mov     ax,cx
-        shl     dx,10
-        add     ax,dx
-        add     ax,bx
-        pop     edx
-        pop     ecx
-        pop     ebx
-end;
-
-function calc_freq_shift_down(freq,shift: Word): Word; assembler;
-asm
-        push    ebx
-        push    ecx
-        push    edx
-        mov     cx,freq
-        mov     ax,shift
-        mov     bx,cx
-        and     bx,0000001111111111b
-        mov     dx,cx
-        and     dx,0001110000000000b
-        sub     bx,ax
-        and     cx,1110000000000000b
-        shr     dx,10
-        cmp     bx,FreqStart
-        ja      @@2
-        or      dx,dx
-        jnz     @@1
-        mov     bx,FreqStart
-        jmp     @@2
-@@1:    add     bx,FreqRange
-        dec     dx
-@@2:    mov     ax,cx
-        shl     dx,10
-        add     ax,dx
-        add     ax,bx
-        pop     edx
-        pop     ecx
-        pop     ebx
-end;
-
-function calc_vibtrem_shift(depth,position: Byte;
-                            var direction: Byte): Word; assembler;
-asm
-        push    ebx
-        push    ecx
-        push    edx
-        push    edi
-        xor     ebx,ebx
-        mov     al,depth
-        xor     ah,ah
-        mov     bl,position
-        xor     bh,bh
-        mov     dh,bl
-        mov     cl,vibtrem_table_size
-        dec     cl
-        and     bl,cl
-        lea     edi,[vibtrem_table]
-        add     edi,ebx
-        mov     dl,byte ptr [edi]
-        mul     dl
-        rol     ax,1
-        xchg    ah,al
-        and     ah,1
-        mov     ebx,[direction]
-        mov     cl,1
-        mov     [ebx],cl
-        mov     dl,vibtrem_table_size
-        test    dh,dl
-        jne     @@1
-        mov     cl,0
-        mov     [ebx],cl
-@@1:    pop     edi
-        pop     edx
-        pop     ecx
-        pop     ebx
-end;
-
-procedure change_freq(chan: Byte; freq: Word); assembler;
-asm
-        push    ebx
-        push    edx
-        xor     ebx,ebx
-        mov     bl,chan
-        dec     ebx
-        shl     ebx,1
-        mov     ax,freq
-        and     ax,1fffh
-        mov     dx,word ptr [freq_table+ebx]
-        and     dx,NOT 1fffh
-        add     ax,dx
-        mov     word ptr [freq_table+ebx],ax
-        xor     edx,edx
-        mov     dx,word ptr [_chan_n+ebx]
-        add     dx,0a0h
-        push    edx
-        xor     edx,edx
-        mov     dl,al
-        push    edx
-        mov     dx,word ptr [_chan_n+ebx]
-        add     dx,0b0h
-        push    edx
-        xor     edx,edx
-        mov     dl,ah
-        push    edx
-        call    opl3out
-        call    opl3out
-        pop     edx
-        pop     ebx
-end;
-
-function ins_parameter(ins,param: Byte): Byte; assembler;
-asm
-        push    ebx
-        push    esi
-        xor     ebx,ebx
-        lea     esi,[songdata.instr_data]
-        mov     bl,ins
-        dec     ebx
-        mov     eax,INSTRUMENT_SIZE
-        mul     ebx
-        add     esi,eax
-        mov     bl,param
-        add     esi,ebx
-        lodsb
-        pop     esi
-        pop     ebx
-end;
-
-function min(value: Word; minimum: Word): Word; assembler;
-asm
-        mov     ax,value
-        cmp     ax,minimum
-        jae     @@1
-        mov     ax,minimum
-@@1:
-end;
-
-function max(value: Word; maximum: Word): Word; assembler;
-asm
-        mov     ax,value
-        cmp     ax,maximum
-        jbe     @@1
-        mov     ax,maximum
-@@1:
-end;
-
-function asciiz_string(str: String): String;
-begin
-  If (Pos(#0,str) <> 0) then asciiz_string := Copy(str,1,Pos(#0,str)-1)
-  else asciiz_string := '';
-end;
-
-function concw(lo,hi: Byte): Word;
-begin
-  concw := lo+(hi SHL 8);
-end;
-
-procedure synchronize_song_timer;
-begin
-  song_timer := TRUNC(time_playing);
-  song_timer_tenths := TRUNC(time_playing*100) MOD 100;
-  timer_temp := song_timer_tenths;
-end;
-
-procedure change_frequency(chan: Byte; freq: Word);
-begin
-  macro_table[chan].vib_paused := TRUE;
-  change_freq(chan,freq);
-  macro_table[chan].vib_count := 1;
-  macro_table[chan].vib_pos := 0;
-  macro_table[chan].vib_freq := freq;
-  macro_table[chan].vib_paused := FALSE;
-end;
-
-function _macro_speedup: Word; assembler;
-asm
-        mov     ax,macro_speedup
-        or      ax,ax
-        jnz     @@1
-        inc     ax
-@@1:
-end;
-
-procedure update_timer(Hz: Longint);
-begin
-  _debug_str_ := 'A2PLAYER.PAS:update_timer';
-  If (Hz = 0) then begin TimerSetup(18); EXIT end
-  else tempo := Hz;
-  If (tempo = 18) and timer_fix then IRQ_freq := TRUNC((tempo+0.2)*20)
-  else IRQ_freq := 250;
-  While (IRQ_freq MOD (tempo*_macro_speedup) <> 0) do Inc(IRQ_freq);
-  If (IRQ_freq > MAX_IRQ_FREQ) then IRQ_freq := MAX_IRQ_FREQ;
-  TimerSetup(IRQ_freq);
-end;
-
-procedure key_off(chan: Byte);
-begin
-  freq_table[chan] := LO(freq_table[chan])+
-                     (HI(freq_table[chan]) AND NOT $20) SHL 8;
-  change_freq(chan,freq_table[chan]);
-  event_table[chan].note := event_table[chan].note OR keyoff_flag;
-end;
-
-procedure release_sustaining_sound(chan: Byte);
-begin
-  opl3out(_instr[02]+_chan_m[chan],63);
-  opl3out(_instr[03]+_chan_c[chan],63);
-
-  FillChar(fmpar_table[chan].adsrw_car,
-           SizeOf(fmpar_table[chan].adsrw_car),0);
-  FillChar(fmpar_table[chan].adsrw_mod,
-           SizeOf(fmpar_table[chan].adsrw_mod),0);
-
-  opl3out($0b0+_chan_n[chan],0);
-  opl3out(_instr[04]+_chan_m[chan],BYTE_NULL);
-  opl3out(_instr[05]+_chan_c[chan],BYTE_NULL);
-  opl3out(_instr[06]+_chan_m[chan],BYTE_NULL);
-  opl3out(_instr[07]+_chan_c[chan],BYTE_NULL);
-
-  key_off(chan);
-  event_table[chan].instr_def := 0;
-  reset_chan[chan] := TRUE;
-end;
-
-function scale_volume(volume,scale_factor: Byte): Byte;
-begin
-  scale_volume := 63-Round((63-volume)/63*
-                           (63-scale_factor));
-end;
-
-procedure set_ins_volume(modulator,carrier,chan: Byte);
-
-var
-  temp: Byte;
-
-begin
-{$IFNDEF __TMT__}
-  // ** OPL3 emulation workaround **
-  // force muted instrument volume with missing ADSR instrument data
-  // when there is additionally no FM-reg macro defined for the instrument
-  If is_ins_adsr_data_empty(voice_table[chan]) and
-     NOT (songdata.instr_macros[voice_table[chan]].length <> 0) and
-        NOT replay_forbidden then
-    begin
-      modulator := 63;
-      carrier := 63;
-    end;
-{$ENDIF}
-
-  If (modulator <> BYTE_NULL) then
-    begin
-      temp := modulator;
-      If volume_scaling then
-        If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
-           (percussion_mode and (chan in [17..20])) then
-          modulator := scale_volume(ins_parameter(voice_table[chan],2) AND $3f,modulator);
-      If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
-         (percussion_mode and (chan in [17..20])) then
-        opl3out(_instr[02]+_chan_m[chan],
-                scale_volume(scale_volume(modulator,63-global_volume),63-overall_volume)+LO(vscale_table[chan]))
-      else
-        opl3out(_instr[02]+_chan_m[chan],
-                temp+LO(vscale_table[chan]));
-      volume_table[chan] := concw(temp,HI(volume_table[chan]));
-      If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
-         (percussion_mode and (chan in [17..20])) then
-        modulator_vol[chan] := 63-scale_volume(modulator,63-global_volume)
-      else modulator_vol[chan] := 63-modulator;
-    end;
-
-  If (carrier <> BYTE_NULL) then
-    begin
-      temp := carrier;
-      If volume_scaling then
-        carrier := scale_volume(ins_parameter(voice_table[chan],3) AND $3f,carrier);
-      opl3out(_instr[03]+_chan_c[chan],
-              scale_volume(scale_volume(carrier,63-global_volume),63-overall_volume)+HI(vscale_table[chan]));
-      volume_table[chan] := concw(LO(volume_table[chan]),temp);
-      carrier_vol[chan] := 63-scale_volume(carrier,63-global_volume);
-    end;
-end;
-
-procedure reset_ins_volume(chan: Byte);
-begin
-  If NOT volume_scaling then
-    set_ins_volume(ins_parameter(voice_table[chan],2) AND $3f,
-                   ins_parameter(voice_table[chan],3) AND $3f,chan)
-  else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-         set_ins_volume(ins_parameter(voice_table[chan],2) AND $3f,0,chan)
-       else set_ins_volume(0,0,chan);
-end;
-
-procedure set_global_volume;
-
-var
-  chan: Byte;
-
-begin
-  For chan := 1 to songdata.nm_tracks do
-    If NOT ((carrier_vol[chan] = 0) and
-            (modulator_vol[chan] = 0)) then
-      If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-        set_ins_volume(BYTE_NULL,HI(volume_table[chan]),chan)
-      else set_ins_volume(LO(volume_table[chan]),HI(volume_table[chan]),chan);
-end;
-
-procedure set_overall_volume(level: Byte);
-begin
-  overall_volume := max(level,63);
-  set_global_volume;
-end;
-
-procedure init_macro_table(chan,note,ins: Byte; freq: Word);
-begin
-  macro_table[chan].fmreg_count := 1;
-  macro_table[chan].fmreg_pos := 0;
-  macro_table[chan].fmreg_duration := 0;
-  macro_table[chan].fmreg_table := ins;
-  macro_table[chan].arpg_count := 1;
-  macro_table[chan].arpg_pos := 0;
-  macro_table[chan].arpg_table := songdata.instr_macros[ins].arpeggio_table;
-  macro_table[chan].arpg_note := note;
-  macro_table[chan].vib_count := 1;
-  macro_table[chan].vib_paused := FALSE;
-  macro_table[chan].vib_pos := 0;
-  macro_table[chan].vib_table := songdata.instr_macros[ins].vibrato_table;
-  macro_table[chan].vib_freq := freq;
-  macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
-end;
-
-procedure set_ins_data(ins,chan: Byte);
-
-var
-  old_ins: Byte;
-
-begin
-  If (ins <> event_table[chan].instr_def) or reset_chan[chan] then
-    begin
-      opl3out(_instr[02]+_chan_m[chan],63);
-      opl3out(_instr[03]+_chan_c[chan],63);
-
-      If NOT pan_lock[chan] then
-        panning_table[chan] := ins_parameter(ins,11)
-      else panning_table[chan] := songdata.lock_flags[chan] AND 3;
-
-      opl3out(_instr[00]+_chan_m[chan],ins_parameter(ins,0));
-      opl3out(_instr[01]+_chan_c[chan],ins_parameter(ins,1));
-      opl3out(_instr[04]+_chan_m[chan],ins_parameter(ins,4));
-      opl3out(_instr[05]+_chan_c[chan],ins_parameter(ins,5));
-      opl3out(_instr[06]+_chan_m[chan],ins_parameter(ins,6));
-      opl3out(_instr[07]+_chan_c[chan],ins_parameter(ins,7));
-      opl3out(_instr[08]+_chan_m[chan],ins_parameter(ins,8));
-      opl3out(_instr[09]+_chan_c[chan],ins_parameter(ins,9));
-      opl3out(_instr[10]+_chan_n[chan],ins_parameter(ins,10) OR _panning[panning_table[chan]]);
-
-      fmpar_table[chan].connect := ins_parameter(ins,10) AND 1;
-      fmpar_table[chan].feedb   := ins_parameter(ins,10) SHR 1 AND 7;
-      fmpar_table[chan].multipM := ins_parameter(ins,0)  AND $0f;
-      fmpar_table[chan].kslM    := ins_parameter(ins,2)  SHR 6;
-      fmpar_table[chan].tremM   := ins_parameter(ins,0)  SHR 7;
-      fmpar_table[chan].vibrM   := ins_parameter(ins,0)  SHR 6 AND 1;
-      fmpar_table[chan].ksrM    := ins_parameter(ins,0)  SHR 4 AND 1;
-      fmpar_table[chan].sustM   := ins_parameter(ins,0)  SHR 5 AND 1;
-      fmpar_table[chan].multipC := ins_parameter(ins,1)  AND $0f;
-      fmpar_table[chan].kslC    := ins_parameter(ins,3)  SHR 6;
-      fmpar_table[chan].tremC   := ins_parameter(ins,1)  SHR 7;
-      fmpar_table[chan].vibrC   := ins_parameter(ins,1)  SHR 6 AND 1;
-      fmpar_table[chan].ksrC    := ins_parameter(ins,1)  SHR 4 AND 1;
-      fmpar_table[chan].sustC   := ins_parameter(ins,1)  SHR 5 AND 1;
-
-      fmpar_table[chan].adsrw_car.attck := ins_parameter(ins,5) SHR 4;
-      fmpar_table[chan].adsrw_mod.attck := ins_parameter(ins,4) SHR 4;
-      fmpar_table[chan].adsrw_car.dec   := ins_parameter(ins,5) AND $0f;
-      fmpar_table[chan].adsrw_mod.dec   := ins_parameter(ins,4) AND $0f;
-      fmpar_table[chan].adsrw_car.sustn := ins_parameter(ins,7) SHR 4;
-      fmpar_table[chan].adsrw_mod.sustn := ins_parameter(ins,6) SHR 4;
-      fmpar_table[chan].adsrw_car.rel   := ins_parameter(ins,7) AND $0f;
-      fmpar_table[chan].adsrw_mod.rel   := ins_parameter(ins,6) AND $0f;
-      fmpar_table[chan].adsrw_car.wform := ins_parameter(ins,9) AND $07;
-      fmpar_table[chan].adsrw_mod.wform := ins_parameter(ins,8) AND $07;
-
-      If NOT reset_chan[chan] then
-        keyoff_loop[chan] := FALSE;
-
-      If reset_chan[chan] then
-        begin
-          voice_table[chan] := ins;
-          reset_ins_volume(chan);
-          reset_chan[chan] := FALSE;
-        end;
-
-      If (event_table[chan].note AND $7f in [1..12*8+1]) then
-        init_macro_table(chan,event_table[chan].note AND $7f,ins,freq_table[chan])
-      else init_macro_table(chan,0,ins,freq_table[chan]);
-    end;
-
-  vscale_table[chan] := concw(fmpar_table[chan].kslM SHL 6,
-                              fmpar_table[chan].kslC SHL 6);
-  voice_table[chan] := ins;
-  old_ins := event_table[chan].instr_def;
-  event_table[chan].instr_def := ins;
-
-  If NOT volume_lock[chan] or
-     (ins <> old_ins) then reset_ins_volume(chan);
-end;
-
-procedure update_modulator_adsrw(chan: Byte);
-begin
-  opl3out(_instr[04]+_chan_m[chan],
-          fmpar_table[chan].adsrw_mod.attck SHL 4+
-          fmpar_table[chan].adsrw_mod.dec);
-  opl3out(_instr[06]+_chan_m[chan],
-          fmpar_table[chan].adsrw_mod.sustn SHL 4+
-          fmpar_table[chan].adsrw_mod.rel);
-  opl3out(_instr[08]+_chan_m[chan],
-          fmpar_table[chan].adsrw_mod.wform);
-end;
-
-procedure update_carrier_adsrw(chan: Byte);
-begin
-  opl3out(_instr[05]+_chan_c[chan],
-          fmpar_table[chan].adsrw_car.attck SHL 4+
-          fmpar_table[chan].adsrw_car.dec);
-  opl3out(_instr[07]+_chan_c[chan],
-          fmpar_table[chan].adsrw_car.sustn SHL 4+
-          fmpar_table[chan].adsrw_car.rel);
-  opl3out(_instr[09]+_chan_c[chan],
-          fmpar_table[chan].adsrw_car.wform);
-end;
-
-procedure update_fmpar(chan: Byte);
-begin
-  opl3out(_instr[00]+_chan_m[chan],fmpar_table[chan].multipM+
-                                   fmpar_table[chan].ksrM  SHL 4+
-                                   fmpar_table[chan].sustM SHL 5+
-                                   fmpar_table[chan].vibrM SHL 6+
-                                   fmpar_table[chan].tremM SHL 7);
-  opl3out(_instr[01]+_chan_c[chan],fmpar_table[chan].multipC+
-                                   fmpar_table[chan].ksrC  SHL 4+
-                                   fmpar_table[chan].sustC SHL 5+
-                                   fmpar_table[chan].vibrC SHL 6+
-                                   fmpar_table[chan].tremC SHL 7);
-
-  opl3out(_instr[10]+_chan_n[chan],(fmpar_table[chan].connect+
-                                    fmpar_table[chan].feedb SHL 1) OR
-                                   _panning[panning_table[chan]]);
-
-  vscale_table[chan] := concw(fmpar_table[chan].kslM SHL 6,
-                              fmpar_table[chan].kslC SHL 6);
-  set_ins_volume(LO(volume_table[chan]),
-                 HI(volume_table[chan]),chan);
-end;
-
-function is_4op_chan(chan: Byte): Boolean; assembler;
-asm
-        mov     al,byte ptr [songdata.flag_4op]
-        mov     ah,chan
-        test    al,1
-        jz      @@1
-        cmp     ah,1
-        jb      @@1
-        cmp     ah,2
-        ja      @@1
-        mov     al,TRUE
-        jmp     @@7
-@@1:    test    al,2
-        jz      @@2
-        cmp     ah,3
-        jb      @@2
-        cmp     ah,4
-        ja      @@2
-        mov     al,TRUE
-        jmp     @@7
-@@2:    test    al,4
-        jz      @@3
-        cmp     ah,5
-        jb      @@3
-        cmp     ah,6
-        ja      @@3
-        mov     al,TRUE
-        jmp     @@7
-@@3:    test    al,8
-        jz      @@4
-        cmp     ah,10
-        jb      @@4
-        cmp     ah,11
-        ja      @@4
-        mov     al,TRUE
-        jmp     @@7
-@@4:    test    al,10h
-        jz      @@5
-        cmp     ah,12
-        jb      @@5
-        cmp     ah,13
-        ja      @@5
-        mov     al,TRUE
-        jmp     @@7
-@@5:    test    al,20h
-        jz      @@6
-        cmp     ah,14
-        jb      @@6
-        cmp     ah,15
-        ja      @@6
-        mov     al,TRUE
-        jmp     @@7
-@@6:    mov     al,FALSE
-@@7:
-end;
-
-procedure output_note(note,ins,chan: Byte; restart_macro: Boolean);
-
-var
-  pos: Byte;
-  freq: Word;
-
-begin
-  If (note = 0) and (ftune_table[chan] = 0) then EXIT;
-  If NOT (note in [1..12*8+1]) then freq := freq_table[chan]
-  else begin
-         freq := nFreq(note-1)+SHORTINT(ins_parameter(ins,12));
-         If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
-           opl3out($0b0+_chan_n[chan],0);
-
-         freq_table[chan] := concw(LO(freq_table[chan]),
-                                   HI(freq_table[chan]) OR $20);
-
-         pos := Round(25/(12*8+1)*note);
-         If (decay_bar[pos].lvl <> 0) then
-           If (pos > 1) and
-              (decay_bar[pos-1].dir <> 1) then
-             Dec(pos)
-           else If (pos < 25) and
-                   (decay_bar[pos+1].lvl <> 1) then
-                  Inc(pos);
-
-         If is_4op_chan(chan) then
-           If (chan in [2,4,6,11,13,15]) then
-             begin
-               decay_bar[pos].dir := 1;
-               If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-                 decay_bar[pos].max_lvl :=
-                   (carrier_vol[PRED(chan)]+carrier_vol[chan]) DIV 2
-               else decay_bar[pos].max_lvl :=
-                      (carrier_vol[PRED(chan)]+modulator_vol[PRED(chan)]+
-                       carrier_vol[chan]+modulator_vol[chan]) DIV 4;
-             end
-           else
-         else
-           begin
-             decay_bar[pos].dir := 1;
-             If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               decay_bar[pos].max_lvl :=
-                 carrier_vol[chan]
-             else decay_bar[pos].max_lvl :=
-                    (carrier_vol[chan]+modulator_vol[chan]) DIV 2;
-           end;
-       end;
-
-  If (ftune_table[chan] = -127) then ftune_table[chan] := 0;
-  freq := freq+ftune_table[chan];
-
-  If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
-    change_frequency(chan,freq);
-
-  If (note <> 0) then
-    begin
-      event_table[chan].note := note;
-      If restart_macro then
-        With event_table[chan] do
-           If NOT (((effect_def = ef_Extended) and
-                   (effect DIV 16 = ef_ex_ExtendedCmd) and
-                   (effect MOD 16 = ef_ex_cmd_NoRestart)) or
-                  ((effect_def2 = ef_Extended) and
-                   (effect2 DIV 16 = ef_ex_ExtendedCmd) and
-                   (effect2 MOD 16 = ef_ex_cmd_NoRestart))) then
-             init_macro_table(chan,note,ins,freq)
-           else macro_table[chan].arpg_note := note;
-    end;
-end;
-
-procedure output_note_NR(note,ins,chan: Byte; restart_macro: Boolean);
-
-var
-  pos: Byte;
-  freq: Word;
-
-begin
-  If (note = 0) and (ftune_table[chan] = 0) then EXIT;
-  If NOT (note in [1..12*8+1]) then freq := freq_table[chan]
-  else begin
-         freq := nFreq(note-1)+SHORTINT(ins_parameter(ins,12));
-         freq_table[chan] := concw(LO(freq_table[chan]),
-                                   HI(freq_table[chan]) OR $20);
-
-         pos := Round(25/(12*8+1)*note);
-         If (decay_bar[pos].lvl <> 0) then
-           If (pos > 1) and
-              (decay_bar[pos-1].dir <> 1) then
-             Dec(pos)
-           else If (pos < 25) and
-                   (decay_bar[pos+1].lvl <> 1) then
-                  Inc(pos);
-
-         If is_4op_chan(chan) then
-           If (chan in [2,4,6,11,13,15]) then
-             begin
-               decay_bar[pos].dir := 1;
-               If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-                 decay_bar[pos].max_lvl :=
-                   (carrier_vol[PRED(chan)]+carrier_vol[chan]) DIV 2
-               else decay_bar[pos].max_lvl :=
-                      (carrier_vol[PRED(chan)]+modulator_vol[PRED(chan)]+
-                       carrier_vol[chan]+modulator_vol[chan]) DIV 4;
-             end
-           else
-         else
-           begin
-             decay_bar[pos].dir := 1;
-             If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               decay_bar[pos].max_lvl :=
-                 carrier_vol[chan]
-             else decay_bar[pos].max_lvl :=
-                    (carrier_vol[chan]+modulator_vol[chan]) DIV 2;
-           end;
-       end;
-
-  If (ftune_table[chan] = -127) then ftune_table[chan] := 0;
-  freq := freq+ftune_table[chan];
-
-  If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
-    change_frequency(chan,freq);
-
-  If (note <> 0) then
-    begin
-      event_table[chan].note := note;
-      If restart_macro then
-        With event_table[chan] do
-           If NOT (((effect_def = ef_Extended) and
-                   (effect DIV 16 = ef_ex_ExtendedCmd) and
-                   (effect MOD 16 = ef_ex_cmd_NoRestart)) or
-                  ((effect_def2 = ef_Extended) and
-                   (effect2 DIV 16 = ef_ex_ExtendedCmd) and
-                   (effect2 MOD 16 = ef_ex_cmd_NoRestart))) then
-             init_macro_table(chan,note,ins,freq)
-           else macro_table[chan].arpg_note := note;
-    end;
-end;
-
-procedure generate_custom_vibrato(value: Byte);
-
-const
-  vibtab_size: array[0..15] of Byte = (
-    16,16,16,16,32,32,32,32,64,64,64,64,128,128,128,128);
-
-var
-  mul_r: Real;
-  mul_b: Byte;
-  idx,idx2: Byte;
-
-function min0(value: Longint): Longint;
-begin
-  If (value >= 0) then min0 := value
-  else min0 := 0;
-end;
-
-begin
-  Case value of
-    // set default speed table
-    0: begin
-         vibtrem_table_size := def_vibtrem_table_size;
-         Move(def_vibtrem_table,vibtrem_table,SizeOf(vibtrem_table));
-       end;
-
-    // set custom speed table (fixed size = 32)
-    1..239:
-       begin
-         vibtrem_table_size := def_vibtrem_table_size;
-         mul_r := value/16;
-         For idx2 := 0 to 7 do
-          begin
-            vibtrem_table[idx2*32] := 0;
-            For idx := 1 to 16 do
-              vibtrem_table[idx2*32+idx] := ROUND(idx*mul_r);
-            For idx := 17 to 31 do
-              vibtrem_table[idx2*32+idx] := ROUND((32-idx)*mul_r);
-          end;
-       end;
-
-    // set custom speed table (speed factor = 1-4)
-    240..255:
-       begin
-         vibtrem_speed_factor := SUCC((value-240) MOD 4);
-         vibtrem_table_size := 2*vibtab_size[value-240];
-         mul_b := 256 DIV (vibtab_size[value-240]);
-         For idx2 := 0 to PRED(128 DIV vibtab_size[value-240]) do
-           begin
-             vibtrem_table[2*vibtab_size[value-240]*idx2] := 0;
-             For idx := 1 to vibtab_size[value-240] do
-               vibtrem_table[2*vibtab_size[value-240]*idx2+idx] :=
-                 min0(idx*mul_b-1);
-             For idx := vibtab_size[value-240]+1 to
-                        2*vibtab_size[value-240]-1 do
-               vibtrem_table[2*vibtab_size[value-240]*idx2+idx] :=
-                 min0((2*vibtab_size[value-240]-idx)*mul_b-1);
-           end;
-       end;
-  end;
-end;
-
-procedure update_fine_effects(chan: Byte); forward;
-procedure play_line;
-
-var
-  chan,idx: Byte;
-  event: array[1..20] of tCHUNK;
-  eLo,eHi,eLo2,eHi2: array[1..20] of Byte;
-
-function no_loop(current_chan,current_line: Byte): Boolean;
-
-var
-  result: Boolean;
-  chan: Byte;
-
-begin
-  result := TRUE;
-  For chan := 1 to PRED(current_chan) do
-    If (loop_table[chan][current_line] <> 0) and
-       (loop_table[chan][current_line] <> BYTE_NULL) then
-      begin
-        result := FALSE;
-        BREAK;
-      end;
-  no_loop := result;
-end;
-
-function get_event(pattern,line,channel: Byte): tCHUNK;
-begin
-  asm
-        mov     esi,[pattdata]
-        mov     edi,@result
-        mov     al,pattern
-        inc     al
-        cmp     al,max_patterns
-        jbe     @@1
-        mov     ecx,CHUNK_SIZE
-        xor     al,al
-        rep     stosb
-        jmp     @@2
-@@1:    xor     eax,eax
-        mov     al,line
-        mov     ebx,CHUNK_SIZE
-        mul     ebx
-        mov     ecx,eax
-        xor     eax,eax
-        mov     al,channel
-        dec     eax
-        mov     ebx,256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        xor     eax,eax
-        mov     al,pattern
-        mov     ebx,8
-        div     ebx
-        push    eax
-        mov     eax,edx
-        mov     ebx,20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        pop     eax
-        mov     ebx,8*20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        add     esi,ecx
-        mov     ecx,CHUNK_SIZE
-        rep     movsb
-@@2:
-  end;
-end;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:play_line';
-  If (current_line = 0) and
-     (current_order = calc_following_order(0)) then
-    time_playing := 0;
-
-  If NOT (pattern_break and (next_line AND $0f0 = pattern_loop_flag)) and
-         (current_order <> last_order) then
-    begin
-      FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
-      FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
-      last_order := current_order;
-    end;
-
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      event[chan] := get_event(current_pattern,current_line,chan);
-      If (effect_table[chan] <> 0) then last_effect[chan] := effect_table[chan];
-      If (glfsld_table[chan] <> 0) then effect_table[chan] := glfsld_table[chan]
-      else effect_table[chan] := effect_table[chan] AND $0ff00;
-      If (effect_table2[chan] <> 0) then last_effect2[chan] := effect_table2[chan];
-      If (glfsld_table2[chan] <> 0) then effect_table2[chan] := glfsld_table2[chan]
-      else effect_table2[chan] := effect_table2[chan] AND $0ff00;
-      ftune_table[chan] := 0;
-
-      If (event[chan].note = BYTE_NULL) then
-        event[chan].note := event_table[chan].note OR keyoff_flag
-      else If (event[chan].note in [fixed_note_flag+1..fixed_note_flag+12*8+1]) then
-             event[chan].note := event[chan].note-fixed_note_flag;
-
-      If (event[chan].note <> 0) or
-         (event[chan].effect_def <> 0) or
-         (event[chan].effect_def2 <> 0) or
-         ((event[chan].effect_def = 0) and (event[chan].effect <> 0)) or
-         ((event[chan].effect_def2 = 0) and (event[chan].effect2 <> 0)) then
-        event_new[chan] := TRUE
-      else event_new[chan] := FALSE;
-
-      If (event[chan].note <> 0) or
-         (event[chan].instr_def <> 0) or
-         (event[chan].effect_def+event[chan].effect <> 0) or
-         (event[chan].effect_def2+event[chan].effect2 <> 0) then
-        begin
-          event_table[chan].effect_def := event[chan].effect_def;
-          event_table[chan].effect := event[chan].effect;
-          event_table[chan].effect_def2 := event[chan].effect_def2;
-          event_table[chan].effect2 := event[chan].effect2;
-        end;
-
-      If (event[chan].instr_def <> 0) then
-        If NOT Empty(songdata.instr_data[event[chan].instr_def],
-                     INSTRUMENT_SIZE) then
-          set_ins_data(event[chan].instr_def,chan)
-        else begin
-               release_sustaining_sound(chan);
-               set_ins_data(event[chan].instr_def,chan);
-             end;
-
-      If NOT (event[chan].effect_def in [ef_Vibrato,ef_ExtraFineVibrato,
-                                   ef_VibratoVolSlide,ef_VibratoVSlideFine]) then
-        FillChar(vibr_table[chan],SizeOf(vibr_table[chan]),0);
-
-      If NOT (event[chan].effect_def2 in [ef_Vibrato,ef_ExtraFineVibrato,
-                                    ef_VibratoVolSlide,ef_VibratoVSlideFine]) then
-        FillChar(vibr_table2[chan],SizeOf(vibr_table2[chan]),0);
-
-      If NOT (event[chan].effect_def in [ef_RetrigNote,ef_MultiRetrigNote]) then
-        FillChar(retrig_table[chan],SizeOf(retrig_table[chan]),0);
-
-      If NOT (event[chan].effect_def2 in [ef_RetrigNote,ef_MultiRetrigNote]) then
-        FillChar(retrig_table2[chan],SizeOf(retrig_table2[chan]),0);
-
-      If NOT (event[chan].effect_def in [ef_Tremolo,ef_ExtraFineTremolo]) then
-        FillChar(trem_table[chan],SizeOf(trem_table[chan]),0);
-
-      If NOT (event[chan].effect_def2 in [ef_Tremolo,ef_ExtraFineTremolo]) then
-        FillChar(trem_table2[chan],SizeOf(trem_table2[chan]),0);
-
-      If NOT (((event[chan].effect_def = ef_Arpeggio) and (event[chan].effect <> 0)) or
-               (event[chan].effect_def = ef_ExtraFineArpeggio)) and
-
-
-
-
-
-               (arpgg_table[chan].note <> 0) and (arpgg_table[chan].state <> 1) then
-        begin
-          arpgg_table[chan].state := 1;
-          change_frequency(chan,nFreq(arpgg_table[chan].note-1)+
-            SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-        end
-      else If NOT (((event[chan].effect_def2 = ef_Arpeggio) and (event[chan].effect2 <> 0)) or
-                  (event[chan].effect_def2 = ef_ExtraFineArpeggio)) and
-                  (arpgg_table2[chan].note <> 0) and (arpgg_table2[chan].state <> 1) then
-             begin
-               arpgg_table2[chan].state := 1;
-               change_frequency(chan,nFreq(arpgg_table2[chan].note-1)+
-                 SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-             end;
-    end;
-
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      If (tremor_table[chan].pos <> 0) and
-         (event[chan].effect_def <> ef_Tremor) then
-        begin
-          tremor_table[chan].pos := 0;
-          set_ins_volume(LO(tremor_table[chan].volume),
-                         HI(tremor_table[chan].volume),chan);
-        end;
-
-      If (tremor_table2[chan].pos <> 0) and
-         (event[chan].effect_def2 <> ef_Tremor) then
-        begin
-          tremor_table2[chan].pos := 0;
-          set_ins_volume(LO(tremor_table2[chan].volume),
-                         HI(tremor_table2[chan].volume),chan);
-        end;
-
-      eLo[chan]  := LO(last_effect[chan]);
-      eHi[chan]  := HI(last_effect[chan]);
-      eLo2[chan] := LO(last_effect2[chan]);
-      eHi2[chan] := HI(last_effect2[chan]);
-    end;
-
-  For chan := 1 to songdata.nm_tracks do
-    Case event[chan].effect_def of
-
-      ef_Arpeggio,
-      ef_ExtraFineArpeggio,
-      ef_ArpggVSlide,
-      ef_ArpggVSlideFine:
-        If (event[chan].effect_def <> ef_Arpeggio) or
-           (event[chan].effect <> 0) then
-          begin
-            Case event[chan].effect_def of
-              ef_Arpeggio:
-                effect_table[chan] := concw(ef_Arpeggio+ef_fix1,event[chan].effect);
-
-              ef_ExtraFineArpeggio:
-                effect_table[chan] := concw(ef_ExtraFineArpeggio,event[chan].effect);
-
-              ef_ArpggVSlide,
-              ef_ArpggVSlideFine:
-                If (event[chan].effect <> 0) then
-                  effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-                else If (eLo[chan] in [ef_ArpggVSlide,ef_ArpggVSlideFine]) and
-                        (eHi[chan] <> 0) then
-                       effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
-                     else effect_table[chan] := effect_table[chan] AND $0ff00;
-            end;
-
-            If (event[chan].note AND $7f in [1..12*8+1]) then
-              begin
-                arpgg_table[chan].state := 0;
-                arpgg_table[chan].note := event[chan].note AND $7f;
-                If (event[chan].effect_def in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
-                  begin
-                    arpgg_table[chan].add1 := event[chan].effect DIV 16;
-                    arpgg_table[chan].add2 := event[chan].effect MOD 16;
-                  end;
-              end
-            else If (event[chan].note = 0) and
-                    (event_table[chan].note AND $7f in [1..12*8+1]) then
-                   begin
-                     If NOT (eLo[chan] in [ef_Arpeggio+ef_fix1,ef_ExtraFineArpeggio,
-                                     ef_ArpggVSlide,ef_ArpggVSlideFine]) then
-                       arpgg_table[chan].state := 0;
-
-                     arpgg_table[chan].note := event_table[chan].note AND $7f;
-                     If (event[chan].effect_def in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
-                       begin
-                         arpgg_table[chan].add1 := event[chan].effect DIV 16;
-                         arpgg_table[chan].add2 := event[chan].effect MOD 16;
-                       end;
-                   end
-                 else effect_table[chan] := 0;
-          end;
-
-      ef_FSlideUp,
-      ef_FSlideDown,
-      ef_FSlideUpFine,
-      ef_FSlideDownFine:
-        begin
-          effect_table[chan] := concw(event[chan].effect_def,event[chan].effect);
-          fslide_table[chan] := event[chan].effect;
-        end;
-
-      ef_GlobalFSlideUp,
-      ef_GlobalFSlideDown:
-        begin
-          If (event[chan].effect_def = ef_GlobalFSlideUp) then
-            begin
-              If (event[chan].effect_def2 = ef_Extended) and
-                 (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-                effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
-                                            event[chan].effect)
-              else If (event[chan].effect_def2 = ef_Extended) and
-                      (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-                     effect_table[chan] := concw(ef_FSlideUpFine,event[chan].effect)
-                   else effect_table[chan] := concw(ef_FSlideUp,event[chan].effect);
-            end
-          else
-            begin
-              If (event[chan].effect_def2 = ef_Extended) and
-                 (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-                effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
-                                            event[chan].effect)
-              else If (event[chan].effect_def2 = ef_Extended) and
-                      (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-                     effect_table[chan] := concw(ef_FSlideDownFine,event[chan].effect)
-                   else effect_table[chan] := concw(ef_FSlideDown,event[chan].effect);
-            end;
-          For idx := chan to songdata.nm_tracks do
-            begin
-              fslide_table[idx] := event[chan].effect;
-              glfsld_table[idx] := effect_table[chan];
-            end;
-        end;
-
-      ef_FSlideUpVSlide,
-      ef_FSlUpVSlF,
-      ef_FSlideDownVSlide,
-      ef_FSlDownVSlF,
-      ef_FSlUpFineVSlide,
-      ef_FSlUpFineVSlF,
-      ef_FSlDownFineVSlide,
-      ef_FSlDownFineVSlF:
-        If (event[chan].effect <> 0) then
-          effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-        else If (eLo[chan] in [ef_FSlideUpVSlide,ef_FSlUpVSlF,ef_FSlideDownVSlide,
-                         ef_FSlDownVSlF,ef_FSlUpFineVSlide,ef_FSlUpFineVSlF,
-                         ef_FSlDownFineVSlide,ef_FSlDownFineVSlF]) and
-                (eHi[chan] <> 0) then
-               effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
-             else effect_table[chan] := effect_table[chan] AND $0ff00;
-
-      ef_TonePortamento:
-        If (event[chan].note in [1..12*8+1]) then
-          begin
-            If (event[chan].effect <> 0) then
-              effect_table[chan] := concw(ef_TonePortamento,event[chan].effect)
-            else If (eLo[chan] = ef_TonePortamento) and
-                    (eHi[chan] <> 0) then
-                   effect_table[chan] := concw(ef_TonePortamento,eHi[chan])
-                 else effect_table[chan] := ef_TonePortamento;
-
-            porta_table[chan].speed := HI(effect_table[chan]);
-            porta_table[chan].freq := nFreq(event[chan].note-1)+
-              SHORTINT(ins_parameter(event_table[chan].instr_def,12));
-          end
-        else If (eLo[chan] = ef_TonePortamento) then
-               begin
-                 If (event[chan].effect <> 0) then
-                   effect_table[chan] := concw(ef_TonePortamento,event[chan].effect)
-                 else If (eLo[chan] = ef_TonePortamento) and
-                         (eHi[chan] <> 0) then
-                        effect_table[chan] := concw(ef_TonePortamento,eHi[chan])
-                      else effect_table[chan] := ef_TonePortamento;
-                 porta_table[chan].speed := HI(effect_table[chan]);
-               end;
-
-      ef_TPortamVolSlide,
-      ef_TPortamVSlideFine:
-        If (event[chan].effect <> 0) then
-          effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-        else If (eLo[chan] in [ef_TPortamVolSlide,ef_TPortamVSlideFine]) and
-                (eHi[chan] <> 0) then
-               effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
-             else effect_table[chan] := effect_table[chan] AND $0ff00;
-
-      ef_Vibrato,
-      ef_ExtraFineVibrato:
-        begin
-          If (event[chan].effect <> 0) then
-            effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-          else If (eLo[chan] in [ef_Vibrato,ef_ExtraFineVibrato]) and
-                  (eHi[chan] <> 0) then
-                 effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
-               else effect_table[chan] := event[chan].effect_def;
-
-          If (event[chan].effect_def2 = ef_Extended) and
-             (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-            vibr_table[chan].fine := TRUE;
-
-          vibr_table[chan].speed := HI(effect_table[chan]) DIV 16;
-          vibr_table[chan].depth := HI(effect_table[chan]) MOD 16;
-        end;
-
-      ef_Tremolo,
-      ef_ExtraFineTremolo:
-        begin
-          If (event[chan].effect <> 0) then
-            effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-          else If (eLo[chan] in [ef_Tremolo,ef_ExtraFineTremolo]) and
-                  (eHi[chan] <> 0) then
-                 effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
-               else effect_table[chan] := event[chan].effect_def;
-
-          If (event[chan].effect_def2 = ef_Extended) and
-             (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-            trem_table[chan].fine := TRUE;
-
-          trem_table[chan].speed := HI(effect_table[chan]) DIV 16;
-          trem_table[chan].depth := HI(effect_table[chan]) MOD 16;
-        end;
-
-      ef_VibratoVolSlide,
-      ef_VibratoVSlideFine:
-        begin
-          If (event[chan].effect <> 0) then
-            effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
-          else If (eLo[chan] in [ef_VibratoVolSlide,ef_VibratoVSlideFine]) and
-                  (HI(effect_table[chan]) <> 0) then
-                 effect_table[chan] := concw(event[chan].effect_def,HI(effect_table[chan]))
-               else effect_table[chan] := effect_table[chan] AND $0ff00;
-
-          If (event[chan].effect_def2 = ef_Extended) and
-             (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-            vibr_table[chan].fine := TRUE;
-        end;
-
-      ef_SetCarrierVol:
-        set_ins_volume(BYTE_NULL,63-event[chan].effect,chan);
-
-      ef_SetModulatorVol:
-        set_ins_volume(63-event[chan].effect,BYTE_NULL,chan);
-
-      ef_SetInsVolume:
-        If percussion_mode and (chan in [17..20]) then
-          set_ins_volume(63-event[chan].effect,BYTE_NULL,chan)
-        else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               set_ins_volume(BYTE_NULL,63-event[chan].effect,chan)
-             else set_ins_volume(63-event[chan].effect,63-event[chan].effect,chan);
-
-      ef_ForceInsVolume:
-        If percussion_mode and (chan in [17..20]) then
-          set_ins_volume(63-event[chan].effect,BYTE_NULL,chan)
-        else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               set_ins_volume(scale_volume(ins_parameter(voice_table[chan],2) AND $3f,63-event[chan].effect),63-event[chan].effect,chan)
-             else set_ins_volume(63-event[chan].effect,63-event[chan].effect,chan);
-
-      ef_PositionJump:
-        If no_loop(chan,current_line) then
-          begin
-            pattern_break := TRUE;
-            next_line := pattern_break_flag+chan;
-          end;
-
-      ef_PatternBreak:
-        If no_loop(chan,current_line) then
-          begin
-            pattern_break := TRUE;
-            next_line := max(event[chan].effect,PRED(songdata.patt_len));
-          end;
-
-      ef_SetSpeed:
-        speed := event[chan].effect;
-
-      ef_SetTempo:
-        update_timer(event[chan].effect);
-
-      ef_SetWaveform:
-        begin
-          If (event[chan].effect DIV 16 in [0..7]) then
-            begin
-              fmpar_table[chan].adsrw_car.wform := event[chan].effect DIV 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          If (event[chan].effect MOD 16 in [0..7]) then
-            begin
-              fmpar_table[chan].adsrw_mod.wform := event[chan].effect MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-        end;
-
-      ef_VolSlide:
-        effect_table[chan] := concw(ef_VolSlide,event[chan].effect);
-
-      ef_VolSlideFine:
-        effect_table[chan] := concw(ef_VolSlideFine,event[chan].effect);
-
-      ef_RetrigNote:
-        If (event[chan].effect <> 0) then
-          begin
-            If NOT (eLo[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
-              retrig_table[chan] := 1;
-            effect_table[chan] := concw(ef_RetrigNote,event[chan].effect);
-          end;
-
-      ef_SetGlobalVolume:
-        begin
-          global_volume := event[chan].effect;
-          set_global_volume;
-        end;
-
-      ef_MultiRetrigNote:
-        If (event[chan].effect DIV 16 <> 0) then
-          begin
-            If NOT (eLo[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
-              retrig_table[chan] := 1;
-            effect_table[chan] := concw(ef_MultiRetrigNote,event[chan].effect);
-          end;
-
-      ef_Tremor:
-        If (event[chan].effect DIV 16 <> 0) and
-           (event[chan].effect MOD 16 <> 0) then
-        begin
-          If (eLo[chan] <> ef_Tremor) then
-            begin
-              tremor_table[chan].pos := 0;
-              tremor_table[chan].volume := volume_table[chan];
-            end;
-          effect_table[chan] := concw(ef_Tremor,event[chan].effect);
-        end;
-
-      ef_Extended:
-        Case (event[chan].effect DIV 16) of
-          ef_ex_SetTremDepth:
-            Case (event[chan].effect MOD 16) of
-              0: begin
-                   opl3out(_instr[11],misc_register AND $07f);
-                   current_tremolo_depth := 0;
-                 end;
-
-              1: begin
-                   opl3out(_instr[11],misc_register OR $080);
-                   current_tremolo_depth := 1;
-                 end;
-            end;
-
-          ef_ex_SetVibDepth:
-            Case (event[chan].effect MOD 16) of
-              0: begin
-                   opl3out(_instr[11],misc_register AND $0bf);
-                   current_vibrato_depth := 0;
-                 end;
-
-              1: begin
-                   opl3out(_instr[11],misc_register OR $040);
-                   current_vibrato_depth := 1;
-                 end;
-            end;
-
-          ef_ex_SetAttckRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.attck := event[chan].effect MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetDecayRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.dec := event[chan].effect MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetSustnLevelM:
-            begin
-              fmpar_table[chan].adsrw_mod.sustn := event[chan].effect MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetRelRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.rel := event[chan].effect MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetAttckRateC:
-            begin
-              fmpar_table[chan].adsrw_car.attck := event[chan].effect MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetDecayRateC:
-            begin
-              fmpar_table[chan].adsrw_car.dec := event[chan].effect MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetSustnLevelC:
-            begin
-              fmpar_table[chan].adsrw_car.sustn := event[chan].effect MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetRelRateC:
-            begin
-              fmpar_table[chan].adsrw_car.rel := event[chan].effect MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetFeedback:
-            begin
-              fmpar_table[chan].feedb := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex_SetPanningPos:
-            begin
-              panning_table[chan] := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex_PatternLoop,
-          ef_ex_PatternLoopRec:
-            If (event[chan].effect MOD 16 = 0) then
-              loopbck_table[chan] := current_line
-            else If (loopbck_table[chan] <> BYTE_NULL) then
-                   begin
-                     If (loop_table[chan][current_line] = BYTE_NULL) then
-                       loop_table[chan][current_line] := event[chan].effect MOD 16;
-                     If (loop_table[chan][current_line] <> 0) then
-                       begin
-                         pattern_break := TRUE;
-                         next_line := pattern_loop_flag+chan;
-                       end
-                     else If (event[chan].effect DIV 16 = ef_ex_PatternLoopRec) then
-                            loop_table[chan][current_line] := BYTE_NULL;
-                   end;
-
-          ef_ex_MacroKOffLoop:
-            If (event[chan].effect MOD 16 <> 0) then
-              keyoff_loop[chan] := TRUE
-            else keyoff_loop[chan] := FALSE;
-
-          ef_ex_ExtendedCmd:
-            Case (event[chan].effect MOD 16) of
-              ef_ex_cmd_RSS:        release_sustaining_sound(chan);
-              ef_ex_cmd_ResetVol:   reset_ins_volume(chan);
-              ef_ex_cmd_LockVol:    volume_lock  [chan] := TRUE;
-              ef_ex_cmd_UnlockVol:  volume_lock  [chan] := FALSE;
-              ef_ex_cmd_LockVP:     peak_lock    [chan] := TRUE;
-              ef_ex_cmd_UnlockVP:   peak_lock    [chan] := FALSE;
-              ef_ex_cmd_VSlide_def: volslide_type[chan] := 0;
-              ef_ex_cmd_LockPan:    pan_lock     [chan] := TRUE;
-              ef_ex_cmd_UnlockPan:  pan_lock     [chan] := FALSE;
-              ef_ex_cmd_VibrOff:    change_frequency(chan,freq_table[chan]);
-              ef_ex_cmd_TremOff:    set_ins_volume(LO(volume_table[chan]),
-                                                   HI(volume_table[chan]),chan);
-              ef_ex_cmd_VSlide_car:
-                If (event[chan].effect_def2 = ef_Extended) and
-                   (event[chan].effect2 = ef_ex_ExtendedCmd*16+
-                                    ef_ex_cmd_VSlide_mod) then
-                  volslide_type[chan] := 3
-                else volslide_type[chan] := 1;
-
-              ef_ex_cmd_VSlide_mod:
-                If (event[chan].effect_def2 = ef_Extended) and
-                   (event[chan].effect2 = ef_ex_ExtendedCmd*16+
-                                    ef_ex_cmd_VSlide_car) then
-                  volslide_type[chan] := 3
-                else volslide_type[chan] := 2;
-            end;
-        end;
-
-      ef_Extended2:
-        Case (event[chan].effect DIV 16) of
-          ef_ex2_PatDelayFrame,
-          ef_ex2_PatDelayRow:
-            begin
-              pattern_delay := TRUE;
-              If (event[chan].effect DIV 16 = ef_ex2_PatDelayFrame) then
-                tickD := (event[chan].effect MOD 16)
-              else tickD := speed*(event[chan].effect MOD 16);
-            end;
-
-          ef_ex2_NoteDelay:
-            begin
-              effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteDelay,0);
-              notedel_table[chan] := event[chan].effect MOD 16;
-            end;
-
-          ef_ex2_NoteCut:
-            begin
-              effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteCut,0);
-              notecut_table[chan] := event[chan].effect MOD 16;
-            end;
-
-          ef_ex2_FineTuneUp:
-            Inc(ftune_table[chan],event[chan].effect MOD 16);
-
-          ef_ex2_FineTuneDown:
-            Dec(ftune_table[chan],event[chan].effect MOD 16);
-
-          ef_ex2_GlVolSlideUp:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp,
-                                        event[chan].effect MOD 16);
-          ef_ex2_GlVolSlideDn:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn,
-                                        event[chan].effect MOD 16);
-          ef_ex2_GlVolSlideUpF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_GlVolSlideDnF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_GlVolSldUpXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_GlVolSldDnXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_VolSlideUpXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_VolSlideDnXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_FreqSlideUpXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
-                                        event[chan].effect MOD 16);
-          ef_ex2_FreqSlideDnXF:
-            effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
-                                        event[chan].effect MOD 16);
-        end;
-
-      ef_Extended3:
-        Case (event[chan].effect DIV 16) of
-          ef_ex3_SetConnection:
-            begin
-              fmpar_table[chan].connect := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetMultipM:
-            begin
-              fmpar_table[chan].multipM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKslM:
-            begin
-              fmpar_table[chan].kslM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetTremoloM:
-            begin
-              fmpar_table[chan].tremM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetVibratoM:
-            begin
-              fmpar_table[chan].vibrM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKsrM:
-            begin
-              fmpar_table[chan].ksrM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetSustainM:
-            begin
-              fmpar_table[chan].sustM := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetMultipC:
-            begin
-              fmpar_table[chan].multipC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKslC:
-            begin
-              fmpar_table[chan].kslC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetTremoloC:
-            begin
-              fmpar_table[chan].tremC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetVibratoC:
-            begin
-              fmpar_table[chan].vibrC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKsrC:
-            begin
-              fmpar_table[chan].ksrC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetSustainC:
-            begin
-              fmpar_table[chan].sustC := event[chan].effect MOD 16;
-              update_fmpar(chan);
-            end;
-        end;
-    end;
-
-  For chan := 1 to songdata.nm_tracks do
-    Case event[chan].effect_def2 of
-      ef_Arpeggio,
-      ef_ExtraFineArpeggio,
-      ef_ArpggVSlide,
-      ef_ArpggVSlideFine:
-        If (event[chan].effect_def2 <> ef_Arpeggio) or
-           (event[chan].effect2 <> 0) then
-          begin
-            Case event[chan].effect_def2 of
-              ef_Arpeggio:
-                effect_table2[chan] := concw(ef_Arpeggio+ef_fix1,event[chan].effect2);
-
-              ef_ExtraFineArpeggio:
-                effect_table2[chan] := concw(ef_ExtraFineArpeggio,event[chan].effect2);
-
-              ef_ArpggVSlide,
-              ef_ArpggVSlideFine:
-                If (event[chan].effect2 <> 0) then
-                  effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-                else If (eLo2[chan] in [ef_ArpggVSlide,ef_ArpggVSlideFine]) and
-                        (eHi2[chan] <> 0) then
-                       effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
-                     else effect_table2[chan] := effect_table2[chan] AND $0ff00;
-            end;
-
-            If (event[chan].note AND $7f in [1..12*8+1]) then
-              begin
-                arpgg_table2[chan].state := 0;
-                arpgg_table2[chan].note := event[chan].note AND $7f;
-                If (event[chan].effect_def2 in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
-                  begin
-                    arpgg_table2[chan].add1 := event[chan].effect2 DIV 16;
-                    arpgg_table2[chan].add2 := event[chan].effect2 MOD 16;
-                  end;
-              end
-            else If (event[chan].note = 0) and
-                    (event_table[chan].note AND $7f in [1..12*8+1]) then
-                   begin
-                     If NOT (eLo2[chan] in [ef_Arpeggio+ef_fix1,ef_ExtraFineArpeggio,
-                                     ef_ArpggVSlide,ef_ArpggVSlideFine]) then
-                       arpgg_table2[chan].state := 0;
-
-                     arpgg_table2[chan].note := event_table[chan].note AND $7f;
-                     If (event[chan].effect_def2 in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
-                       begin
-                         arpgg_table2[chan].add1 := event[chan].effect2 DIV 16;
-                         arpgg_table2[chan].add2 := event[chan].effect2 MOD 16;
-                       end;
-                   end
-                 else effect_table2[chan] := 0;
-          end;
-
-      ef_FSlideUp,
-      ef_FSlideDown,
-      ef_FSlideUpFine,
-      ef_FSlideDownFine:
-        begin
-          effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2);
-          fslide_table2[chan] := event[chan].effect2;
-        end;
-
-      ef_GlobalFSlideUp,
-      ef_GlobalFSlideDown:
-        begin
-          If (event[chan].effect_def2 = ef_GlobalFSlideUp) then
-            begin
-              If (event[chan].effect_def = ef_Extended) and
-                 (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-                effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
-                                             event[chan].effect2)
-              else If (event[chan].effect_def = ef_Extended) and
-                      (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-                     effect_table2[chan] := concw(ef_FSlideUpFine,event[chan].effect2)
-                   else effect_table2[chan] := concw(ef_FSlideUp,event[chan].effect2);
-            end
-          else
-            begin
-              If (event[chan].effect_def = ef_Extended) and
-                 (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-                effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
-                                             event[chan].effect2)
-              else If (event[chan].effect_def = ef_Extended) and
-                      (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-                     effect_table2[chan] := concw(ef_FSlideDownFine,event[chan].effect2)
-                   else effect_table2[chan] := concw(ef_FSlideDown,event[chan].effect2);
-            end;
-          For idx := chan to songdata.nm_tracks do
-            begin
-              fslide_table2[idx] := event[chan].effect2;
-              glfsld_table2[idx] := effect_table2[chan];
-            end;
-        end;
-
-      ef_FSlideUpVSlide,
-      ef_FSlUpVSlF,
-      ef_FSlideDownVSlide,
-      ef_FSlDownVSlF,
-      ef_FSlUpFineVSlide,
-      ef_FSlUpFineVSlF,
-      ef_FSlDownFineVSlide,
-      ef_FSlDownFineVSlF:
-        If (event[chan].effect2 <> 0) then
-          effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-        else If (eLo2[chan] in [ef_FSlideUpVSlide,ef_FSlUpVSlF,ef_FSlideDownVSlide,
-                         ef_FSlDownVSlF,ef_FSlUpFineVSlide,ef_FSlUpFineVSlF,
-                         ef_FSlDownFineVSlide,ef_FSlDownFineVSlF]) and
-                (eHi2[chan] <> 0) then
-               effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
-             else effect_table2[chan] := effect_table2[chan] AND $0ff00;
-
-      ef_TonePortamento:
-        If (event[chan].note in [1..12*8+1]) then
-          begin
-            If (event[chan].effect2 <> 0) then
-              effect_table2[chan] := concw(ef_TonePortamento,event[chan].effect2)
-            else If (eLo2[chan] = ef_TonePortamento) and
-                    (eHi2[chan] <> 0) then
-                   effect_table2[chan] := concw(ef_TonePortamento,eHi2[chan])
-                 else effect_table2[chan] := ef_TonePortamento;
-
-            porta_table2[chan].speed := HI(effect_table2[chan]);
-            porta_table2[chan].freq := nFreq(event[chan].note-1)+
-              SHORTINT(ins_parameter(event_table[chan].instr_def,12));
-          end
-        else If (eLo2[chan] = ef_TonePortamento) then
-               begin
-                 If (event[chan].effect2 <> 0) then
-                   effect_table2[chan] := concw(ef_TonePortamento,event[chan].effect2)
-                 else If (eLo2[chan] = ef_TonePortamento) and
-                         (eHi2[chan] <> 0) then
-                        effect_table2[chan] := concw(ef_TonePortamento,eHi2[chan])
-                      else effect_table2[chan] := ef_TonePortamento;
-                 porta_table2[chan].speed := HI(effect_table2[chan]);
-               end;
-
-      ef_TPortamVolSlide,
-      ef_TPortamVSlideFine:
-        If (event[chan].effect2 <> 0) then
-          effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-        else If (eLo2[chan] in [ef_TPortamVolSlide,ef_TPortamVSlideFine]) and
-                (eHi2[chan] <> 0) then
-               effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
-             else effect_table2[chan] := effect_table2[chan] AND $0ff00;
-
-      ef_Vibrato,
-      ef_ExtraFineVibrato:
-        begin
-          If (event[chan].effect2 <> 0) then
-            effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-          else If (eLo2[chan] in [ef_Vibrato,ef_ExtraFineVibrato]) and
-                  (eHi2[chan] <> 0) then
-                 effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
-               else effect_table2[chan] := event[chan].effect_def2;
-
-          If (event[chan].effect_def = ef_Extended) and
-             (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-            vibr_table2[chan].fine := TRUE;
-
-          vibr_table2[chan].speed := HI(effect_table2[chan]) DIV 16;
-          vibr_table2[chan].depth := HI(effect_table2[chan]) MOD 16;
-        end;
-
-      ef_Tremolo,
-      ef_ExtraFineTremolo:
-        begin
-          If (event[chan].effect2 <> 0) then
-            effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-          else If (eLo2[chan] in [ef_Tremolo,ef_ExtraFineTremolo]) and
-                  (eHi2[chan] <> 0) then
-                 effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
-               else effect_table2[chan] := event[chan].effect_def2;
-
-          If (event[chan].effect_def = ef_Extended) and
-             (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
-            trem_table2[chan].fine := TRUE;
-
-          trem_table2[chan].speed := HI(effect_table2[chan]) DIV 16;
-          trem_table2[chan].depth := HI(effect_table2[chan]) MOD 16;
-        end;
-
-      ef_VibratoVolSlide,
-      ef_VibratoVSlideFine:
-        begin
-          If (event[chan].effect2 <> 0) then
-            effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
-          else If (eLo2[chan] in [ef_VibratoVolSlide,ef_VibratoVSlideFine]) and
-                  (HI(effect_table2[chan]) <> 0) then
-                 effect_table2[chan] := concw(event[chan].effect_def2,HI(effect_table2[chan]))
-               else effect_table2[chan] := effect_table2[chan] AND $0ff00;
-
-          If (event[chan].effect_def = ef_Extended) and
-             (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
-            vibr_table2[chan].fine := TRUE;
-        end;
-
-      ef_SetCarrierVol:
-        set_ins_volume(BYTE_NULL,63-event[chan].effect2,chan);
-
-      ef_SetModulatorVol:
-        set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan);
-
-      ef_SetInsVolume:
-        If percussion_mode and (chan in [17..20]) then
-          set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan)
-        else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               set_ins_volume(BYTE_NULL,63-event[chan].effect2,chan)
-             else set_ins_volume(63-event[chan].effect2,63-event[chan].effect2,chan);
-
-      ef_ForceInsVolume:
-        If percussion_mode and (chan in [17..20]) then
-          set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan)
-        else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
-               set_ins_volume(scale_volume(ins_parameter(voice_table[chan],2) AND $3f,63-event[chan].effect2),63-event[chan].effect2,chan)
-             else set_ins_volume(63-event[chan].effect2,63-event[chan].effect2,chan);
-
-      ef_PositionJump:
-        If no_loop(chan,current_line) then
-          begin
-            pattern_break := TRUE;
-            next_line := pattern_break_flag+chan;
-          end;
-
-      ef_PatternBreak:
-        If no_loop(chan,current_line) then
-          begin
-            pattern_break := TRUE;
-            next_line := max(event[chan].effect2,PRED(songdata.patt_len));
-          end;
-
-      ef_SetSpeed:
-        speed := event[chan].effect2;
-
-      ef_SetTempo:
-        update_timer(event[chan].effect2);
-
-      ef_SetWaveform:
-        begin
-          If (event[chan].effect2 DIV 16 in [0..7]) then
-            begin
-              fmpar_table[chan].adsrw_car.wform := event[chan].effect2 DIV 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          If (event[chan].effect2 MOD 16 in [0..7]) then
-            begin
-              fmpar_table[chan].adsrw_mod.wform := event[chan].effect2 MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-        end;
-
-      ef_VolSlide:
-        effect_table2[chan] := concw(ef_VolSlide,event[chan].effect2);
-
-      ef_VolSlideFine:
-        effect_table2[chan] := concw(ef_VolSlideFine,event[chan].effect2);
-
-      ef_RetrigNote:
-        If (event[chan].effect2 <> 0) then
-          begin
-            If NOT (eLo2[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
-              retrig_table2[chan] := 1;
-            effect_table2[chan] := concw(ef_RetrigNote,event[chan].effect2);
-          end;
-
-      ef_SetGlobalVolume:
-        begin
-          global_volume := event[chan].effect2;
-          set_global_volume;
-        end;
-
-      ef_MultiRetrigNote:
-        If (event[chan].effect2 DIV 16 <> 0) then
-          begin
-            If NOT (eLo2[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
-              retrig_table2[chan] := 1;
-            effect_table2[chan] := concw(ef_MultiRetrigNote,event[chan].effect2);
-          end;
-
-      ef_Tremor:
-        If (event[chan].effect2 DIV 16 <> 0) and
-           (event[chan].effect2 MOD 16 <> 0) then
-        begin
-          If (eLo2[chan] <> ef_Tremor) then
-            begin
-              tremor_table2[chan].pos := 0;
-              tremor_table2[chan].volume := volume_table[chan];
-            end;
-          effect_table2[chan] := concw(ef_Tremor,event[chan].effect2);
-        end;
-
-      ef_Extended:
-        Case (event[chan].effect2 DIV 16) of
-          ef_ex_SetTremDepth:
-            Case (event[chan].effect2 MOD 16) of
-              0: begin
-                   opl3out(_instr[11],misc_register AND $07f);
-                   current_tremolo_depth := 0;
-                 end;
-
-              1: begin
-                   opl3out(_instr[11],misc_register OR $080);
-                   current_tremolo_depth := 1;
-                 end;
-            end;
-
-          ef_ex_SetVibDepth:
-            Case (event[chan].effect2 MOD 16) of
-              0: begin
-                   opl3out(_instr[11],misc_register AND $0bf);
-                   current_vibrato_depth := 0;
-                 end;
-
-              1: begin
-                   opl3out(_instr[11],misc_register OR $040);
-                   current_vibrato_depth := 1;
-                 end;
-            end;
-
-          ef_ex_SetAttckRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.attck := event[chan].effect2 MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetDecayRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.dec := event[chan].effect2 MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetSustnLevelM:
-            begin
-              fmpar_table[chan].adsrw_mod.sustn := event[chan].effect2 MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetRelRateM:
-            begin
-              fmpar_table[chan].adsrw_mod.rel := event[chan].effect2 MOD 16;
-              update_modulator_adsrw(chan);
-            end;
-
-          ef_ex_SetAttckRateC:
-            begin
-              fmpar_table[chan].adsrw_car.attck := event[chan].effect2 MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetDecayRateC:
-            begin
-              fmpar_table[chan].adsrw_car.dec := event[chan].effect2 MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetSustnLevelC:
-            begin
-              fmpar_table[chan].adsrw_car.sustn := event[chan].effect2 MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetRelRateC:
-            begin
-              fmpar_table[chan].adsrw_car.rel := event[chan].effect2 MOD 16;
-              update_carrier_adsrw(chan);
-            end;
-
-          ef_ex_SetFeedback:
-            begin
-              fmpar_table[chan].feedb := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex_SetPanningPos:
-            begin
-              panning_table[chan] := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex_PatternLoop,
-          ef_ex_PatternLoopRec:
-            If (event[chan].effect2 MOD 16 = 0) then
-              loopbck_table[chan] := current_line
-            else If (loopbck_table[chan] <> BYTE_NULL) then
-                   begin
-                     If (loop_table[chan][current_line] = BYTE_NULL) then
-                       loop_table[chan][current_line] := event[chan].effect2 MOD 16;
-                     If (loop_table[chan][current_line] <> 0) then
-                       begin
-                         pattern_break := TRUE;
-                         next_line := pattern_loop_flag+chan;
-                       end
-                     else If (event[chan].effect2 DIV 16 = ef_ex_PatternLoopRec) then
-                            loop_table[chan][current_line] := BYTE_NULL;
-                   end;
-
-          ef_ex_MacroKOffLoop:
-            If (event[chan].effect2 MOD 16 <> 0) then
-              keyoff_loop[chan] := TRUE
-            else keyoff_loop[chan] := FALSE;
-
-          ef_ex_ExtendedCmd:
-            Case (event[chan].effect2 MOD 16) of
-              ef_ex_cmd_RSS:        release_sustaining_sound(chan);
-              ef_ex_cmd_ResetVol:   reset_ins_volume(chan);
-              ef_ex_cmd_LockVol:    volume_lock  [chan] := TRUE;
-              ef_ex_cmd_UnlockVol:  volume_lock  [chan] := FALSE;
-              ef_ex_cmd_LockVP:     peak_lock    [chan] := TRUE;
-              ef_ex_cmd_UnlockVP:   peak_lock    [chan] := FALSE;
-              ef_ex_cmd_VSlide_def: volslide_type[chan] := 0;
-              ef_ex_cmd_LockPan:    pan_lock     [chan] := TRUE;
-              ef_ex_cmd_UnlockPan:  pan_lock     [chan] := FALSE;
-              ef_ex_cmd_VibrOff:    change_frequency(chan,freq_table[chan]);
-              ef_ex_cmd_TremOff:    set_ins_volume(LO(volume_table[chan]),
-                                                   HI(volume_table[chan]),chan);
-              ef_ex_cmd_VSlide_car:
-                If NOT ((event[chan].effect_def = ef_Extended) and
-                        (event[chan].effect = ef_ex_ExtendedCmd*16+
-                                        ef_ex_cmd_VSlide_mod)) then
-                  volslide_type[chan] := 1;
-
-              ef_ex_cmd_VSlide_mod:
-                If NOT ((event[chan].effect_def = ef_Extended) and
-                        (event[chan].effect = ef_ex_ExtendedCmd*16+
-                                        ef_ex_cmd_VSlide_car)) then
-                  volslide_type[chan] := 2;
-            end;
-        end;
-
-      ef_Extended2:
-        Case (event[chan].effect2 DIV 16) of
-          ef_ex2_PatDelayFrame,
-          ef_ex2_PatDelayRow:
-            begin
-              pattern_delay := TRUE;
-              If (event[chan].effect2 DIV 16 = ef_ex2_PatDelayFrame) then
-                tickD := (event[chan].effect2 MOD 16)
-              else tickD := speed*(event[chan].effect2 MOD 16);
-            end;
-
-          ef_ex2_NoteDelay:
-            begin
-              effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteDelay,0);
-              notedel_table[chan] := event[chan].effect2 MOD 16;
-            end;
-
-          ef_ex2_NoteCut:
-            begin
-              effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteCut,0);
-              notecut_table[chan] := event[chan].effect2 MOD 16;
-            end;
-
-          ef_ex2_FineTuneUp:
-            Inc(ftune_table[chan],event[chan].effect2 MOD 16);
-
-          ef_ex2_FineTuneDown:
-            Dec(ftune_table[chan],event[chan].effect2 MOD 16);
-
-          ef_ex2_GlVolSlideUp:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_GlVolSlideDn:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_GlVolSlideUpF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_GlVolSlideDnF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_GlVolSldUpXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_GlVolSldDnXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_VolSlideUpXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_VolSlideDnXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_FreqSlideUpXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
-                                         event[chan].effect2 MOD 16);
-          ef_ex2_FreqSlideDnXF:
-            effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
-                                         event[chan].effect2 MOD 16);
-        end;
-
-      ef_Extended3:
-        Case (event[chan].effect2 DIV 16) of
-          ef_ex3_SetConnection:
-            begin
-              fmpar_table[chan].connect := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetMultipM:
-            begin
-              fmpar_table[chan].multipM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKslM:
-            begin
-              fmpar_table[chan].kslM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetTremoloM:
-            begin
-              fmpar_table[chan].tremM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetVibratoM:
-            begin
-              fmpar_table[chan].vibrM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKsrM:
-            begin
-              fmpar_table[chan].ksrM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetSustainM:
-            begin
-              fmpar_table[chan].sustM := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetMultipC:
-            begin
-              fmpar_table[chan].multipC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKslC:
-            begin
-              fmpar_table[chan].kslC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetTremoloC:
-            begin
-              fmpar_table[chan].tremC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetVibratoC:
-            begin
-              fmpar_table[chan].vibrC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetKsrC:
-            begin
-              fmpar_table[chan].ksrC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-
-          ef_ex3_SetSustainC:
-            begin
-              fmpar_table[chan].sustC := event[chan].effect2 MOD 16;
-              update_fmpar(chan);
-            end;
-        end;
-    end;
-
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      If (event[chan].effect_def+event[chan].effect = 0) then
-        If (glfsld_table[chan] = 0) then effect_table[chan] := 0
-      else begin
-             event_table[chan].effect_def := event[chan].effect_def;
-             event_table[chan].effect := event[chan].effect;
-           end;
-
-      If (event[chan].effect_def2+event[chan].effect2 = 0) then
-        If (glfsld_table2[chan] = 0) then effect_table2[chan] := 0
-      else begin
-             event_table[chan].effect_def2 := event[chan].effect_def2;
-             event_table[chan].effect2 := event[chan].effect2;
-           end;
-
-      If (event[chan].note = event[chan].note OR keyoff_flag) then key_off(chan)
-      else If NOT (LO(effect_table[chan]) in  [ef_TonePortamento,
-                                               ef_TPortamVolSlide,
-                                               ef_TPortamVSlideFine,
-                                               ef_extended2+ef_fix2+ef_ex2_NoteDelay]) and
-              NOT (LO(effect_table2[chan]) in [ef_TonePortamento,
-                                               ef_TPortamVolSlide,
-                                               ef_TPortamVSlideFine,
-                                               ef_extended2+ef_fix2+ef_ex2_NoteDelay]) then
-             If NOT (((event[chan].effect_def2 = ef_SwapArpeggio) or
-                      (event[chan].effect_def2 = ef_SwapVibrato)) and
-                     (event[chan].effect_def = ef_Extended) and
-                     (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
-                     (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart)) and
-                NOT (((event[chan].effect_def = ef_SwapArpeggio) or
-                      (event[chan].effect_def = ef_SwapVibrato)) and
-                     (event[chan].effect_def2 = ef_Extended) and
-                     (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
-                     (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart)) then
-               output_note(event[chan].note,voice_table[chan],chan,TRUE)
-             else output_note_NR(event[chan].note,voice_table[chan],chan,TRUE)
-          else If (event[chan].note <> 0) and
-                  (event_table[chan].note = event_table[chan].note OR keyoff_flag) and
-                  ((event[chan].effect_def in [ef_TonePortamento,
-                                         ef_TPortamVolSlide,
-                                         ef_TPortamVSlideFine]) or
-                   (event[chan].effect_def2 in [ef_TonePortamento,
-                                          ef_TPortamVolSlide,
-                                          ef_TPortamVSlideFine])) then
-                 output_note(event_table[chan].note AND NOT keyoff_flag,voice_table[chan],chan,FALSE)
-               else If (event[chan].note <> 0) then
-                      event_table[chan].note := event[chan].note;
-
-      Case event[chan].effect_def of
-        ef_SwapArpeggio:
-          begin
-            If (event[chan].effect_def2 = ef_Extended) and
-               (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
-               (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart) then
-              begin
-                If (macro_table[chan].arpg_pos >
-                    songdata.macro_table[event[chan].effect].arpeggio.length) then
-                  macro_table[chan].arpg_pos :=
-                    songdata.macro_table[event[chan].effect].arpeggio.length;
-                macro_table[chan].arpg_table := event[chan].effect;
-              end
-            else begin
-                   macro_table[chan].arpg_count := 1;
-                   macro_table[chan].arpg_pos := 0;
-                   macro_table[chan].arpg_table := event[chan].effect;
-                   macro_table[chan].arpg_note := event_table[chan].note;
-                 end;
-          end;
-
-        ef_SwapVibrato:
-          begin
-            If (event[chan].effect_def2 = ef_Extended) and
-               (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
-               (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart) then
-              begin
-                If (macro_table[chan].vib_table >
-                    songdata.macro_table[event[chan].effect].vibrato.length) then
-                  macro_table[chan].vib_pos :=
-                    songdata.macro_table[event[chan].effect].vibrato.length;
-                macro_table[chan].vib_table := event[chan].effect;
-              end
-            else begin
-                   macro_table[chan].vib_count := 1;
-                   macro_table[chan].vib_pos := 0;
-                   macro_table[chan].vib_table := event[chan].effect;
-                   macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
-                 end;
-          end;
-
-        ef_SetCustomSpeedTab:
-          generate_custom_vibrato(event[chan].effect);
-      end;
-
-      Case event[chan].effect_def2 of
-        ef_SwapArpeggio:
-          begin
-            If (event[chan].effect_def = ef_Extended) and
-               (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
-               (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart) then
-              begin
-                If (macro_table[chan].arpg_pos >
-                    songdata.macro_table[event[chan].effect2].arpeggio.length) then
-                  macro_table[chan].arpg_pos :=
-                    songdata.macro_table[event[chan].effect2].arpeggio.length;
-                macro_table[chan].arpg_table := event[chan].effect2;
-              end
-            else begin
-                   macro_table[chan].arpg_count := 1;
-                   macro_table[chan].arpg_pos := 0;
-                   macro_table[chan].arpg_table := event[chan].effect2;
-                   macro_table[chan].arpg_note := event_table[chan].note;
-                 end;
-          end;
-
-        ef_SwapVibrato:
-          begin
-            If (event[chan].effect_def = ef_Extended) and
-               (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
-               (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart) then
-              begin
-                If (macro_table[chan].vib_table >
-                    songdata.macro_table[event[chan].effect2].vibrato.length) then
-                  macro_table[chan].vib_pos :=
-                    songdata.macro_table[event[chan].effect2].vibrato.length;
-                macro_table[chan].vib_table := event[chan].effect2;
-              end
-            else begin
-                   macro_table[chan].vib_count := 1;
-                   macro_table[chan].vib_pos := 0;
-                   macro_table[chan].vib_table := event[chan].effect2;
-                   macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
-                 end;
-          end;
-
-        ef_SetCustomSpeedTab:
-          generate_custom_vibrato(event[chan].effect2);
-      end;
-
-      update_fine_effects(chan);
-    end;
-
-  If pattern_delay then
-    begin
-      time_playing := time_playing+1/tempo*tickD;
-      If (time_playing > 3600-1) then time_playing := 0;
-    end
-  else begin
-         time_playing := time_playing+1/tempo*speed;
-         If (time_playing > 3600-1) then time_playing := 0;
-       end;
-end;
-
-procedure portamento_up(chan: Byte; slide: Word; limit: Word);
-
-var
-  freq: Word;
-
-begin
-  freq := calc_freq_shift_up(freq_table[chan] AND $1fff,slide);
-  If (freq <= limit) then change_frequency(chan,freq)
-  else change_frequency(chan,limit);
-end;
-
-procedure portamento_down(chan: Byte; slide: Word; limit: Word);
-
-var
-  freq: Word;
-
-begin
-  freq := calc_freq_shift_down(freq_table[chan] AND $1fff,slide);
-  If (freq >= limit) then change_frequency(chan,freq)
-  else change_frequency(chan,limit);
-end;
-
-procedure macro_vibrato__porta_up(chan: Byte; depth: Byte);
-
-var
-  freq: Word;
-
-begin
-  freq := calc_freq_shift_up(macro_table[chan].vib_freq AND $1fff,depth);
-  If (freq <= nFreq(12*8+1)) then change_freq(chan,freq)
-  else change_freq(chan,nFreq(12*8+1));
-end;
-
-procedure macro_vibrato__porta_down(chan: Byte; depth: Byte);
-
-var
-  freq: Word;
-
-begin
-  freq := calc_freq_shift_down(macro_table[chan].vib_freq AND $1fff,depth);
-  If (freq >= nFreq(0)) then change_freq(chan,freq)
-  else change_freq(chan,nFreq(0));
-end;
-
-procedure tone_portamento(chan: Byte);
-begin
-  If (freq_table[chan] AND $1fff > porta_table[chan].freq) then
-    portamento_down(chan,porta_table[chan].speed,porta_table[chan].freq)
-  else If (freq_table[chan] AND $1fff < porta_table[chan].freq) then
-         portamento_up(chan,porta_table[chan].speed,porta_table[chan].freq);
-end;
-
-procedure tone_portamento2(chan: Byte);
-begin
-  If (freq_table[chan] AND $1fff > porta_table2[chan].freq) then
-    portamento_down(chan,porta_table2[chan].speed,porta_table2[chan].freq)
-  else If (freq_table[chan] AND $1fff < porta_table2[chan].freq) then
-         portamento_up(chan,porta_table2[chan].speed,porta_table2[chan].freq);
-end;
-
-procedure slide_volume_up(chan,slide: Byte);
-
-var
-  temp: Word;
-  limit1,limit2,vLo,vHi: Byte;
-
-procedure slide_carrier_volume_up;
-begin
-  vLo := LO(temp);
-  vHi := HI(temp);
-  If (vHi-slide >= limit1) then temp := concw(vLo,vHi-slide)
-  else temp := concw(vLo,limit1);
-  set_ins_volume(BYTE_NULL,HI(temp),chan);
-  volume_table[chan] := temp;
-end;
-
-procedure slide_modulator_volume_up;
-begin
-  vLo := LO(temp);
-  vHi := HI(temp);
-  If (vLo-slide >= limit2) then temp := concw(vLo-slide,vHi)
-  else temp := concw(limit2,vHi);
-  set_ins_volume(LO(temp),BYTE_NULL,chan);
-  volume_table[chan] := temp;
-end;
-
-begin
-  If NOT peak_lock[chan] then limit1 := 0
-  else limit1 := ins_parameter(event_table[chan].instr_def,3) AND $3f;
-
-  If NOT peak_lock[chan] then limit2 := 0
-  else limit2 := ins_parameter(event_table[chan].instr_def,2) AND $3f;
-  temp := volume_table[chan];
-
-  Case volslide_type[chan] of
-    0: begin
-         slide_carrier_volume_up;
-         If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
-            (percussion_mode and (chan in [17..20])) then
-           slide_modulator_volume_up;
-       end;
-    1: slide_carrier_volume_up;
-    2: slide_modulator_volume_up;
-    3: begin
-         slide_carrier_volume_up;
-         slide_modulator_volume_up;
-       end;
-  end;
-end;
-
-procedure slide_volume_down(chan,slide: Byte);
-
-var
-  temp: Word;
-  vLo,vHi: Byte;
-
-procedure slide_carrier_volume_down;
-begin
-  vLo := LO(temp);
-  vHi := HI(temp);
-  If (vHi+slide <= 63) then temp := concw(vLo,vHi+slide)
-  else temp := concw(vLo,63);
-  set_ins_volume(BYTE_NULL,HI(temp),chan);
-  volume_table[chan] := temp;
-end;
-
-procedure slide_modulator_volume_down;
-begin
-  vLo := LO(temp);
-  vHi := HI(temp);
-  If (vLo+slide <= 63) then temp := concw(vLo+slide,vHi)
-  else temp := concw(63,vHi);
-  set_ins_volume(LO(temp),BYTE_NULL,chan);
-  volume_table[chan] := temp;
-end;
-
-begin
-  temp := volume_table[chan];
-  Case volslide_type[chan] of
-    0: begin
-         slide_carrier_volume_down;
-         If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
-            (percussion_mode and (chan in [17..20])) then
-           slide_modulator_volume_down;
-       end;
-    1: slide_carrier_volume_down;
-    2: slide_modulator_volume_down;
-    3: begin
-         slide_carrier_volume_down;
-         slide_modulator_volume_down;
-       end;
-  end;
-end;
-
-procedure volume_slide(chan,up_speed,down_speed: Byte);
-begin
-  If (up_speed <> 0) then slide_volume_up(chan,up_speed)
-  else If (down_speed <> 0) then slide_volume_down(chan,down_speed);
-end;
-
-procedure global_volume_slide(up_speed,down_speed: Byte);
-begin
-  If (up_speed <> BYTE_NULL) then
-    global_volume := max(global_volume+up_speed,63);
-  If (down_speed <> BYTE_NULL) then
-    If (global_volume >= down_speed) then Dec(global_volume,down_speed)
-    else global_volume := 0;
-  set_global_volume;
-end;
-
-procedure arpeggio(chan: Byte);
-
-const
-  arpgg_state: array[0..2] of Byte = (1,2,0);
-
-var
-  freq: Word;
-
-begin
-  Case arpgg_table[chan].state of
-    0: freq := nFreq(arpgg_table[chan].note-1);
-    1: freq := nFreq(arpgg_table[chan].note-1 +arpgg_table[chan].add1);
-    2: freq := nFreq(arpgg_table[chan].note-1 +arpgg_table[chan].add2);
-  end;
-
-  arpgg_table[chan].state := arpgg_state[arpgg_table[chan].state];
-  change_frequency(chan,freq+
-    SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-end;
-
-procedure arpeggio2(chan: Byte);
-
-const
-  arpgg_state: array[0..2] of Byte = (1,2,0);
-
-var
-  freq: Word;
-
-begin
-  Case arpgg_table2[chan].state of
-    0: freq := nFreq(arpgg_table2[chan].note-1);
-    1: freq := nFreq(arpgg_table2[chan].note-1 +arpgg_table2[chan].add1);
-    2: freq := nFreq(arpgg_table2[chan].note-1 +arpgg_table2[chan].add2);
-  end;
-
-  arpgg_table2[chan].state := arpgg_state[arpgg_table2[chan].state];
-  change_frequency(chan,freq+
-    SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-end;
-
-procedure vibrato(chan: Byte);
-
-var
-  freq,old_freq: Word;
-  direction: Byte;
-
-begin
-  Inc(vibr_table[chan].pos,vibr_table[chan].speed*vibtrem_speed_factor);
-  freq := calc_vibtrem_shift(vibr_table[chan].depth,
-                             vibr_table[chan].pos,direction);
-  old_freq := freq_table[chan];
-  If (direction = 0) then portamento_down(chan,freq,nFreq(0))
-  else portamento_up(chan,freq,nFreq(12*8+1));
-  freq_table[chan] := old_freq;
-end;
-
-procedure vibrato2(chan: Byte);
-
-var
-  freq,old_freq: Word;
-  direction: Byte;
-
-begin
-  Inc(vibr_table2[chan].pos,vibr_table2[chan].speed*vibtrem_speed_factor);
-  freq := calc_vibtrem_shift(vibr_table2[chan].depth,
-                             vibr_table2[chan].pos,direction);
-  old_freq := freq_table[chan];
-  If (direction = 0) then portamento_down(chan,freq,nFreq(0))
-  else portamento_up(chan,freq,nFreq(12*8+1));
-  freq_table[chan] := old_freq;
-end;
-
-procedure tremolo(chan: Byte);
-
-var
-  vol,old_vol: Word;
-  direction: Byte;
-
-begin
-  Inc(trem_table[chan].pos,trem_table[chan].speed*vibtrem_speed_factor);
-  vol := calc_vibtrem_shift(trem_table[chan].depth,
-                            trem_table[chan].pos,direction);
-  old_vol := volume_table[chan];
-  If (direction = 0) then slide_volume_down(chan,vol)
-  else slide_volume_up(chan,vol);
-  volume_table[chan] := old_vol;
-end;
-
-procedure tremolo2(chan: Byte);
-
-var
-  vol,old_vol: Word;
-  direction: Byte;
-
-begin
-  Inc(trem_table2[chan].pos,trem_table2[chan].speed*vibtrem_speed_factor);
-  vol := calc_vibtrem_shift(trem_table2[chan].depth,
-                            trem_table2[chan].pos,direction);
-  old_vol := volume_table[chan];
-  If (direction = 0) then slide_volume_down(chan,vol)
-  else slide_volume_up(chan,vol);
-  volume_table[chan] := old_vol;
-end;
-
-procedure update_effects;
-
-var
-  chan,eLo,eHi,
-  eLo2,eHi2: Byte;
-
-function chanvol(chan: Byte): Byte;
-begin
-  If (ins_parameter(voice_table[chan],10) AND 1 = 0) then chanvol := 63-HI(volume_table[chan])
-  else chanvol := 63-Round((LO(volume_table[chan])+HI(volume_table[chan]))/2);
-end;
-
-begin
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      eLo  := LO(effect_table[chan]);
-      eHi  := HI(effect_table[chan]);
-      eLo2 := LO(effect_table2[chan]);
-      eHi2 := HI(effect_table2[chan]);
-
-      Case eLo of
-        ef_Arpeggio+ef_fix1:
-          arpeggio(chan);
-
-        ef_ArpggVSlide:
-          begin
-            volume_slide(chan,eHi DIV 16,eHi MOD 16);
-            arpeggio(chan);
-          end;
-
-        ef_ArpggVSlideFine:
-          arpeggio(chan);
-
-        ef_FSlideUp:
-          portamento_up(chan,eHi,nFreq(12*8+1));
-
-        ef_FSlideDown:
-          portamento_down(chan,eHi,nFreq(0));
-
-        ef_FSlideUpVSlide:
-          begin
-            portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
-            volume_slide(chan,eHi DIV 16,eHi MOD 16);
-          end;
-
-        ef_FSlUpVSlF:
-          portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
-
-        ef_FSlideDownVSlide:
-          begin
-            portamento_down(chan,fslide_table[chan],nFreq(0));
-            volume_slide(chan,eHi DIV 16,eHi MOD 16);
-          end;
-
-        ef_FSlDownVSlF:
-          portamento_down(chan,fslide_table[chan],nFreq(0));
-
-        ef_FSlUpFineVSlide:
-          volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-        ef_FSlDownFineVSlide:
-          volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-        ef_TonePortamento:
-          tone_portamento(chan);
-
-        ef_TPortamVolSlide:
-          begin
-            volume_slide(chan,eHi DIV 16,eHi MOD 16);
-            tone_portamento(chan);
-          end;
-
-        ef_TPortamVSlideFine:
-          tone_portamento(chan);
-
-        ef_Vibrato:
-          If NOT vibr_table[chan].fine then
-            vibrato(chan);
-
-        ef_Tremolo:
-          If NOT trem_table[chan].fine then
-            tremolo(chan);
-
-        ef_VibratoVolSlide:
-          begin
-            volume_slide(chan,eHi DIV 16,eHi MOD 16);
-            If NOT vibr_table[chan].fine then
-              vibrato(chan);
-          end;
-
-        ef_VibratoVSlideFine:
-          If NOT vibr_table[chan].fine then
-            vibrato(chan);
-
-        ef_VolSlide:
-          volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-        ef_RetrigNote:
-          If (retrig_table[chan] >= eHi) then
-            begin
-              retrig_table[chan] := 0;
-              output_note(event_table[chan].note,
-                          event_table[chan].instr_def,chan,TRUE);
-            end
-          else Inc(retrig_table[chan]);
-
-        ef_MultiRetrigNote:
-          If (retrig_table[chan] >= eHi DIV 16) then
-            begin
-              Case eHi MOD 16 of
-                0,8: ;
-
-                1: slide_volume_down(chan,1);
-                2: slide_volume_down(chan,2);
-                3: slide_volume_down(chan,4);
-                4: slide_volume_down(chan,8);
-                5: slide_volume_down(chan,16);
-
-                9: slide_volume_up(chan,1);
-               10: slide_volume_up(chan,2);
-               11: slide_volume_up(chan,4);
-               12: slide_volume_up(chan,8);
-               13: slide_volume_up(chan,16);
-
-
-                6: slide_volume_down(chan,chanvol(chan)-
-                                          Round(chanvol(chan)*2/3));
-                7: slide_volume_down(chan,chanvol(chan)-
-                                          Round(chanvol(chan)*1/2));
-
-               14: slide_volume_up(chan,max(Round(chanvol(chan)*3/2)-
-                                            chanvol(chan),63));
-               15: slide_volume_up(chan,max(Round(chanvol(chan)*2)-
-                                            chanvol(chan),63));
-              end;
-
-             retrig_table[chan] := 0;
-             output_note(event_table[chan].note,
-                         event_table[chan].instr_def,chan,TRUE);
-            end
-          else Inc(retrig_table[chan]);
-
-        ef_Tremor:
-          If (tremor_table[chan].pos >= 0) then
-            begin
-              If (SUCC(tremor_table[chan].pos) <= eHi DIV 16) then
-                Inc(tremor_table[chan].pos)
-              else begin
-                     slide_volume_down(chan,63);
-                     tremor_table[chan].pos := -1;
-                   end;
-            end
-          else If (PRED(tremor_table[chan].pos) >= -(eHi MOD 16)) then
-                 Dec(tremor_table[chan].pos)
-               else begin
-                      set_ins_volume(LO(tremor_table[chan].volume),
-                                     HI(tremor_table[chan].volume),chan);
-                      tremor_table[chan].pos := 1;
-                    end;
-
-        ef_extended2+ef_fix2+ef_ex2_NoteDelay:
-          If (notedel_table[chan] = 0) then
-            begin
-              notedel_table[chan] := BYTE_NULL;
-              output_note(event_table[chan].note,
-                          event_table[chan].instr_def,chan,TRUE);
-            end
-          else Dec(notedel_table[chan]);
-
-        ef_extended2+ef_fix2+ef_ex2_NoteCut:
-          If (notecut_table[chan] = 0) then
-            begin
-              notecut_table[chan] := BYTE_NULL;
-              key_off(chan);
-            end
-          else Dec(notecut_table[chan]);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp:
-          global_volume_slide(eHi,BYTE_NULL);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn:
-          global_volume_slide(BYTE_NULL,eHi);
-      end;
-
-      Case eLo2 of
-        ef_Arpeggio+ef_fix1:
-          arpeggio2(chan);
-
-        ef_ArpggVSlide:
-          begin
-            volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-            arpeggio2(chan);
-          end;
-
-        ef_ArpggVSlideFine:
-          arpeggio2(chan);
-
-        ef_FSlideUp:
-          portamento_up(chan,eHi2,nFreq(12*8+1));
-
-        ef_FSlideDown:
-          portamento_down(chan,eHi2,nFreq(0));
-
-        ef_FSlideUpVSlide:
-          begin
-            portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
-            volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-          end;
-
-        ef_FSlUpVSlF:
-          portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
-
-        ef_FSlideDownVSlide:
-          begin
-            portamento_down(chan,fslide_table2[chan],nFreq(0));
-            volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-          end;
-
-        ef_FSlDownVSlF:
-          portamento_down(chan,fslide_table2[chan],nFreq(0));
-
-        ef_FSlUpFineVSlide:
-          volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-        ef_FSlDownFineVSlide:
-          volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-        ef_TonePortamento:
-          tone_portamento2(chan);
-
-        ef_TPortamVolSlide:
-          begin
-            volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-            tone_portamento2(chan);
-          end;
-
-        ef_TPortamVSlideFine:
-          tone_portamento2(chan);
-
-        ef_Vibrato:
-          If NOT vibr_table2[chan].fine then
-            vibrato2(chan);
-
-        ef_Tremolo:
-          If NOT trem_table2[chan].fine then
-            tremolo2(chan);
-
-        ef_VibratoVolSlide:
-          begin
-            volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-            If NOT vibr_table2[chan].fine then
-              vibrato2(chan);
-          end;
-
-        ef_VibratoVSlideFine:
-          If NOT vibr_table2[chan].fine then
-            vibrato2(chan);
-
-        ef_VolSlide:
-          volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-        ef_RetrigNote:
-          If (retrig_table2[chan] >= eHi2) then
-            begin
-              retrig_table2[chan] := 0;
-              output_note(event_table[chan].note,
-                          event_table[chan].instr_def,chan,TRUE);
-            end
-          else Inc(retrig_table2[chan]);
-
-        ef_MultiRetrigNote:
-          If (retrig_table2[chan] >= eHi2 DIV 16) then
-            begin
-              Case eHi2 MOD 16 of
-                0,8: ;
-
-                1: slide_volume_down(chan,1);
-                2: slide_volume_down(chan,2);
-                3: slide_volume_down(chan,4);
-                4: slide_volume_down(chan,8);
-                5: slide_volume_down(chan,16);
-
-                9: slide_volume_up(chan,1);
-               10: slide_volume_up(chan,2);
-               11: slide_volume_up(chan,4);
-               12: slide_volume_up(chan,8);
-               13: slide_volume_up(chan,16);
-
-
-                6: slide_volume_down(chan,chanvol(chan)-
-                                          Round(chanvol(chan)*2/3));
-                7: slide_volume_down(chan,chanvol(chan)-
-                                          Round(chanvol(chan)*1/2));
-
-               14: slide_volume_up(chan,max(Round(chanvol(chan)*3/2)-
-                                            chanvol(chan),63));
-               15: slide_volume_up(chan,max(Round(chanvol(chan)*2)-
-                                            chanvol(chan),63));
-              end;
-
-              retrig_table2[chan] := 0;
-              output_note(event_table[chan].note,
-                          event_table[chan].instr_def,chan,TRUE);
-            end
-          else Inc(retrig_table2[chan]);
-
-        ef_Tremor:
-          If (tremor_table2[chan].pos >= 0) then
-            begin
-              If (SUCC(tremor_table2[chan].pos) <= eHi2 DIV 16) then
-                Inc(tremor_table2[chan].pos)
-              else begin
-                     slide_volume_down(chan,63);
-                     tremor_table2[chan].pos := -1;
-                   end;
-            end
-          else If (PRED(tremor_table2[chan].pos) >= -(eHi2 MOD 16)) then
-                 Dec(tremor_table2[chan].pos)
-               else begin
-                      set_ins_volume(LO(tremor_table2[chan].volume),
-                                     HI(tremor_table2[chan].volume),chan);
-                      tremor_table2[chan].pos := 1;
-                    end;
-
-        ef_extended2+ef_fix2+ef_ex2_NoteDelay:
-          If (notedel_table[chan] = 0) then
-            begin
-              notedel_table[chan] := BYTE_NULL;
-              output_note(event_table[chan].note,
-                          event_table[chan].instr_def,chan,TRUE);
-            end
-          else Dec(notedel_table[chan]);
-
-        ef_extended2+ef_fix2+ef_ex2_NoteCut:
-          If (notecut_table[chan] = 0) then
-            begin
-              notecut_table[chan] := BYTE_NULL;
-              key_off(chan);
-            end
-          else Dec(notecut_table[chan]);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp:
-          global_volume_slide(eHi2,BYTE_NULL);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn:
-          global_volume_slide(BYTE_NULL,eHi2);
-      end;
-    end;
-end;
-
-procedure update_fine_effects(chan: Byte);
-
-var
-  eLo,eHi,
-  eLo2,eHi2: Byte;
-
-begin
-  eLo  := LO(effect_table[chan]);
-  eHi  := HI(effect_table[chan]);
-  eLo2 := LO(effect_table2[chan]);
-  eHi2 := HI(effect_table2[chan]);
-
-  Case eLo of
-    ef_ArpggVSlideFine:
-      volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-    ef_FSlideUpFine:
-      portamento_up(chan,eHi,nFreq(12*8+1));
-
-    ef_FSlideDownFine:
-      portamento_down(chan,eHi,nFreq(0));
-
-    ef_FSlUpVSlF:
-      volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-    ef_FSlDownVSlF:
-      volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-    ef_FSlUpFineVSlide:
-      portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
-
-    ef_FSlUpFineVSlF:
-      begin
-        portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
-        volume_slide(chan,eHi DIV 16,eHi MOD 16);
-      end;
-
-    ef_FSlDownFineVSlide:
-      portamento_down(chan,fslide_table[chan],nFreq(0));
-
-    ef_FSlDownFineVSlF:
-      begin
-        portamento_down(chan,fslide_table[chan],nFreq(0));
-        volume_slide(chan,eHi DIV 16,eHi MOD 16);
-      end;
-
-    ef_TPortamVSlideFine:
-      volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-    ef_Vibrato:
-      If vibr_table[chan].fine then
-        vibrato(chan);
-
-    ef_Tremolo:
-      If trem_table[chan].fine then
-        tremolo(chan);
-
-    ef_VibratoVolSlide:
-      If vibr_table[chan].fine then
-        vibrato(chan);
-
-    ef_VibratoVSlideFine:
-      begin
-        volume_slide(chan,eHi DIV 16,eHi MOD 16);
-        If vibr_table[chan].fine then
-          vibrato(chan);
-      end;
-
-    ef_VolSlideFine:
-      volume_slide(chan,eHi DIV 16,eHi MOD 16);
-
-    ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF:
-      global_volume_slide(eHi,BYTE_NULL);
-
-    ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF:
-      global_volume_slide(BYTE_NULL,eHi);
-  end;
-
-  Case eLo2 of
-    ef_ArpggVSlideFine:
-      volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-    ef_FSlideUpFine:
-      portamento_up(chan,eHi2,nFreq(12*8+1));
-
-    ef_FSlideDownFine:
-      portamento_down(chan,eHi2,nFreq(0));
-
-    ef_FSlUpVSlF:
-      volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-    ef_FSlDownVSlF:
-      volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-    ef_FSlUpFineVSlide:
-      portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
-
-    ef_FSlUpFineVSlF:
-      begin
-        portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
-        volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-      end;
-
-    ef_FSlDownFineVSlide:
-      portamento_down(chan,fslide_table2[chan],nFreq(0));
-
-    ef_FSlDownFineVSlF:
-      begin
-        portamento_down(chan,fslide_table2[chan],nFreq(0));
-        volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-      end;
-
-    ef_TPortamVSlideFine:
-      volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-    ef_Vibrato:
-      If vibr_table2[chan].fine then
-        vibrato2(chan);
-
-    ef_Tremolo:
-      If trem_table2[chan].fine then
-        tremolo2(chan);
-
-    ef_VibratoVolSlide:
-      If vibr_table2[chan].fine then
-        vibrato2(chan);
-
-    ef_VibratoVSlideFine:
-      begin
-        volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-        If vibr_table2[chan].fine then
-          vibrato2(chan);
-      end;
-
-    ef_VolSlideFine:
-      volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
-
-    ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF:
-      global_volume_slide(eHi2,BYTE_NULL);
-
-    ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF:
-      global_volume_slide(BYTE_NULL,eHi2);
-  end;
-end;
-
-procedure update_extra_fine_effects;
-
-var
-  chan,eLo,eHi,
-  eLo2,eHi2: Byte;
-
-begin
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      eLo  := LO(effect_table[chan]);
-      eHi  := HI(effect_table[chan]);
-      eLo2 := LO(effect_table2[chan]);
-      eHi2 := HI(effect_table2[chan]);
-
-      Case eLo of
-        ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF:
-          global_volume_slide(eHi,BYTE_NULL);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF:
-          global_volume_slide(BYTE_NULL,eHi);
-
-        ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF:
-          volume_slide(chan,eHi,0);
-
-        ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF:
-          volume_slide(chan,0,eHi);
-
-        ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF:
-          portamento_up(chan,eHi,nFreq(12*8+1));
-
-        ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF:
-          portamento_down(chan,eHi,nFreq(0));
-
-        ef_ExtraFineArpeggio:
-          arpeggio(chan);
-
-        ef_ExtraFineVibrato:
-          If NOT vibr_table[chan].fine then
-            vibrato(chan);
-
-        ef_ExtraFineTremolo:
-          If NOT trem_table[chan].fine then
-            tremolo(chan);
-      end;
-
-      Case eLo2 of
-        ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF:
-          global_volume_slide(eHi2,BYTE_NULL);
-
-        ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF:
-          global_volume_slide(BYTE_NULL,eHi2);
-
-        ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF:
-          volume_slide(chan,eHi2,0);
-
-        ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF:
-          volume_slide(chan,0,eHi2);
-
-        ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF:
-          portamento_up(chan,eHi2,nFreq(12*8+1));
-
-        ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF:
-          portamento_down(chan,eHi2,nFreq(0));
-
-        ef_ExtraFineArpeggio:
-          arpeggio2(chan);
-
-        ef_ExtraFineVibrato:
-          If NOT vibr_table2[chan].fine then
-            vibrato2(chan);
-
-        ef_ExtraFineTremolo:
-          If NOT trem_table2[chan].fine then
-            tremolo2(chan);
-      end;
-    end;
-end;
-
-function calc_following_order(order: Byte): Integer;
-
-var
-  result: Integer;
-  index,jump_count: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:calc_following_order';
-  result := -1;
-  index := order;
-  jump_count := 0;
-
-  Repeat
-    If (songdata.pattern_order[index] < $80) then result := index
-    else begin
-           index := songdata.pattern_order[index]-$80;
-           Inc(jump_count);
-         end;
-  until (jump_count > $7f) or
-        (result <> -1);
-
-  calc_following_order := result;
-end;
-
-function calc_order_jump: Integer;
-
-var
-  temp: Byte;
-  result: Integer;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:calc_order_jump';
-  result := 0;
-  temp := 0;
-
-  Repeat
-    If (songdata.pattern_order[current_order] > $7f) then
-      current_order := songdata.pattern_order[current_order]-$80;
-    Inc(temp);
-  until (temp > $7f) or (songdata.pattern_order[current_order] < $80);
-
-  If (temp > $7f) then begin stop_playing; result := -1; end;
-  calc_order_jump := result;
-end;
-
-procedure update_song_position;
-
-var
-  temp: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:update_song_position';
-  If (current_line < PRED(songdata.patt_len)) and NOT pattern_break then Inc(current_line)
-  else begin
-         If NOT (pattern_break and (next_line AND $0f0 = pattern_loop_flag)) and
-                (current_order < $7f) then
-           begin
-             FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
-             FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
-             Inc(current_order);
-           end;
-
-         If pattern_break and (next_line AND $0f0 = pattern_loop_flag) then
-           begin
-             temp := next_line-pattern_loop_flag;
-             next_line := loopbck_table[temp];
-             If (loop_table[temp][current_line] <> 0) then
-               Dec(loop_table[temp][current_line]);
-           end
-         else If pattern_break and (next_line AND $0f0 = pattern_break_flag) then
-                begin
-                  current_order := event_table[next_line-pattern_break_flag].effect;
-                  pattern_break := FALSE;
-                end
-              else If (current_order > $7f) then
-                     current_order := 0;
-
-         If (songdata.pattern_order[current_order] > $7f) then
-           If (calc_order_jump = -1) then EXIT;
-
-         current_pattern := songdata.pattern_order[current_order];
-         If NOT pattern_break then current_line := 0
-         else begin
-                pattern_break := FALSE;
-                current_line := next_line;
-              end;
-       end;
-
-  For temp := 1 to songdata.nm_tracks do
-    begin
-      glfsld_table[temp] := 0;
-      glfsld_table2[temp] := 0;
-    end;
-
-  If (current_line = 0) and
-     (current_order = calc_following_order(0)) and speed_update then
-    begin
-      tempo := songdata.tempo;
-      speed := songdata.speed;
-      update_timer(tempo);
-    end;
-end;
-
-procedure poll_proc;
-
-var
-  temp: Byte;
-
-var
-  _debug_str_bak_: String;
-
-begin
-  _debug_str_bak_ := _debug_str_;
-  _debug_str_ := 'A2PLAYER.PAS:_poll_proc';
-
-  If (NOT pattern_delay and (ticks-tick0+1 >= speed)) or
-     fast_forward then
-    begin
-      If (songdata.pattern_order[current_order] > $7f) then
-        If (calc_order_jump = -1) then EXIT;
-
-      current_pattern := songdata.pattern_order[current_order];
-      play_line;
-      If NOT fast_forward then update_effects
-      else For temp := 1 to speed do
-             begin
-               update_effects;
-               If (temp MOD 4 = temp) then
-                 update_extra_fine_effects;
-               Inc(ticks);
-             end;
-
-      If fast_forward or NOT pattern_delay then
-        update_song_position;
-
-      tick0 := ticks;
-      If fast_forward then
-        If NOT pattern_delay then synchronize_song_timer;
-
-      If fast_forward and pattern_delay then
-        begin
-          tickD := 0;
-          pattern_delay := FALSE;
-        end;
-
-      If fast_forward then fast_forward := FALSE;
-    end
-  else
-    begin
-      update_effects;
-      Inc(ticks);
-      If pattern_delay and (tickD > 1) then Dec(tickD)
-      else begin
-             If pattern_delay then
-               begin
-                 tick0 := ticks;
-                 update_song_position;
-               end;
-             pattern_delay := FALSE;
-           end;
-    end;
-
-  Inc(tickXF);
-  If (tickXF MOD 4 = 0) then
-    begin
-      update_extra_fine_effects;
-      Dec(tickXF,4);
-    end;
-  _debug_str_ := _debug_str_bak_;
-end;
-
-procedure macro_poll_proc;
-
-const
-  IDLE = $0fff;
-  FINISHED = $0ffff;
-
-var
-  chan: Byte;
-  finished_flag: Word;
-
-var
-  _debug_str_bak_: String;
-
-function _ins_adsr_data_empty(ins: Byte): Boolean;
-begin
-  _ins_adsr_data_empty :=
-    (ins_parameter(ins,5) SHR 4 = 0) and
-    (ins_parameter(ins,4) SHR 4 = 0) and
-    (ins_parameter(ins,5) AND $0f = 0) and
-    (ins_parameter(ins,4) AND $0f = 0) and
-    (ins_parameter(ins,7) SHR 4 = 0) and
-    (ins_parameter(ins,6) SHR 4 = 0) and
-    (ins_parameter(ins,7) AND $0f = 0) and
-    (ins_parameter(ins,6) AND $0f = 0);
-end;
-
-begin
-  _debug_str_bak_ := _debug_str_;
-  _debug_str_ := 'ADT2UNIT.PAS:macro_poll_proc';
-  For chan := 1 to songdata.nm_tracks do
-    begin
-      If NOT keyoff_loop[chan] then finished_flag := FINISHED
-      else finished_flag := IDLE;
-
-      With macro_table[chan] do
-        begin
-          With songdata.instr_macros[fmreg_table] do
-            If (fmreg_table <> 0) and (speed <> 0) then
-              If (fmreg_duration > 1) then Dec(fmreg_duration)
-              else begin
-                     fmreg_count := 1;
-                     If (fmreg_pos <= length) then
-                       If (loop_begin <> 0) and (loop_length <> 0) then
-                         If (fmreg_pos = loop_begin+PRED(loop_length)) then
-                           fmreg_pos := loop_begin
-                         else If (fmreg_pos < length) then Inc(fmreg_pos)
-                              else fmreg_pos := finished_flag
-                       else If (fmreg_pos < length) then Inc(fmreg_pos)
-                            else fmreg_pos := finished_flag
-                     else fmreg_pos := finished_flag;
-
-                     If (freq_table[chan] OR $2000 = freq_table[chan]) and
-                        (keyoff_pos <> 0) and
-                        (fmreg_pos >= keyoff_pos) then
-                       fmreg_pos := IDLE
-                     else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
-                             (fmreg_pos <> 0) and (keyoff_pos <> 0) and
-                             ((fmreg_pos < keyoff_pos) or (fmreg_pos = IDLE)) then
-                            fmreg_pos := keyoff_pos;
-
-                     If (fmreg_pos <> 0) and
-                        (fmreg_pos <> IDLE) and (fmreg_pos <> finished_flag) then
-                       begin
-                         fmreg_duration := data[fmreg_pos].duration;
-                         If (fmreg_duration <> 0) then
-                           With data[fmreg_pos] do
-                             begin
-                               // force KEY-ON with missing ADSR instrument data
-                               force_macro_keyon := FALSE;
-                               If (fmreg_pos = 1) then
-                                 If _ins_adsr_data_empty(voice_table[chan]) and
-                                    NOT (songdata.dis_fmreg_col[fmreg_table][0] and
-                                         songdata.dis_fmreg_col[fmreg_table][1] and
-                                         songdata.dis_fmreg_col[fmreg_table][2] and
-                                         songdata.dis_fmreg_col[fmreg_table][3] and
-                                         songdata.dis_fmreg_col[fmreg_table][12] and
-                                         songdata.dis_fmreg_col[fmreg_table][13] and
-                                         songdata.dis_fmreg_col[fmreg_table][14] and
-                                         songdata.dis_fmreg_col[fmreg_table][15]) then
-                                   force_macro_keyon := TRUE;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][0] then
-                                 fmpar_table[chan].adsrw_mod.attck := fm_data.ATTCK_DEC_modulator SHR 4;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][1] then
-                                 fmpar_table[chan].adsrw_mod.dec := fm_data.ATTCK_DEC_modulator AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][2] then
-                                 fmpar_table[chan].adsrw_mod.sustn := fm_data.SUSTN_REL_modulator SHR 4;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][3] then
-                                 fmpar_table[chan].adsrw_mod.rel := fm_data.SUSTN_REL_modulator AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][4] then
-                                 fmpar_table[chan].adsrw_mod.wform := fm_data.WAVEFORM_modulator AND $07;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][6] then
-                                 fmpar_table[chan].kslM := fm_data.KSL_VOLUM_modulator SHR 6;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][7] then
-                                 fmpar_table[chan].multipM := fm_data.AM_VIB_EG_modulator AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][8] then
-                                 fmpar_table[chan].tremM := fm_data.AM_VIB_EG_modulator SHR 7;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][9] then
-                                 fmpar_table[chan].vibrM := fm_data.AM_VIB_EG_modulator SHR 6 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][10] then
-                                 fmpar_table[chan].ksrM := fm_data.AM_VIB_EG_modulator SHR 4 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][11] then
-                                 fmpar_table[chan].sustM := fm_data.AM_VIB_EG_modulator SHR 5 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][12] then
-                                 fmpar_table[chan].adsrw_car.attck := fm_data.ATTCK_DEC_carrier SHR 4;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][13] then
-                                 fmpar_table[chan].adsrw_car.dec := fm_data.ATTCK_DEC_carrier AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][14] then
-                                 fmpar_table[chan].adsrw_car.sustn := fm_data.SUSTN_REL_carrier SHR 4;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][15] then
-                                 fmpar_table[chan].adsrw_car.rel := fm_data.SUSTN_REL_carrier AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][16] then
-                                 fmpar_table[chan].adsrw_car.wform := fm_data.WAVEFORM_carrier AND $07;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][18] then
-                                 fmpar_table[chan].kslC := fm_data.KSL_VOLUM_carrier SHR 6;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][19] then
-                                 fmpar_table[chan].multipC := fm_data.AM_VIB_EG_carrier AND $0f;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][20] then
-                                 fmpar_table[chan].tremC := fm_data.AM_VIB_EG_carrier SHR 7;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][21] then
-                                 fmpar_table[chan].vibrC := fm_data.AM_VIB_EG_carrier SHR 6 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][22] then
-                                 fmpar_table[chan].ksrC := fm_data.AM_VIB_EG_carrier SHR 4 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][23] then
-                                 fmpar_table[chan].sustC := fm_data.AM_VIB_EG_carrier SHR 5 AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][24] then
-                                 fmpar_table[chan].connect := fm_data.FEEDBACK_FM AND 1;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][25] then
-                                 fmpar_table[chan].feedb := fm_data.FEEDBACK_FM SHR 1 AND 7;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][27] then
-                                 If NOT pan_lock[chan] then
-                                   panning_table[chan] := panning;
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][5] then
-                                 set_ins_volume(63-fm_data.KSL_VOLUM_modulator AND $3f,
-                                                BYTE_NULL,chan);
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][17] then
-                                 set_ins_volume(BYTE_NULL,
-                                                63-fm_data.KSL_VOLUM_carrier AND $3f,chan);
-
-                               update_modulator_adsrw(chan);
-                               update_carrier_adsrw(chan);
-                               update_fmpar(chan);
-
-                               If force_macro_keyon or
-                                  NOT (fm_data.FEEDBACK_FM OR $80 <> fm_data.FEEDBACK_FM) then
-                                 output_note(event_table[chan].note,
-                                             event_table[chan].instr_def,chan,FALSE);
-
-                               If NOT songdata.dis_fmreg_col[fmreg_table][26] then
-                                 If (freq_slide > 0) then
-                                   portamento_up(chan,freq_slide,nFreq(12*8+1))
-                                 else If (freq_slide < 0) then
-                                        portamento_down(chan,Abs(freq_slide),nFreq(0));
-                             end;
-                       end;
-                   end;
-
-          With songdata.macro_table[arpg_table].arpeggio do
-            If (arpg_table <> 0) and (speed <> 0) then
-              If (arpg_count = speed) then
-                begin
-                  arpg_count := 1;
-                  If (arpg_pos <= length) then
-                    If (loop_begin <> 0) and (loop_length <> 0) then
-                      If (arpg_pos = loop_begin+PRED(loop_length)) then
-                        arpg_pos := loop_begin
-                      else If (arpg_pos < length) then Inc(arpg_pos)
-                           else arpg_pos := finished_flag
-                    else If (arpg_pos < length) then Inc(arpg_pos)
-                         else arpg_pos := finished_flag
-                  else arpg_pos := finished_flag;
-
-                  If (freq_table[chan] OR $2000 = freq_table[chan]) and
-                     (keyoff_pos <> 0) and
-                     (arpg_pos >= keyoff_pos) then
-                    arpg_pos := IDLE
-                  else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
-                          (keyoff_pos <> 0) and (keyoff_pos <> 0) and
-                          ((arpg_pos < keyoff_pos) or (arpg_pos = IDLE)) then
-                         arpg_pos := keyoff_pos;
-
-                  If (arpg_pos <> 0) and
-                     (arpg_pos <> IDLE) and (arpg_pos <> finished_flag) then
-                    Case data[arpg_pos] of
-                      0: change_frequency(chan,
-                           nFreq(arpg_note-1)+
-                           SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-
-                      1..96:
-                        change_frequency(chan,
-                          nFreq(max(arpg_note+data[arpg_pos],97)-1)+
-                          SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-
-                      $80..$80+12*8+1:
-                        change_frequency(chan,nFreq(data[arpg_pos]-$80-1)+
-                          SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
-                    end;
-                end
-              else Inc(arpg_count);
-
-          With songdata.macro_table[vib_table].vibrato do
-            If NOT vib_paused and
-               (vib_table <> 0) and (speed <> 0) then
-              If (vib_count = speed) then
-                If (vib_delay <> 0) then Dec(vib_delay)
-                else begin
-                       vib_count := 1;
-                       If (vib_pos <= length) then
-                         If (loop_begin <> 0) and (loop_length <> 0) then
-                           If (vib_pos = loop_begin+PRED(loop_length)) then
-                             vib_pos := loop_begin
-                           else If (vib_pos < length) then Inc(vib_pos)
-                                else vib_pos := finished_flag
-                         else If (vib_pos < length) then Inc(vib_pos)
-                              else vib_pos := finished_flag
-                       else vib_pos := finished_flag;
-
-                       If (freq_table[chan] OR $2000 = freq_table[chan]) and
-                          (keyoff_pos <> 0) and
-                          (vib_pos >= keyoff_pos) then
-                         vib_pos := IDLE
-                       else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
-                               (vib_pos <> 0) and (keyoff_pos <> 0) and
-                               ((vib_pos < keyoff_pos) or (vib_pos = IDLE)) then
-                              vib_pos := keyoff_pos;
-
-                       If (vib_pos <> 0) and
-                          (vib_pos <> IDLE) and (vib_pos <> finished_flag) then
-                         If (data[vib_pos] > 0) then
-                           macro_vibrato__porta_up(chan,data[vib_pos])
-                         else If (data[vib_pos] < 0) then
-                                macro_vibrato__porta_down(chan,Abs(data[vib_pos]))
-                              else change_freq(chan,vib_freq);
-                     end
-              else Inc(vib_count);
-        end;
-    end;
-  _debug_str_ := _debug_str_bak_;
-end;
-
-var
-  ticklooper,
-  macro_ticklooper: Longint;
-
-procedure timer_poll_proc;
-
-var
-  _debug_str_bak_: String;
-
-begin
-  _debug_str_bak_ := _debug_str_;
-  _debug_str_ := 'A2PLAYER.PAS:timer_poll_proc';
-
-  If (timer_det < IRQ_freq DIV 200) then Inc(timer_det)
-  else begin
-         timer_det := 1;
-         Inc(_delay_counter);
-       end;
-
-  If (current_order = 0) and (current_line = 0) and
-     (tick0 = ticks) then
-    begin
-      song_timer := 0;
-      timer_temp := 0;
-      song_timer_tenths := 0;
-    end;
-
-  If (play_status = isPlaying) then
-    begin
-      song_timer_tenths := Trunc(100/IRQ_freq*timer_temp);
-      If (song_timer_tenths = 100) then song_timer_tenths := 0;
-      If (timer_temp < IRQ_freq) then Inc(timer_temp)
-      else begin
-             Inc(song_timer);
-             timer_temp := 1;
-           end;
-    end;
-
-  If (song_timer > 3600-1) then
-    begin
-      song_timer := 0;
-      timer_temp := 0;
-      song_timer_tenths := 0;
-    end;
-
-  If (ticklooper = 0) and NOT replay_forbidden then
-    poll_proc;
-
-  If (macro_ticklooper = 0) then
-    macro_poll_proc;
-
-  Inc(ticklooper);
-  If (ticklooper >= IRQ_freq DIV tempo) or fast_forward then
-    ticklooper := 0;
-
-  Inc(macro_ticklooper);
-  If (macro_ticklooper >= IRQ_freq DIV (tempo*_macro_speedup)) then
-    macro_ticklooper := 0;
-
-  _debug_str_ := _debug_str_bak_;
-end;
-
-procedure newtimer;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:newtimer';
-  If irq_mode then timer_poll_proc;
-  If (@external_irq_hook <> NIL) then external_irq_hook;
-end;
-
-procedure init_irq;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:init_irq';
-  If irq_initialized then EXIT;
-  irq_initialized := TRUE;
-  TimerInstallHandler(@newtimer);
-  TimerSetup(50);
-end;
-
-procedure done_irq;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:done_irq';
-  If NOT irq_initialized then EXIT;
-  irq_initialized := FALSE;
-  irq_mode := TRUE;
-  TimerDone;
-  TimerRemoveHandler;
-  irq_mode := FALSE;
-end;
-
-function calc_pattern_pos(pattern: Byte): Byte;
-
-var
-  index: Integer;
-  jump_count,pattern_pos: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:calc_pattern_pos';
-  pattern_pos := BYTE_NULL;
-  jump_count := 0;
-  index := calc_following_order(0);
-  While (index <> -1) and (jump_count < $7f) do
-    If (songdata.pattern_order[index] <> pattern) then
-      If NOT (index < $7f) then BREAK
-      else begin
-             Inc(index);
-             index := calc_following_order(index);
-             Inc(jump_count);
-           end
-    else begin
-           pattern_pos := index;
-           BREAK;
-         end;
-  calc_pattern_pos := pattern_pos;
-end;
-
-procedure init_buffers;
-
-var
-  temp: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:init_buffers';
-  FillChar(fmpar_table,SizeOf(fmpar_table),0);
-  FillChar(pan_lock,SizeOf(pan_lock),BYTE(panlock));
-  FillChar(volume_table,SizeOf(volume_table),0);
-  FillChar(vscale_table,SizeOf(vscale_table),0);
-  FillChar(modulator_vol,SizeOf(modulator_vol),0);
-  FillChar(carrier_vol,SizeOf(carrier_vol),0);
-  FillChar(event_table,SizeOf(event_table),0);
-  FillChar(freq_table,SizeOf(freq_table),0);
-  FillChar(effect_table,SizeOf(effect_table),0);
-  FillChar(effect_table2,SizeOf(effect_table2),0);
-  FillChar(fslide_table,SizeOf(fslide_table),0);
-  FillChar(fslide_table2,SizeOf(fslide_table2),0);
-  FillChar(glfsld_table,SizeOf(glfsld_table),0);
-  FillChar(glfsld_table2,SizeOf(glfsld_table2),0);
-  FillChar(porta_table,SizeOf(porta_table),0);
-  FillChar(porta_table2,SizeOf(porta_table2),0);
-  FillChar(arpgg_table,SizeOf(arpgg_table),0);
-  FillChar(arpgg_table2,SizeOf(arpgg_table2),0);
-  FillChar(vibr_table,SizeOf(vibr_table),0);
-  FillChar(vibr_table2,SizeOf(vibr_table2),0);
-  FillChar(trem_table,SizeOf(trem_table),0);
-  FillChar(trem_table2,SizeOf(trem_table2),0);
-  FillChar(retrig_table,SizeOf(retrig_table),0);
-  FillChar(retrig_table2,SizeOf(retrig_table2),0);
-  FillChar(tremor_table,SizeOf(tremor_table),0);
-  FillChar(tremor_table2,SizeOf(tremor_table2),0);
-  FillChar(panning_table,SizeOf(panning_table),0);
-  FillChar(last_effect,SizeOf(last_effect),0);
-  FillChar(last_effect2,SizeOf(last_effect2),0);
-  FillChar(voice_table,SizeOf(voice_table),0);
-  FillChar(event_new,SizeOf(event_new),0);
-  FillChar(notedel_table,SizeOf(notedel_table),BYTE_NULL);
-  FillChar(notecut_table,SizeOf(notecut_table),BYTE_NULL);
-  FillChar(ftune_table,SizeOf(ftune_table),0);
-  FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
-  FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
-  FillChar(reset_chan,SizeOf(reset_chan),BYTE(FALSE));
-  FillChar(keyoff_loop,SizeOf(keyoff_loop),BYTE(FALSE));
-  FillChar(macro_table,SizeOf(macro_table),0);
-
-  If NOT lockvol then FillChar(volume_lock,SizeOf(volume_lock),0)
-  else For temp := 1 to 20 do volume_lock[temp] := BOOLEAN(songdata.lock_flags[temp] SHR 4 AND 1);
-
-  If NOT panlock then FillChar(panning_table,SizeOf(panning_table),0)
-  else For temp := 1 to 20 do panning_table[temp] := songdata.lock_flags[temp] AND 3;
-
-  If NOT lockVP then FillChar(peak_lock,SizeOf(peak_lock),0)
-  else For temp := 1 to 20 do peak_lock[temp] := BOOLEAN(songdata.lock_flags[temp] SHR 5 AND 1);
-
-  For temp := 1 to 20 do
-    volslide_type[temp] := songdata.lock_flags[temp] SHR 2 AND 3;
-end;
-
-procedure init_player;
-
-var
-  temp: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:init_player';
-  opl2out($01,0);
-
-  For temp := 1 to 18 do opl2out($0b0+_chan_n[temp],0);
-  For temp := $080 to $08d do opl2out(temp,BYTE_NULL);
-  For temp := $090 to $095 do opl2out(temp,BYTE_NULL);
-
-  speed_update    := BOOLEAN(songdata.common_flag AND 1);
-  lockvol         := BOOLEAN(songdata.common_flag SHR 1 AND 1);
-  lockVP          := BOOLEAN(songdata.common_flag SHR 2 AND 1);
-  tremolo_depth   :=         songdata.common_flag SHR 3 AND 1;
-  vibrato_depth   :=         songdata.common_flag SHR 4 AND 1;
-  panlock         := BOOLEAN(songdata.common_flag SHR 5 AND 1);
-  percussion_mode := BOOLEAN(songdata.common_flag SHR 6 AND 1);
-  volume_scaling  := BOOLEAN(songdata.common_flag SHR 7 AND 1);
-
-  current_tremolo_depth := tremolo_depth;
-  current_vibrato_depth := vibrato_depth;
-  init_buffers;
-
-  If NOT percussion_mode then
-    begin
-      _chan_n := _chmm_n;
-      _chan_m := _chmm_m;
-      _chan_c := _chmm_c;
-    end
-  else
-    begin
-      _chan_n := _chpm_n;
-      _chan_m := _chpm_m;
-      _chan_c := _chpm_c;
-    end;
-
-  misc_register := tremolo_depth SHL 7+
-                   vibrato_depth SHL 6+
-                   BYTE(percussion_mode) SHL 5;
-
-  opl2out($01,$20);
-  opl2out($08,$40);
-  opl3exp($0105);
-  opl3exp($04+songdata.flag_4op SHL 8);
-
-  key_off(17);
-  key_off(18);
-  opl2out(_instr[11],misc_register);
-
-  current_tremolo_depth := tremolo_depth;
-  current_vibrato_depth := vibrato_depth;
-  global_volume := 63;
-  vibtrem_speed_factor := def_vibtrem_speed_factor;
-  vibtrem_table_size := def_vibtrem_table_size;
-  Move(def_vibtrem_table,vibtrem_table,SizeOf(vibtrem_table));
-
-  For temp := 1 to 20 do
-    begin
-      arpgg_table[temp].state := 1;
-      voice_table[temp] := temp;
-    end;
-end;
-
-procedure stop_playing;
-
-var
-  temp: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:stop_playing';
-  irq_mode := FALSE;
-  play_status := isStopped;
-  global_volume := 63;
-  current_tremolo_depth := tremolo_depth;
-  current_vibrato_depth := vibrato_depth;
-  pattern_break := FALSE;
-  current_order := 0;
-  current_pattern := 0;
-  current_line := 0;
-  song_timer := 0;
-  timer_temp := 0;
-  song_timer_tenths := 0;
-
-  For temp := 1 to 20 do release_sustaining_sound(temp);
-  opl2out(_instr[11],0);
-  opl3exp($0004);
-  opl3exp($0005);
-  init_buffers;
-
-  speed := songdata.speed;
-  update_timer(songdata.tempo);
-end;
-
-procedure init_old_songdata;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:init_old_songdata';
-  FillChar(old_songdata,SizeOf(old_songdata),0);
-  FillChar(old_songdata.pattern_order,SizeOf(old_songdata.pattern_order),$080);
-  FillChar(old_songdata.instr_data,SizeOf(old_songdata.instr_data),0);
-end;
-
-procedure init_songdata;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:init_songdata';
-  If (play_status <> isStopped) then stop_playing
-  else init_buffers;
-
-  FillChar(songdata,SizeOf(songdata),0);
-  FillChar(songdata.pattern_order,SizeOf(songdata.pattern_order),$080);
-  FillChar(pattdata^,PATTERN_SIZE*max_patterns,0);
-
-  songdata.patt_len := 64;
-  songdata.nm_tracks := 9;
-  songdata.tempo := tempo;
-  songdata.speed := speed;
-  songdata.macro_speedup := 1;
-  speed_update := FALSE;
-  lockvol := FALSE;
-  panlock := FALSE;
-  lockVP  := FALSE;
-  tremolo_depth := 0;
-  vibrato_depth := 0;
-  volume_scaling := FALSE;
-
-  If (songdata.nm_tracks <= 18) then
-    begin
-      percussion_mode := FALSE;
-      _chan_n := _chmm_n;
-      _chan_m := _chmm_m;
-      _chan_c := _chmm_c;
-    end
-  else
-    begin
-      percussion_mode := TRUE;
-      _chan_n := _chpm_n;
-      _chan_m := _chpm_m;
-      _chan_c := _chpm_c;
-    end;
-end;
-
-procedure start_playing;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:start_playing';
-  stop_playing;
-  If (error_code <> 0) then EXIT
-  else init_player;
-
-  current_order := 0;
-  If (songdata.pattern_order[current_order] > $7f) then
-    If (calc_order_jump = -1) then EXIT;
-
-  current_pattern := songdata.pattern_order[current_order];
-  current_line := 0;
-  pattern_break := FALSE;
-  pattern_delay := FALSE;
-  tickXF := 0;
-  ticks := 0;
-  tick0 := 0;
-  next_line := 0;
-  song_timer := 0;
-  timer_temp := 0;
-  song_timer_tenths := 0;
-  irq_mode := TRUE;
-  replay_forbidden := FALSE;
-  play_status := isPlaying;
-  time_playing := 0;
-  ticklooper := 0;
-  macro_ticklooper := 0;
-  speed := songdata.speed;
-  macro_speedup := songdata.macro_speedup;
-  update_timer(songdata.tempo);
-end;
-
-procedure get_chunk(pattern,line,channel: Byte;
-                    var chunk: tADTRACK2_EVENT); assembler;
-asm
-        mov     esi,dword ptr [pattdata]
-        mov     edi,[chunk]
-        mov     al,pattern
-        inc     al
-        cmp     al,max_patterns
-        jbe     @@1
-        mov     ecx,CHUNK_SIZE
-        xor     al,al
-        rep     stosb
-        jmp     @@2
-@@1:    xor     eax,eax
-        mov     al,line
-        mov     ebx,CHUNK_SIZE
-        mul     ebx
-        mov     ecx,eax
-        xor     eax,eax
-        mov     al,channel
-        dec     eax
-        mov     ebx,256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        xor     eax,eax
-        mov     al,pattern
-        mov     ebx,8
-        div     ebx
-        push    eax
-        mov     eax,edx
-        mov     ebx,20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        pop     eax
-        mov     ebx,8*20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        add     esi,ecx
-        mov     ecx,CHUNK_SIZE
-        rep     movsb
-@@2:
-end;
-
-procedure put_chunk(pattern,line,channel: Byte;
-                    chunk: tADTRACK2_EVENT); assembler;
-asm
-        mov     esi,[chunk]
-        mov     edi,dword ptr [pattdata]
-        mov     al,pattern
-        inc     al
-        cmp     al,max_patterns
-        jbe     @@1
-        mov     limit_exceeded,TRUE
-        jmp     @@2
-@@1:    xor     eax,eax
-        mov     al,line
-        mov     ebx,CHUNK_SIZE
-        mul     ebx
-        mov     ecx,eax
-        xor     eax,eax
-        mov     al,channel
-        dec     eax
-        mov     ebx,256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        xor     eax,eax
-        mov     al,pattern
-        mov     ebx,8
-        div     ebx
-        push    eax
-        mov     eax,edx
-        mov     ebx,20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        pop     eax
-        mov     ebx,8*20*256*CHUNK_SIZE
-        mul     ebx
-        add     ecx,eax
-        add     edi,ecx
-        mov     ecx,CHUNK_SIZE
-        rep     movsb
-@@2:
-end;
-
-procedure count_order(var entries: Byte);
-
-var
-  index,
-  index2: Byte;
-
-begin
-  _debug_str_ := 'A2PLAYER.PAS:count_order';
-  index := 0;
-  index2 := 0;
-
-  Repeat
-    If (songdata.pattern_order[index] <> $80) then
-      begin
-        If (songdata.pattern_order[index] > $80) then
-          If (songdata.pattern_order[index]-$80 <> index2) then
-            begin
-              index := songdata.pattern_order[index]-$80;
-              index2 := index;
-            end
-          else BREAK;
-      end
-    else BREAK;
-    If (index < $80) then Inc(index);
-  until (index > $7f);
-
-  entries := index;
-end;
-
-var
-  old_exit_proc: Pointer;
-  temp: Byte;
-
-procedure new_exit_proc;
-begin
-  _debug_str_ := 'A2PLAYER.PAS:new_exit_proc';
-  stop_playing;
-  done_irq;
-  FreeMem(pattdata,PATTERN_SIZE*max_patterns);
-end;
-
-begin
-  old_exit_proc := ExitProc;
-  ExitProc := @new_exit_proc;
-
-  error_code := 0;
-  temp := $80;
-  Repeat
-    If (MemAvail > PATTERN_SIZE*temp) then
-      begin
-        max_patterns := temp;
-        BREAK;
-      end
-    else If (temp-$10 >= $10) then Dec(temp,$10)
-         else begin
-                error_code := -2;
-                BREAK;
-              end;
-  until FALSE;
-
-  If (error_code <> -2) then
-    GetMem(pattdata,PATTERN_SIZE*max_patterns);
-
-  FillChar(decay_bar,SizeOf(decay_bar),0);
-  play_status := isStopped;
-  init_songdata;
-  init_irq;
-  timer_det := 1;
-end.