]> 4ch.mooo.com Git - 16.git/blob - 16/ADT2PLAY/a2player.pas
i hate being tired wwww i will work on the project some more sometime wwww
[16.git] / 16 / ADT2PLAY / a2player.pas
1 unit A2player;
2 interface
3
4 const
5   MAX_IRQ_FREQ = 1000;
6
7 {$i typconst.inc}
8
9 const
10   ef_Arpeggio          = 0;
11   ef_FSlideUp          = 1;
12   ef_FSlideDown        = 2;
13   ef_TonePortamento    = 3;
14   ef_Vibrato           = 4;
15   ef_TPortamVolSlide   = 5;
16   ef_VibratoVolSlide   = 6;
17   ef_FSlideUpFine      = 7;
18   ef_FSlideDownFine    = 8;
19   ef_SetModulatorVol   = 9;
20   ef_VolSlide          = 10;
21   ef_PositionJump      = 11;
22   ef_SetInsVolume      = 12;
23   ef_PatternBreak      = 13;
24   ef_SetTempo          = 14;
25   ef_SetSpeed          = 15;
26   ef_TPortamVSlideFine = 16;
27   ef_VibratoVSlideFine = 17;
28   ef_SetCarrierVol     = 18;
29   ef_SetWaveform       = 19;
30   ef_VolSlideFine      = 20;
31   ef_RetrigNote        = 21;
32   ef_Tremolo           = 22;
33   ef_Tremor            = 23;
34   ef_ArpggVSlide       = 24;
35   ef_ArpggVSlideFine   = 25;
36   ef_MultiRetrigNote   = 26;
37   ef_FSlideUpVSlide    = 27;
38   ef_FSlideDownVSlide  = 28;
39   ef_FSlUpFineVSlide   = 29;
40   ef_FSlDownFineVSlide = 30;
41   ef_FSlUpVSlF         = 31;
42   ef_FSlDownVSlF       = 32;
43   ef_FSlUpFineVSlF     = 33;
44   ef_FSlDownFineVSlF   = 34;
45   ef_Extended          = 35;
46   ef_Extended2         = 36;
47   ef_SetGlobalVolume   = 37;
48   ef_SwapArpeggio      = 38;
49   ef_SwapVibrato       = 39;
50   ef_ForceInsVolume    = 40;
51   ef_Extended3         = 41;
52   ef_ExtraFineArpeggio = 42;
53   ef_ExtraFineVibrato  = 43;
54   ef_ExtraFineTremolo  = 44;
55   ef_SetCustomSpeedTab = 45;
56   ef_GlobalFSlideUp    = 46;
57   ef_GlobalFSlideDown  = 47;
58   ef_ex_SetTremDepth   = 0;
59   ef_ex_SetVibDepth    = 1;
60   ef_ex_SetAttckRateM  = 2;
61   ef_ex_SetDecayRateM  = 3;
62   ef_ex_SetSustnLevelM = 4;
63   ef_ex_SetRelRateM    = 5;
64   ef_ex_SetAttckRateC  = 6;
65   ef_ex_SetDecayRateC  = 7;
66   ef_ex_SetSustnLevelC = 8;
67   ef_ex_SetRelRateC    = 9;
68   ef_ex_SetFeedback    = 10;
69   ef_ex_SetPanningPos  = 11;
70   ef_ex_PatternLoop    = 12;
71   ef_ex_PatternLoopRec = 13;
72   ef_ex_MacroKOffLoop  = 14;
73   ef_ex_ExtendedCmd    = 15;
74   ef_ex_cmd_RSS        = 0;
75   ef_ex_cmd_ResetVol   = 1;
76   ef_ex_cmd_LockVol    = 2;
77   ef_ex_cmd_UnlockVol  = 3;
78   ef_ex_cmd_LockVP     = 4;
79   ef_ex_cmd_UnlockVP   = 5;
80   ef_ex_cmd_VSlide_mod = 6;
81   ef_ex_cmd_VSlide_car = 7;
82   ef_ex_cmd_VSlide_def = 8;
83   ef_ex_cmd_LockPan    = 9;
84   ef_ex_cmd_UnlockPan  = 10;
85   ef_ex_cmd_VibrOff    = 11;
86   ef_ex_cmd_TremOff    = 12;
87   ef_ex_cmd_FVib_FGFS  = 13;
88   ef_ex_cmd_FTrm_XFGFS = 14;
89   ef_ex_cmd_NoRestart  = 15;
90   ef_ex2_PatDelayFrame = 0;
91   ef_ex2_PatDelayRow   = 1;
92   ef_ex2_NoteDelay     = 2;
93   ef_ex2_NoteCut       = 3;
94   ef_ex2_FineTuneUp    = 4;
95   ef_ex2_FineTuneDown  = 5;
96   ef_ex2_GlVolSlideUp  = 6;
97   ef_ex2_GlVolSlideDn  = 7;
98   ef_ex2_GlVolSlideUpF = 8;
99   ef_ex2_GlVolSlideDnF = 9;
100   ef_ex2_GlVolSldUpXF  = 10;
101   ef_ex2_GlVolSldDnXF  = 11;
102   ef_ex2_VolSlideUpXF  = 12;
103   ef_ex2_VolSlideDnXF  = 13;
104   ef_ex2_FreqSlideUpXF = 14;
105   ef_ex2_FreqSlideDnXF = 15;
106   ef_ex3_SetConnection = 0;
107   ef_ex3_SetMultipM    = 1;
108   ef_ex3_SetKslM       = 2;
109   ef_ex3_SetTremoloM   = 3;
110   ef_ex3_SetVibratoM   = 4;
111   ef_ex3_SetKsrM       = 5;
112   ef_ex3_SetSustainM   = 6;
113   ef_ex3_SetMultipC    = 7;
114   ef_ex3_SetKslC       = 8;
115   ef_ex3_SetTremoloC   = 9;
116   ef_ex3_SetVibratoC   = 10;
117   ef_ex3_SetKsrC       = 11;
118   ef_ex3_SetSustainC   = 12;
119
120 const
121   ef_fix1 = $80;
122   ef_fix2 = $90;
123
124 const
125   opl3port: Word = $388;
126   error_code: Integer = 0;
127   current_order: Byte = 0;
128   current_pattern: Byte = 0;
129   current_line: Byte = 0;
130   tempo: Byte = 50;
131   speed: Byte = 6;
132   macro_speedup: Word = 1;
133   irq_mode: Boolean = FALSE;
134   max_patterns: Byte = 128;
135   fast_forward: Boolean = FALSE;
136   overall_volume: Byte = 63;
137   global_volume: Byte = 63;
138
139 const
140   song_timer: Word = 0;
141   song_timer_tenths: Word = 0;
142
143 var
144   timer_temp,timer_det: Word;
145   ticks,tick0,tickD,
146   tickXF: Longint;
147   limit_exceeded: Boolean;
148
149 type
150   tFM_INST_DATA = Record
151                     AM_VIB_EG_modulator,
152                     AM_VIB_EG_carrier,
153                     KSL_VOLUM_modulator,
154                     KSL_VOLUM_carrier,
155                     ATTCK_DEC_modulator,
156                     ATTCK_DEC_carrier,
157                     SUSTN_REL_modulator,
158                     SUSTN_REL_carrier,
159                     WAVEFORM_modulator,
160                     WAVEFORM_carrier,
161                     FEEDBACK_FM: Byte;
162                   end;
163 type
164   tADTRACK2_INS = Record
165                     fm_data: tFM_INST_DATA;
166                     panning: Byte;
167                     fine_tune: Shortint;
168                     perc_voice: Byte;
169                   end;
170 type
171   tARPEGGIO_TABLE = Record
172                       length,
173                       speed,
174                       loop_begin,
175                       loop_length,
176                       keyoff_pos: Byte;
177                       data: array[1..255] of Byte;
178                     end;
179 type
180   tVIBRATO_TABLE = Record
181                      length,
182                      speed,
183                      delay,
184                      loop_begin,
185                      loop_length,
186                      keyoff_pos: Byte;
187                      data: array[1..255] of Shortint;
188                    end;
189 type
190   tREGISTER_TABLE_DEF = Record
191                           fm_data: tFM_INST_DATA;
192                           freq_slide: Smallint;
193                           panning: Byte;
194                           duration: Byte;
195                         end;
196 type
197   tREGISTER_TABLE = Record
198                       length,
199                       loop_begin,
200                       loop_length,
201                       keyoff_pos,
202                       arpeggio_table,
203                       vibrato_table: Byte;
204                       data: array[1..255] of tREGISTER_TABLE_DEF;
205                     end;
206 type
207   tMACRO_TABLE = Record
208                    arpeggio: tARPEGGIO_TABLE;
209                    vibrato:  tVIBRATO_TABLE;
210                  end;
211 type
212   tFM_PARAMETER_TABLE = Record
213                           adsrw_car,
214                           adsrw_mod: Record
215                                        attck,dec,sustn,rel,
216                                        wform: Byte;
217                                      end;
218                           connect,
219                           feedb,
220                           multipM,kslM,tremM,vibrM,ksrM,sustM,
221                           multipC,kslC,tremC,vibrC,ksrC,sustC: Byte;
222                         end;
223 type
224   tADTRACK2_EVENT = Record
225                       note,
226                       instr_def,
227                       effect_def,
228                       effect,
229                       effect_def2,
230                       effect2: Byte;
231                     end;
232
233 type
234   tDIS_FMREG_COL = array[0..27] of Boolean;
235
236 type
237   tFIXED_SONGDATA = Record
238                       songname:      String[42];
239                       composer:      String[42];
240                       instr_names:   array[1..255] of String[42];
241                       instr_data:    array[1..255] of tADTRACK2_INS;
242                       instr_macros:  array[1..255] of tREGISTER_TABLE;
243                       macro_table:   array[1..255] of tMACRO_TABLE;
244                       pattern_order: array[0..$7f] of Byte;
245                       tempo:         Byte;
246                       speed:         Byte;
247                       common_flag:   Byte;
248                       patt_len:      Word;
249                       nm_tracks:     Byte;
250                       macro_speedup: Word;
251                       flag_4op:      Byte;
252                       lock_flags:    array[1..20]  of Byte;
253                       pattern_names: array[0..$7f] of String[42];
254                       dis_fmreg_col: array[1..255] of tDIS_FMREG_COL;
255                     end;
256 type
257   tPLAY_STATUS = (isPlaying,isPaused,isStopped);
258
259 type
260   tVARIABLE_DATA = array[0..7]    of
261                    array[1..20]   of
262                    array[0..$0ff] of tADTRACK2_EVENT;
263 type
264   tPATTERN_DATA = array[0..15] of tVARIABLE_DATA;
265
266 type
267   tDUMMY_BUFF = array[0..PRED(655350)] of Byte;
268
269 type
270   tOLD_ADTRACK2_INS = Record
271                         fm_data: tFM_INST_DATA;
272                         panning: Byte;
273                         fine_tune: Shortint;
274                       end;
275 type
276   pOLD_FIXED_SONGDATA = ^tOLD_FIXED_SONGDATA;
277   tOLD_FIXED_SONGDATA = Record
278                           songname:      String[42];
279                           composer:      String[42];
280                           instr_names:   array[1..250] of String[32];
281                           instr_data:    array[1..250] of tOLD_ADTRACK2_INS;
282                           pattern_order: array[0..$7f] of Byte;
283                           tempo:         Byte;
284                           speed:         Byte;
285                           common_flag:   Byte;
286                         end;
287 type
288   tOLD_CHUNK = Record
289                  note:       Byte;
290                  instr_def:  Byte;
291                  effect_def: Byte;
292                  effect:     Byte;
293                end;
294 type
295   tCHUNK = tADTRACK2_EVENT;
296
297 type
298   tOLD_VARIABLE_DATA1 = array[0..$0f] of array[0..$3f] of
299                         array[1..9]   of tOLD_CHUNK;
300 type
301   tOLD_VARIABLE_DATA2 = array[0..7]   of array[1..18] of
302                         array[0..$3f] of tOLD_CHUNK;
303 type
304   tByteSet = Set of Byte;
305
306 const
307   INSTRUMENT_SIZE = SizeOf(tADTRACK2_INS);
308   CHUNK_SIZE = SizeOf(tCHUNK);
309   PATTERN_SIZE = 20*256*CHUNK_SIZE;
310
311 var
312   time_playing: Real;
313   pattdata: ^tPATTERN_DATA;
314   songdata: tFIXED_SONGDATA;
315   old_songdata: tOLD_FIXED_SONGDATA;
316   old_hash_buffer: tOLD_VARIABLE_DATA1;
317   hash_buffer: tOLD_VARIABLE_DATA2;
318   buffer: array[0..PRED(SizeOf(tVARIABLE_DATA))] of Byte;
319
320 const
321   external_irq_hook: procedure = NIL;
322   _delay_counter: Longint = 0;
323   irq_freq: Word = 50;
324   irq_initialized: Boolean = FALSE;
325   timer_fix: Boolean = TRUE;
326   pattern_break: Boolean = FALSE;
327   pattern_delay: Boolean = FALSE;
328   next_line: Byte = 0;
329   play_status: tPLAY_STATUS = isStopped;
330   replay_forbidden: Boolean = TRUE;
331   force_macro_keyon: Boolean = FALSE;
332
333 type
334   tDECAY_BAR = Record
335                   dir: Integer;
336                   lvl,max_lvl: Real;
337                 end;
338 var
339   decay_bar: array[1..96] of tDECAY_BAR;
340
341 procedure start_playing;
342 procedure set_overall_volume(level: Byte);
343 procedure stop_playing;
344 procedure init_old_songdata;
345 procedure init_songdata;
346 procedure init_irq;
347 procedure done_irq;
348 procedure get_chunk(pattern,line,channel: Byte; var chunk: tADTRACK2_EVENT);
349 procedure put_chunk(pattern,line,channel: Byte; chunk: tADTRACK2_EVENT);
350 procedure count_order(var entries: Byte);
351 procedure timer_poll_proc;
352 procedure opl3exp(data: Word);
353
354 function  calc_following_order(order: Byte): Integer;
355 function  asciiz_string(str: String): String;
356
357 implementation
358 uses DOS,TimerInt,ParserIO;
359
360 const
361   _panning: array[0..2] of Byte = ($30,$10,$20);
362
363 const
364   _instr:  array[0..11] of Byte = ($20, $20,
365                                    $40, $40,
366                                    $60, $60,
367                                    $80, $80,
368                                    $0e0,$0e0,
369                                    $0c0,
370                                    $0bd);
371 type
372   tTRACK_ADDR = array[1..20] of Word;
373
374 const                    { 01 - 02 - 03 - 04 - 05 - 06 - 07 - 08 - 09 - 10 - 11 - 12 - 13 - 14 - 15 - 16 - 17 - 18 - 19 - 20 }
375   _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);
376   _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);
377   _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);
378                          {                                                                            BD   SD   TT   TC   HH }
379   _chpm_n: tTRACK_ADDR = ($003,$000,$004,$001,$005,$002,$106,$107,$108,$103,$100,$104,$101,$105,$102,$006,$007,$008,$008,$007);
380   _chpm_m: tTRACK_ADDR = ($008,$000,$009,$001,$00a,$002,$110,$111,$112,$108,$100,$109,$101,$10a,$102,$010,$014,$012,$015,$011);
381   _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);
382
383 var
384   _chan_n: tTRACK_ADDR;
385   _chan_m: tTRACK_ADDR;
386   _chan_c: tTRACK_ADDR;
387
388 const
389   keyoff_flag        = $080;
390   fixed_note_flag    = $090;
391   pattern_loop_flag  = $0e0;
392   pattern_break_flag = $0f0;
393
394 const
395   def_vibtrem_speed_factor: Byte = 1;
396   def_vibtrem_table_size: Byte = 32;
397   def_vibtrem_table: array[0..255] of Byte = (
398     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
399     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
400     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
401     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
402     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
403     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
404     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
405     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
406     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
407     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
408     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
409     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
410     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
411     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24,
412     0,24,49,74,97,120,141,161,180,197,212,224,235,244,250,253,255,
413     253,250,244,235,224,212,197,180,161,141,120,97,74,49,24);
414
415 var
416   vibtrem_speed_factor: Byte;
417   vibtrem_table_size: Byte;
418   vibtrem_table: array[0..255] of Byte;
419
420 var
421   fmpar_table:   array[1..20] of tFM_PARAMETER_TABLE;
422   volume_lock:   array[1..20] of Boolean;
423   volume_table:  array[1..20] of Word;
424   vscale_table:  array[1..20] of Word;
425   peak_lock:     array[1..20] of Boolean;
426   pan_lock:      array[1..20] of Boolean;
427   event_table:   array[1..20] of tADTRACK2_EVENT;
428   voice_table:   array[1..20] of Byte;
429   modulator_vol: array[1..20] of Byte;
430   carrier_vol:   array[1..20] of Byte;
431   freq_table:    array[1..20] of Word;
432   effect_table:  array[1..20] of Word;
433   effect_table2: array[1..20] of Word;
434   fslide_table:  array[1..20] of Byte;
435   fslide_table2: array[1..20] of Byte;
436   glfsld_table:  array[1..20] of Word;
437   glfsld_table2: array[1..20] of Word;
438   porta_table:   array[1..20] of Record freq: Word; speed: Byte; end;
439   porta_table2:  array[1..20] of Record freq: Word; speed: Byte; end;
440   arpgg_table:   array[1..20] of Record state,note,add1,add2: Byte; end;
441   arpgg_table2:  array[1..20] of Record state,note,add1,add2: Byte; end;
442   vibr_table:    array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
443   vibr_table2:   array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
444   trem_table:    array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
445   trem_table2:   array[1..20] of Record pos,speed,depth: Byte; fine: Boolean; end;
446   retrig_table:  array[1..20] of Byte;
447   retrig_table2: array[1..20] of Byte;
448   tremor_table:  array[1..20] of Record pos: Integer; volume: Word; end;
449   tremor_table2: array[1..20] of Record pos: Integer; volume: Word; end;
450   panning_table: array[1..20] of Byte;
451   last_effect:   array[1..20] of Word;
452   last_effect2:  array[1..20] of Word;
453   volslide_type: array[1..20] of Byte;
454   event_new:     array[1..20] of Boolean;
455   notedel_table: array[1..20] of Byte;
456   notecut_table: array[1..20] of Byte;
457   ftune_table:   array[1..20] of Shortint;
458   keyoff_loop:   array[1..20] of Boolean;
459   macro_table:   array[1..20] of Record
460                                    fmreg_pos,arpg_pos,vib_pos: Word;
461                                    fmreg_count,fmreg_duration,arpg_count,
462                                    vib_count,vib_delay: Byte;
463                                    vib_paused: Boolean;
464                                    fmreg_table,arpg_table,vib_table: Byte;
465                                    arpg_note: Byte;
466                                    vib_freq: Word;
467                                  end;
468
469   loopbck_table: array[1..20] of Byte;
470   loop_table:    array[1..20,0..255] of Byte;
471   misc_register: Byte;
472
473 const
474   current_tremolo_depth: Byte = 0;
475   current_vibrato_depth: Byte = 0;
476
477 var
478   speed_update,lockvol,panlock,lockVP: Boolean;
479   tremolo_depth,vibrato_depth: Byte;
480   volume_scaling,percussion_mode: Boolean;
481   last_order: Byte;
482   reset_chan: array[1..20] of Boolean;
483
484 procedure opl2out(reg,data: Word); assembler;
485 asm
486         mov     ax,reg
487         mov     dx,word ptr [opl3port]
488         or      ah,ah
489         jz      @@1
490         add     dx,2
491 @@1:    out     dx,al
492         mov     ecx,6
493 @@2:    in      al,dx
494         loop    @@2
495         inc     dl
496         mov     ax,data
497         out     dx,al
498         dec     dl
499         mov     ecx,36
500 @@3:    in      al,dx
501         loop    @@3
502 end;
503
504 procedure opl3out(reg,data: Word); assembler;
505 asm
506         mov     ax,reg
507         mov     dx,word ptr [opl3port]
508         or      ah,ah
509         jz      @@1
510         add     dx,2
511 @@1:    out     dx,al
512         inc     dl
513         mov     ax,data
514         out     dx,al
515         dec     dl
516         mov     ecx,26
517 @@2:    in      al,dx
518         loop    @@2
519 end;
520
521 procedure opl3exp(data: Word); assembler;
522 asm
523         mov     ax,data
524         mov     dx,word ptr [opl3port]
525         add     dx,2
526         out     dx,al
527         mov     ecx,6
528 @@1:    in      al,dx
529         loop    @@1
530         inc     dl
531         mov     al,ah
532         out     dx,al
533         mov     ecx,36
534 @@2:    in      al,dx
535         loop    @@2
536 end;
537
538 const
539   FreqStart = $156;
540   FreqEnd   = $2ae;
541   FreqRange = FreqEnd-FreqStart;
542
543 function nFreq(note: Byte): Word; assembler;
544
545 const
546   Fnum: array[0..11] of Word = (
547     $157,$16b,$181,$198,$1b0,$1ca,$1e5,$202,$220,$241,$263,$287);
548
549 asm
550         push    ebx
551         push    ecx
552         xor     ebx,ebx
553         mov     al,[note]
554         xor     ah,ah
555         cmp     ax,12*8
556         jae     @@1
557         push    eax
558         mov     bl,12
559         div     bl
560         mov     bl,ah
561         xor     bh,bh
562         shl     bx,1
563         pop     eax
564         mov     cl,12
565         div     cl
566         xor     ah,ah
567         shl     ax,10
568         add     ax,word ptr [Fnum+ebx]
569         jmp     @@2
570 @@1:    mov     ax,7
571         shl     ax,10
572         add     ax,FreqEnd
573 @@2:    pop     ecx
574         pop     ebx
575 end;
576
577 function calc_freq_shift_up(freq,shift: Word): Word; assembler;
578 asm
579         push    ebx
580         push    ecx
581         push    edx
582         mov     cx,freq
583         mov     ax,shift
584         mov     bx,cx
585         and     bx,0000001111111111b
586         mov     dx,cx
587         and     dx,0001110000000000b
588         add     bx,ax
589         and     cx,1110000000000000b
590         shr     dx,10
591         cmp     bx,FreqEnd
592         jb      @@2
593         cmp     dx,7
594         jnz     @@1
595         mov     bx,FreqEnd
596         jmp     @@2
597 @@1:    sub     bx,FreqRange
598         inc     dx
599 @@2:    mov     ax,cx
600         shl     dx,10
601         add     ax,dx
602         add     ax,bx
603         pop     edx
604         pop     ecx
605         pop     ebx
606 end;
607
608 function calc_freq_shift_down(freq,shift: Word): Word; assembler;
609 asm
610         push    ebx
611         push    ecx
612         push    edx
613         mov     cx,freq
614         mov     ax,shift
615         mov     bx,cx
616         and     bx,0000001111111111b
617         mov     dx,cx
618         and     dx,0001110000000000b
619         sub     bx,ax
620         and     cx,1110000000000000b
621         shr     dx,10
622         cmp     bx,FreqStart
623         ja      @@2
624         or      dx,dx
625         jnz     @@1
626         mov     bx,FreqStart
627         jmp     @@2
628 @@1:    add     bx,FreqRange
629         dec     dx
630 @@2:    mov     ax,cx
631         shl     dx,10
632         add     ax,dx
633         add     ax,bx
634         pop     edx
635         pop     ecx
636         pop     ebx
637 end;
638
639 function calc_vibtrem_shift(depth,position: Byte;
640                             var direction: Byte): Word; assembler;
641 asm
642         push    ebx
643         push    ecx
644         push    edx
645         push    edi
646         xor     ebx,ebx
647         mov     al,depth
648         xor     ah,ah
649         mov     bl,position
650         xor     bh,bh
651         mov     dh,bl
652         mov     cl,vibtrem_table_size
653         dec     cl
654         and     bl,cl
655         lea     edi,[vibtrem_table]
656         add     edi,ebx
657         mov     dl,byte ptr [edi]
658         mul     dl
659         rol     ax,1
660         xchg    ah,al
661         and     ah,1
662         mov     ebx,[direction]
663         mov     cl,1
664         mov     [ebx],cl
665         mov     dl,vibtrem_table_size
666         test    dh,dl
667         jne     @@1
668         mov     cl,0
669         mov     [ebx],cl
670 @@1:    pop     edi
671         pop     edx
672         pop     ecx
673         pop     ebx
674 end;
675
676 procedure change_freq(chan: Byte; freq: Word); assembler;
677 asm
678         push    ebx
679         push    edx
680         xor     ebx,ebx
681         mov     bl,chan
682         dec     ebx
683         shl     ebx,1
684         mov     ax,freq
685         and     ax,1fffh
686         mov     dx,word ptr [freq_table+ebx]
687         and     dx,NOT 1fffh
688         add     ax,dx
689         mov     word ptr [freq_table+ebx],ax
690         xor     edx,edx
691         mov     dx,word ptr [_chan_n+ebx]
692         add     dx,0a0h
693         push    edx
694         xor     edx,edx
695         mov     dl,al
696         push    edx
697         mov     dx,word ptr [_chan_n+ebx]
698         add     dx,0b0h
699         push    edx
700         xor     edx,edx
701         mov     dl,ah
702         push    edx
703         call    opl3out
704         call    opl3out
705         pop     edx
706         pop     ebx
707 end;
708
709 function ins_parameter(ins,param: Byte): Byte; assembler;
710 asm
711         push    ebx
712         push    esi
713         xor     ebx,ebx
714         lea     esi,[songdata.instr_data]
715         mov     bl,ins
716         dec     ebx
717         mov     eax,INSTRUMENT_SIZE
718         mul     ebx
719         add     esi,eax
720         mov     bl,param
721         add     esi,ebx
722         lodsb
723         pop     esi
724         pop     ebx
725 end;
726
727 function min(value: Word; minimum: Word): Word; assembler;
728 asm
729         mov     ax,value
730         cmp     ax,minimum
731         jae     @@1
732         mov     ax,minimum
733 @@1:
734 end;
735
736 function max(value: Word; maximum: Word): Word; assembler;
737 asm
738         mov     ax,value
739         cmp     ax,maximum
740         jbe     @@1
741         mov     ax,maximum
742 @@1:
743 end;
744
745 function asciiz_string(str: String): String;
746 begin
747   If (Pos(#0,str) <> 0) then asciiz_string := Copy(str,1,Pos(#0,str)-1)
748   else asciiz_string := '';
749 end;
750
751 function concw(lo,hi: Byte): Word;
752 begin
753   concw := lo+(hi SHL 8);
754 end;
755
756 procedure synchronize_song_timer;
757 begin
758   song_timer := TRUNC(time_playing);
759   song_timer_tenths := TRUNC(time_playing*100) MOD 100;
760   timer_temp := song_timer_tenths;
761 end;
762
763 procedure change_frequency(chan: Byte; freq: Word);
764 begin
765   macro_table[chan].vib_paused := TRUE;
766   change_freq(chan,freq);
767   macro_table[chan].vib_count := 1;
768   macro_table[chan].vib_pos := 0;
769   macro_table[chan].vib_freq := freq;
770   macro_table[chan].vib_paused := FALSE;
771 end;
772
773 function _macro_speedup: Word; assembler;
774 asm
775         mov     ax,macro_speedup
776         or      ax,ax
777         jnz     @@1
778         inc     ax
779 @@1:
780 end;
781
782 procedure update_timer(Hz: Longint);
783 begin
784   _debug_str_ := 'A2PLAYER.PAS:update_timer';
785   If (Hz = 0) then begin TimerSetup(18); EXIT end
786   else tempo := Hz;
787   If (tempo = 18) and timer_fix then IRQ_freq := TRUNC((tempo+0.2)*20)
788   else IRQ_freq := 250;
789   While (IRQ_freq MOD (tempo*_macro_speedup) <> 0) do Inc(IRQ_freq);
790   If (IRQ_freq > MAX_IRQ_FREQ) then IRQ_freq := MAX_IRQ_FREQ;
791   TimerSetup(IRQ_freq);
792 end;
793
794 procedure key_off(chan: Byte);
795 begin
796   freq_table[chan] := LO(freq_table[chan])+
797                      (HI(freq_table[chan]) AND NOT $20) SHL 8;
798   change_freq(chan,freq_table[chan]);
799   event_table[chan].note := event_table[chan].note OR keyoff_flag;
800 end;
801
802 procedure release_sustaining_sound(chan: Byte);
803 begin
804   opl3out(_instr[02]+_chan_m[chan],63);
805   opl3out(_instr[03]+_chan_c[chan],63);
806
807   FillChar(fmpar_table[chan].adsrw_car,
808            SizeOf(fmpar_table[chan].adsrw_car),0);
809   FillChar(fmpar_table[chan].adsrw_mod,
810            SizeOf(fmpar_table[chan].adsrw_mod),0);
811
812   opl3out($0b0+_chan_n[chan],0);
813   opl3out(_instr[04]+_chan_m[chan],BYTE_NULL);
814   opl3out(_instr[05]+_chan_c[chan],BYTE_NULL);
815   opl3out(_instr[06]+_chan_m[chan],BYTE_NULL);
816   opl3out(_instr[07]+_chan_c[chan],BYTE_NULL);
817
818   key_off(chan);
819   event_table[chan].instr_def := 0;
820   reset_chan[chan] := TRUE;
821 end;
822
823 function scale_volume(volume,scale_factor: Byte): Byte;
824 begin
825   scale_volume := 63-Round((63-volume)/63*
826                            (63-scale_factor));
827 end;
828
829 procedure set_ins_volume(modulator,carrier,chan: Byte);
830
831 var
832   temp: Byte;
833
834 begin
835 {$IFNDEF __TMT__}
836   // ** OPL3 emulation workaround **
837   // force muted instrument volume with missing ADSR instrument data
838   // when there is additionally no FM-reg macro defined for the instrument
839   If is_ins_adsr_data_empty(voice_table[chan]) and
840      NOT (songdata.instr_macros[voice_table[chan]].length <> 0) and
841          NOT replay_forbidden then
842     begin
843       modulator := 63;
844       carrier := 63;
845     end;
846 {$ENDIF}
847
848   If (modulator <> BYTE_NULL) then
849     begin
850       temp := modulator;
851       If volume_scaling then
852         If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
853            (percussion_mode and (chan in [17..20])) then
854           modulator := scale_volume(ins_parameter(voice_table[chan],2) AND $3f,modulator);
855       If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
856          (percussion_mode and (chan in [17..20])) then
857         opl3out(_instr[02]+_chan_m[chan],
858                 scale_volume(scale_volume(modulator,63-global_volume),63-overall_volume)+LO(vscale_table[chan]))
859       else
860         opl3out(_instr[02]+_chan_m[chan],
861                 temp+LO(vscale_table[chan]));
862       volume_table[chan] := concw(temp,HI(volume_table[chan]));
863       If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
864          (percussion_mode and (chan in [17..20])) then
865         modulator_vol[chan] := 63-scale_volume(modulator,63-global_volume)
866       else modulator_vol[chan] := 63-modulator;
867     end;
868
869   If (carrier <> BYTE_NULL) then
870     begin
871       temp := carrier;
872       If volume_scaling then
873         carrier := scale_volume(ins_parameter(voice_table[chan],3) AND $3f,carrier);
874       opl3out(_instr[03]+_chan_c[chan],
875               scale_volume(scale_volume(carrier,63-global_volume),63-overall_volume)+HI(vscale_table[chan]));
876       volume_table[chan] := concw(LO(volume_table[chan]),temp);
877       carrier_vol[chan] := 63-scale_volume(carrier,63-global_volume);
878     end;
879 end;
880
881 procedure reset_ins_volume(chan: Byte);
882 begin
883   If NOT volume_scaling then
884     set_ins_volume(ins_parameter(voice_table[chan],2) AND $3f,
885                    ins_parameter(voice_table[chan],3) AND $3f,chan)
886   else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
887          set_ins_volume(ins_parameter(voice_table[chan],2) AND $3f,0,chan)
888        else set_ins_volume(0,0,chan);
889 end;
890
891 procedure set_global_volume;
892
893 var
894   chan: Byte;
895
896 begin
897   For chan := 1 to songdata.nm_tracks do
898     If NOT ((carrier_vol[chan] = 0) and
899             (modulator_vol[chan] = 0)) then
900       If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
901         set_ins_volume(BYTE_NULL,HI(volume_table[chan]),chan)
902       else set_ins_volume(LO(volume_table[chan]),HI(volume_table[chan]),chan);
903 end;
904
905 procedure set_overall_volume(level: Byte);
906 begin
907   overall_volume := max(level,63);
908   set_global_volume;
909 end;
910
911 procedure init_macro_table(chan,note,ins: Byte; freq: Word);
912 begin
913   macro_table[chan].fmreg_count := 1;
914   macro_table[chan].fmreg_pos := 0;
915   macro_table[chan].fmreg_duration := 0;
916   macro_table[chan].fmreg_table := ins;
917   macro_table[chan].arpg_count := 1;
918   macro_table[chan].arpg_pos := 0;
919   macro_table[chan].arpg_table := songdata.instr_macros[ins].arpeggio_table;
920   macro_table[chan].arpg_note := note;
921   macro_table[chan].vib_count := 1;
922   macro_table[chan].vib_paused := FALSE;
923   macro_table[chan].vib_pos := 0;
924   macro_table[chan].vib_table := songdata.instr_macros[ins].vibrato_table;
925   macro_table[chan].vib_freq := freq;
926   macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
927 end;
928
929 procedure set_ins_data(ins,chan: Byte);
930
931 var
932   old_ins: Byte;
933
934 begin
935   If (ins <> event_table[chan].instr_def) or reset_chan[chan] then
936     begin
937       opl3out(_instr[02]+_chan_m[chan],63);
938       opl3out(_instr[03]+_chan_c[chan],63);
939
940       If NOT pan_lock[chan] then
941         panning_table[chan] := ins_parameter(ins,11)
942       else panning_table[chan] := songdata.lock_flags[chan] AND 3;
943
944       opl3out(_instr[00]+_chan_m[chan],ins_parameter(ins,0));
945       opl3out(_instr[01]+_chan_c[chan],ins_parameter(ins,1));
946       opl3out(_instr[04]+_chan_m[chan],ins_parameter(ins,4));
947       opl3out(_instr[05]+_chan_c[chan],ins_parameter(ins,5));
948       opl3out(_instr[06]+_chan_m[chan],ins_parameter(ins,6));
949       opl3out(_instr[07]+_chan_c[chan],ins_parameter(ins,7));
950       opl3out(_instr[08]+_chan_m[chan],ins_parameter(ins,8));
951       opl3out(_instr[09]+_chan_c[chan],ins_parameter(ins,9));
952       opl3out(_instr[10]+_chan_n[chan],ins_parameter(ins,10) OR _panning[panning_table[chan]]);
953
954       fmpar_table[chan].connect := ins_parameter(ins,10) AND 1;
955       fmpar_table[chan].feedb   := ins_parameter(ins,10) SHR 1 AND 7;
956       fmpar_table[chan].multipM := ins_parameter(ins,0)  AND $0f;
957       fmpar_table[chan].kslM    := ins_parameter(ins,2)  SHR 6;
958       fmpar_table[chan].tremM   := ins_parameter(ins,0)  SHR 7;
959       fmpar_table[chan].vibrM   := ins_parameter(ins,0)  SHR 6 AND 1;
960       fmpar_table[chan].ksrM    := ins_parameter(ins,0)  SHR 4 AND 1;
961       fmpar_table[chan].sustM   := ins_parameter(ins,0)  SHR 5 AND 1;
962       fmpar_table[chan].multipC := ins_parameter(ins,1)  AND $0f;
963       fmpar_table[chan].kslC    := ins_parameter(ins,3)  SHR 6;
964       fmpar_table[chan].tremC   := ins_parameter(ins,1)  SHR 7;
965       fmpar_table[chan].vibrC   := ins_parameter(ins,1)  SHR 6 AND 1;
966       fmpar_table[chan].ksrC    := ins_parameter(ins,1)  SHR 4 AND 1;
967       fmpar_table[chan].sustC   := ins_parameter(ins,1)  SHR 5 AND 1;
968
969       fmpar_table[chan].adsrw_car.attck := ins_parameter(ins,5) SHR 4;
970       fmpar_table[chan].adsrw_mod.attck := ins_parameter(ins,4) SHR 4;
971       fmpar_table[chan].adsrw_car.dec   := ins_parameter(ins,5) AND $0f;
972       fmpar_table[chan].adsrw_mod.dec   := ins_parameter(ins,4) AND $0f;
973       fmpar_table[chan].adsrw_car.sustn := ins_parameter(ins,7) SHR 4;
974       fmpar_table[chan].adsrw_mod.sustn := ins_parameter(ins,6) SHR 4;
975       fmpar_table[chan].adsrw_car.rel   := ins_parameter(ins,7) AND $0f;
976       fmpar_table[chan].adsrw_mod.rel   := ins_parameter(ins,6) AND $0f;
977       fmpar_table[chan].adsrw_car.wform := ins_parameter(ins,9) AND $07;
978       fmpar_table[chan].adsrw_mod.wform := ins_parameter(ins,8) AND $07;
979
980       If NOT reset_chan[chan] then
981         keyoff_loop[chan] := FALSE;
982
983       If reset_chan[chan] then
984         begin
985           voice_table[chan] := ins;
986           reset_ins_volume(chan);
987           reset_chan[chan] := FALSE;
988         end;
989
990       If (event_table[chan].note AND $7f in [1..12*8+1]) then
991         init_macro_table(chan,event_table[chan].note AND $7f,ins,freq_table[chan])
992       else init_macro_table(chan,0,ins,freq_table[chan]);
993     end;
994
995   vscale_table[chan] := concw(fmpar_table[chan].kslM SHL 6,
996                               fmpar_table[chan].kslC SHL 6);
997   voice_table[chan] := ins;
998   old_ins := event_table[chan].instr_def;
999   event_table[chan].instr_def := ins;
1000
1001   If NOT volume_lock[chan] or
1002      (ins <> old_ins) then reset_ins_volume(chan);
1003 end;
1004
1005 procedure update_modulator_adsrw(chan: Byte);
1006 begin
1007   opl3out(_instr[04]+_chan_m[chan],
1008           fmpar_table[chan].adsrw_mod.attck SHL 4+
1009           fmpar_table[chan].adsrw_mod.dec);
1010   opl3out(_instr[06]+_chan_m[chan],
1011           fmpar_table[chan].adsrw_mod.sustn SHL 4+
1012           fmpar_table[chan].adsrw_mod.rel);
1013   opl3out(_instr[08]+_chan_m[chan],
1014           fmpar_table[chan].adsrw_mod.wform);
1015 end;
1016
1017 procedure update_carrier_adsrw(chan: Byte);
1018 begin
1019   opl3out(_instr[05]+_chan_c[chan],
1020           fmpar_table[chan].adsrw_car.attck SHL 4+
1021           fmpar_table[chan].adsrw_car.dec);
1022   opl3out(_instr[07]+_chan_c[chan],
1023           fmpar_table[chan].adsrw_car.sustn SHL 4+
1024           fmpar_table[chan].adsrw_car.rel);
1025   opl3out(_instr[09]+_chan_c[chan],
1026           fmpar_table[chan].adsrw_car.wform);
1027 end;
1028
1029 procedure update_fmpar(chan: Byte);
1030 begin
1031   opl3out(_instr[00]+_chan_m[chan],fmpar_table[chan].multipM+
1032                                    fmpar_table[chan].ksrM  SHL 4+
1033                                    fmpar_table[chan].sustM SHL 5+
1034                                    fmpar_table[chan].vibrM SHL 6+
1035                                    fmpar_table[chan].tremM SHL 7);
1036   opl3out(_instr[01]+_chan_c[chan],fmpar_table[chan].multipC+
1037                                    fmpar_table[chan].ksrC  SHL 4+
1038                                    fmpar_table[chan].sustC SHL 5+
1039                                    fmpar_table[chan].vibrC SHL 6+
1040                                    fmpar_table[chan].tremC SHL 7);
1041
1042   opl3out(_instr[10]+_chan_n[chan],(fmpar_table[chan].connect+
1043                                     fmpar_table[chan].feedb SHL 1) OR
1044                                    _panning[panning_table[chan]]);
1045
1046   vscale_table[chan] := concw(fmpar_table[chan].kslM SHL 6,
1047                               fmpar_table[chan].kslC SHL 6);
1048   set_ins_volume(LO(volume_table[chan]),
1049                  HI(volume_table[chan]),chan);
1050 end;
1051
1052 function is_4op_chan(chan: Byte): Boolean; assembler;
1053 asm
1054         mov     al,byte ptr [songdata.flag_4op]
1055         mov     ah,chan
1056         test    al,1
1057         jz      @@1
1058         cmp     ah,1
1059         jb      @@1
1060         cmp     ah,2
1061         ja      @@1
1062         mov     al,TRUE
1063         jmp     @@7
1064 @@1:    test    al,2
1065         jz      @@2
1066         cmp     ah,3
1067         jb      @@2
1068         cmp     ah,4
1069         ja      @@2
1070         mov     al,TRUE
1071         jmp     @@7
1072 @@2:    test    al,4
1073         jz      @@3
1074         cmp     ah,5
1075         jb      @@3
1076         cmp     ah,6
1077         ja      @@3
1078         mov     al,TRUE
1079         jmp     @@7
1080 @@3:    test    al,8
1081         jz      @@4
1082         cmp     ah,10
1083         jb      @@4
1084         cmp     ah,11
1085         ja      @@4
1086         mov     al,TRUE
1087         jmp     @@7
1088 @@4:    test    al,10h
1089         jz      @@5
1090         cmp     ah,12
1091         jb      @@5
1092         cmp     ah,13
1093         ja      @@5
1094         mov     al,TRUE
1095         jmp     @@7
1096 @@5:    test    al,20h
1097         jz      @@6
1098         cmp     ah,14
1099         jb      @@6
1100         cmp     ah,15
1101         ja      @@6
1102         mov     al,TRUE
1103         jmp     @@7
1104 @@6:    mov     al,FALSE
1105 @@7:
1106 end;
1107
1108 procedure output_note(note,ins,chan: Byte; restart_macro: Boolean);
1109
1110 var
1111   pos: Byte;
1112   freq: Word;
1113
1114 begin
1115   If (note = 0) and (ftune_table[chan] = 0) then EXIT;
1116   If NOT (note in [1..12*8+1]) then freq := freq_table[chan]
1117   else begin
1118          freq := nFreq(note-1)+SHORTINT(ins_parameter(ins,12));
1119          If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
1120            opl3out($0b0+_chan_n[chan],0);
1121
1122          freq_table[chan] := concw(LO(freq_table[chan]),
1123                                    HI(freq_table[chan]) OR $20);
1124
1125          pos := Round(25/(12*8+1)*note);
1126          If (decay_bar[pos].lvl <> 0) then
1127            If (pos > 1) and
1128               (decay_bar[pos-1].dir <> 1) then
1129              Dec(pos)
1130            else If (pos < 25) and
1131                    (decay_bar[pos+1].lvl <> 1) then
1132                   Inc(pos);
1133
1134          If is_4op_chan(chan) then
1135            If (chan in [2,4,6,11,13,15]) then
1136              begin
1137                decay_bar[pos].dir := 1;
1138                If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1139                  decay_bar[pos].max_lvl :=
1140                    (carrier_vol[PRED(chan)]+carrier_vol[chan]) DIV 2
1141                else decay_bar[pos].max_lvl :=
1142                       (carrier_vol[PRED(chan)]+modulator_vol[PRED(chan)]+
1143                        carrier_vol[chan]+modulator_vol[chan]) DIV 4;
1144              end
1145            else
1146          else
1147            begin
1148              decay_bar[pos].dir := 1;
1149              If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1150                decay_bar[pos].max_lvl :=
1151                  carrier_vol[chan]
1152              else decay_bar[pos].max_lvl :=
1153                     (carrier_vol[chan]+modulator_vol[chan]) DIV 2;
1154            end;
1155        end;
1156
1157   If (ftune_table[chan] = -127) then ftune_table[chan] := 0;
1158   freq := freq+ftune_table[chan];
1159
1160   If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
1161     change_frequency(chan,freq);
1162
1163   If (note <> 0) then
1164     begin
1165       event_table[chan].note := note;
1166       If restart_macro then
1167         With event_table[chan] do
1168            If NOT (((effect_def = ef_Extended) and
1169                    (effect DIV 16 = ef_ex_ExtendedCmd) and
1170                    (effect MOD 16 = ef_ex_cmd_NoRestart)) or
1171                   ((effect_def2 = ef_Extended) and
1172                    (effect2 DIV 16 = ef_ex_ExtendedCmd) and
1173                    (effect2 MOD 16 = ef_ex_cmd_NoRestart))) then
1174              init_macro_table(chan,note,ins,freq)
1175            else macro_table[chan].arpg_note := note;
1176     end;
1177 end;
1178
1179 procedure output_note_NR(note,ins,chan: Byte; restart_macro: Boolean);
1180
1181 var
1182   pos: Byte;
1183   freq: Word;
1184
1185 begin
1186   If (note = 0) and (ftune_table[chan] = 0) then EXIT;
1187   If NOT (note in [1..12*8+1]) then freq := freq_table[chan]
1188   else begin
1189          freq := nFreq(note-1)+SHORTINT(ins_parameter(ins,12));
1190          freq_table[chan] := concw(LO(freq_table[chan]),
1191                                    HI(freq_table[chan]) OR $20);
1192
1193          pos := Round(25/(12*8+1)*note);
1194          If (decay_bar[pos].lvl <> 0) then
1195            If (pos > 1) and
1196               (decay_bar[pos-1].dir <> 1) then
1197              Dec(pos)
1198            else If (pos < 25) and
1199                    (decay_bar[pos+1].lvl <> 1) then
1200                   Inc(pos);
1201
1202          If is_4op_chan(chan) then
1203            If (chan in [2,4,6,11,13,15]) then
1204              begin
1205                decay_bar[pos].dir := 1;
1206                If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1207                  decay_bar[pos].max_lvl :=
1208                    (carrier_vol[PRED(chan)]+carrier_vol[chan]) DIV 2
1209                else decay_bar[pos].max_lvl :=
1210                       (carrier_vol[PRED(chan)]+modulator_vol[PRED(chan)]+
1211                        carrier_vol[chan]+modulator_vol[chan]) DIV 4;
1212              end
1213            else
1214          else
1215            begin
1216              decay_bar[pos].dir := 1;
1217              If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1218                decay_bar[pos].max_lvl :=
1219                  carrier_vol[chan]
1220              else decay_bar[pos].max_lvl :=
1221                     (carrier_vol[chan]+modulator_vol[chan]) DIV 2;
1222            end;
1223        end;
1224
1225   If (ftune_table[chan] = -127) then ftune_table[chan] := 0;
1226   freq := freq+ftune_table[chan];
1227
1228   If NOT (is_4op_chan(chan) and (chan in [1,3,5,10,12,14])) then
1229     change_frequency(chan,freq);
1230
1231   If (note <> 0) then
1232     begin
1233       event_table[chan].note := note;
1234       If restart_macro then
1235         With event_table[chan] do
1236            If NOT (((effect_def = ef_Extended) and
1237                    (effect DIV 16 = ef_ex_ExtendedCmd) and
1238                    (effect MOD 16 = ef_ex_cmd_NoRestart)) or
1239                   ((effect_def2 = ef_Extended) and
1240                    (effect2 DIV 16 = ef_ex_ExtendedCmd) and
1241                    (effect2 MOD 16 = ef_ex_cmd_NoRestart))) then
1242              init_macro_table(chan,note,ins,freq)
1243            else macro_table[chan].arpg_note := note;
1244     end;
1245 end;
1246
1247 procedure generate_custom_vibrato(value: Byte);
1248
1249 const
1250   vibtab_size: array[0..15] of Byte = (
1251     16,16,16,16,32,32,32,32,64,64,64,64,128,128,128,128);
1252
1253 var
1254   mul_r: Real;
1255   mul_b: Byte;
1256   idx,idx2: Byte;
1257
1258 function min0(value: Longint): Longint;
1259 begin
1260   If (value >= 0) then min0 := value
1261   else min0 := 0;
1262 end;
1263
1264 begin
1265   Case value of
1266     // set default speed table
1267     0: begin
1268          vibtrem_table_size := def_vibtrem_table_size;
1269          Move(def_vibtrem_table,vibtrem_table,SizeOf(vibtrem_table));
1270        end;
1271
1272     // set custom speed table (fixed size = 32)
1273     1..239:
1274        begin
1275          vibtrem_table_size := def_vibtrem_table_size;
1276          mul_r := value/16;
1277          For idx2 := 0 to 7 do
1278           begin
1279             vibtrem_table[idx2*32] := 0;
1280             For idx := 1 to 16 do
1281               vibtrem_table[idx2*32+idx] := ROUND(idx*mul_r);
1282             For idx := 17 to 31 do
1283               vibtrem_table[idx2*32+idx] := ROUND((32-idx)*mul_r);
1284           end;
1285        end;
1286
1287     // set custom speed table (speed factor = 1-4)
1288     240..255:
1289        begin
1290          vibtrem_speed_factor := SUCC((value-240) MOD 4);
1291          vibtrem_table_size := 2*vibtab_size[value-240];
1292          mul_b := 256 DIV (vibtab_size[value-240]);
1293          For idx2 := 0 to PRED(128 DIV vibtab_size[value-240]) do
1294            begin
1295              vibtrem_table[2*vibtab_size[value-240]*idx2] := 0;
1296              For idx := 1 to vibtab_size[value-240] do
1297                vibtrem_table[2*vibtab_size[value-240]*idx2+idx] :=
1298                  min0(idx*mul_b-1);
1299              For idx := vibtab_size[value-240]+1 to
1300                         2*vibtab_size[value-240]-1 do
1301                vibtrem_table[2*vibtab_size[value-240]*idx2+idx] :=
1302                  min0((2*vibtab_size[value-240]-idx)*mul_b-1);
1303            end;
1304        end;
1305   end;
1306 end;
1307
1308 procedure update_fine_effects(chan: Byte); forward;
1309 procedure play_line;
1310
1311 var
1312   chan,idx: Byte;
1313   event: array[1..20] of tCHUNK;
1314   eLo,eHi,eLo2,eHi2: array[1..20] of Byte;
1315
1316 function no_loop(current_chan,current_line: Byte): Boolean;
1317
1318 var
1319   result: Boolean;
1320   chan: Byte;
1321
1322 begin
1323   result := TRUE;
1324   For chan := 1 to PRED(current_chan) do
1325     If (loop_table[chan][current_line] <> 0) and
1326        (loop_table[chan][current_line] <> BYTE_NULL) then
1327       begin
1328         result := FALSE;
1329         BREAK;
1330       end;
1331   no_loop := result;
1332 end;
1333
1334 function get_event(pattern,line,channel: Byte): tCHUNK;
1335 begin
1336   asm
1337         mov     esi,[pattdata]
1338         mov     edi,@result
1339         mov     al,pattern
1340         inc     al
1341         cmp     al,max_patterns
1342         jbe     @@1
1343         mov     ecx,CHUNK_SIZE
1344         xor     al,al
1345         rep     stosb
1346         jmp     @@2
1347 @@1:    xor     eax,eax
1348         mov     al,line
1349         mov     ebx,CHUNK_SIZE
1350         mul     ebx
1351         mov     ecx,eax
1352         xor     eax,eax
1353         mov     al,channel
1354         dec     eax
1355         mov     ebx,256*CHUNK_SIZE
1356         mul     ebx
1357         add     ecx,eax
1358         xor     eax,eax
1359         mov     al,pattern
1360         mov     ebx,8
1361         div     ebx
1362         push    eax
1363         mov     eax,edx
1364         mov     ebx,20*256*CHUNK_SIZE
1365         mul     ebx
1366         add     ecx,eax
1367         pop     eax
1368         mov     ebx,8*20*256*CHUNK_SIZE
1369         mul     ebx
1370         add     ecx,eax
1371         add     esi,ecx
1372         mov     ecx,CHUNK_SIZE
1373         rep     movsb
1374 @@2:
1375   end;
1376 end;
1377
1378 begin
1379   _debug_str_ := 'A2PLAYER.PAS:play_line';
1380   If (current_line = 0) and
1381      (current_order = calc_following_order(0)) then
1382     time_playing := 0;
1383
1384   If NOT (pattern_break and (next_line AND $0f0 = pattern_loop_flag)) and
1385          (current_order <> last_order) then
1386     begin
1387       FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
1388       FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
1389       last_order := current_order;
1390     end;
1391
1392   For chan := 1 to songdata.nm_tracks do
1393     begin
1394       event[chan] := get_event(current_pattern,current_line,chan);
1395       If (effect_table[chan] <> 0) then last_effect[chan] := effect_table[chan];
1396       If (glfsld_table[chan] <> 0) then effect_table[chan] := glfsld_table[chan]
1397       else effect_table[chan] := effect_table[chan] AND $0ff00;
1398       If (effect_table2[chan] <> 0) then last_effect2[chan] := effect_table2[chan];
1399       If (glfsld_table2[chan] <> 0) then effect_table2[chan] := glfsld_table2[chan]
1400       else effect_table2[chan] := effect_table2[chan] AND $0ff00;
1401       ftune_table[chan] := 0;
1402
1403       If (event[chan].note = BYTE_NULL) then
1404         event[chan].note := event_table[chan].note OR keyoff_flag
1405       else If (event[chan].note in [fixed_note_flag+1..fixed_note_flag+12*8+1]) then
1406              event[chan].note := event[chan].note-fixed_note_flag;
1407
1408       If (event[chan].note <> 0) or
1409          (event[chan].effect_def <> 0) or
1410          (event[chan].effect_def2 <> 0) or
1411          ((event[chan].effect_def = 0) and (event[chan].effect <> 0)) or
1412          ((event[chan].effect_def2 = 0) and (event[chan].effect2 <> 0)) then
1413         event_new[chan] := TRUE
1414       else event_new[chan] := FALSE;
1415
1416       If (event[chan].note <> 0) or
1417          (event[chan].instr_def <> 0) or
1418          (event[chan].effect_def+event[chan].effect <> 0) or
1419          (event[chan].effect_def2+event[chan].effect2 <> 0) then
1420         begin
1421           event_table[chan].effect_def := event[chan].effect_def;
1422           event_table[chan].effect := event[chan].effect;
1423           event_table[chan].effect_def2 := event[chan].effect_def2;
1424           event_table[chan].effect2 := event[chan].effect2;
1425         end;
1426
1427       If (event[chan].instr_def <> 0) then
1428         If NOT Empty(songdata.instr_data[event[chan].instr_def],
1429                      INSTRUMENT_SIZE) then
1430           set_ins_data(event[chan].instr_def,chan)
1431         else begin
1432                release_sustaining_sound(chan);
1433                set_ins_data(event[chan].instr_def,chan);
1434              end;
1435
1436       If NOT (event[chan].effect_def in [ef_Vibrato,ef_ExtraFineVibrato,
1437                                    ef_VibratoVolSlide,ef_VibratoVSlideFine]) then
1438         FillChar(vibr_table[chan],SizeOf(vibr_table[chan]),0);
1439
1440       If NOT (event[chan].effect_def2 in [ef_Vibrato,ef_ExtraFineVibrato,
1441                                     ef_VibratoVolSlide,ef_VibratoVSlideFine]) then
1442         FillChar(vibr_table2[chan],SizeOf(vibr_table2[chan]),0);
1443
1444       If NOT (event[chan].effect_def in [ef_RetrigNote,ef_MultiRetrigNote]) then
1445         FillChar(retrig_table[chan],SizeOf(retrig_table[chan]),0);
1446
1447       If NOT (event[chan].effect_def2 in [ef_RetrigNote,ef_MultiRetrigNote]) then
1448         FillChar(retrig_table2[chan],SizeOf(retrig_table2[chan]),0);
1449
1450       If NOT (event[chan].effect_def in [ef_Tremolo,ef_ExtraFineTremolo]) then
1451         FillChar(trem_table[chan],SizeOf(trem_table[chan]),0);
1452
1453       If NOT (event[chan].effect_def2 in [ef_Tremolo,ef_ExtraFineTremolo]) then
1454         FillChar(trem_table2[chan],SizeOf(trem_table2[chan]),0);
1455
1456       If NOT (((event[chan].effect_def = ef_Arpeggio) and (event[chan].effect <> 0)) or
1457                (event[chan].effect_def = ef_ExtraFineArpeggio)) and
1458
1459
1460
1461
1462
1463                (arpgg_table[chan].note <> 0) and (arpgg_table[chan].state <> 1) then
1464         begin
1465           arpgg_table[chan].state := 1;
1466           change_frequency(chan,nFreq(arpgg_table[chan].note-1)+
1467             SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
1468         end
1469       else If NOT (((event[chan].effect_def2 = ef_Arpeggio) and (event[chan].effect2 <> 0)) or
1470                   (event[chan].effect_def2 = ef_ExtraFineArpeggio)) and
1471                   (arpgg_table2[chan].note <> 0) and (arpgg_table2[chan].state <> 1) then
1472              begin
1473                arpgg_table2[chan].state := 1;
1474                change_frequency(chan,nFreq(arpgg_table2[chan].note-1)+
1475                  SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
1476              end;
1477     end;
1478
1479   For chan := 1 to songdata.nm_tracks do
1480     begin
1481       If (tremor_table[chan].pos <> 0) and
1482          (event[chan].effect_def <> ef_Tremor) then
1483         begin
1484           tremor_table[chan].pos := 0;
1485           set_ins_volume(LO(tremor_table[chan].volume),
1486                          HI(tremor_table[chan].volume),chan);
1487         end;
1488
1489       If (tremor_table2[chan].pos <> 0) and
1490          (event[chan].effect_def2 <> ef_Tremor) then
1491         begin
1492           tremor_table2[chan].pos := 0;
1493           set_ins_volume(LO(tremor_table2[chan].volume),
1494                          HI(tremor_table2[chan].volume),chan);
1495         end;
1496
1497       eLo[chan]  := LO(last_effect[chan]);
1498       eHi[chan]  := HI(last_effect[chan]);
1499       eLo2[chan] := LO(last_effect2[chan]);
1500       eHi2[chan] := HI(last_effect2[chan]);
1501     end;
1502
1503   For chan := 1 to songdata.nm_tracks do
1504     Case event[chan].effect_def of
1505
1506       ef_Arpeggio,
1507       ef_ExtraFineArpeggio,
1508       ef_ArpggVSlide,
1509       ef_ArpggVSlideFine:
1510         If (event[chan].effect_def <> ef_Arpeggio) or
1511            (event[chan].effect <> 0) then
1512           begin
1513             Case event[chan].effect_def of
1514               ef_Arpeggio:
1515                 effect_table[chan] := concw(ef_Arpeggio+ef_fix1,event[chan].effect);
1516
1517               ef_ExtraFineArpeggio:
1518                 effect_table[chan] := concw(ef_ExtraFineArpeggio,event[chan].effect);
1519
1520               ef_ArpggVSlide,
1521               ef_ArpggVSlideFine:
1522                 If (event[chan].effect <> 0) then
1523                   effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1524                 else If (eLo[chan] in [ef_ArpggVSlide,ef_ArpggVSlideFine]) and
1525                         (eHi[chan] <> 0) then
1526                        effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
1527                      else effect_table[chan] := effect_table[chan] AND $0ff00;
1528             end;
1529
1530             If (event[chan].note AND $7f in [1..12*8+1]) then
1531               begin
1532                 arpgg_table[chan].state := 0;
1533                 arpgg_table[chan].note := event[chan].note AND $7f;
1534                 If (event[chan].effect_def in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
1535                   begin
1536                     arpgg_table[chan].add1 := event[chan].effect DIV 16;
1537                     arpgg_table[chan].add2 := event[chan].effect MOD 16;
1538                   end;
1539               end
1540             else If (event[chan].note = 0) and
1541                     (event_table[chan].note AND $7f in [1..12*8+1]) then
1542                    begin
1543                      If NOT (eLo[chan] in [ef_Arpeggio+ef_fix1,ef_ExtraFineArpeggio,
1544                                      ef_ArpggVSlide,ef_ArpggVSlideFine]) then
1545                        arpgg_table[chan].state := 0;
1546
1547                      arpgg_table[chan].note := event_table[chan].note AND $7f;
1548                      If (event[chan].effect_def in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
1549                        begin
1550                          arpgg_table[chan].add1 := event[chan].effect DIV 16;
1551                          arpgg_table[chan].add2 := event[chan].effect MOD 16;
1552                        end;
1553                    end
1554                  else effect_table[chan] := 0;
1555           end;
1556
1557       ef_FSlideUp,
1558       ef_FSlideDown,
1559       ef_FSlideUpFine,
1560       ef_FSlideDownFine:
1561         begin
1562           effect_table[chan] := concw(event[chan].effect_def,event[chan].effect);
1563           fslide_table[chan] := event[chan].effect;
1564         end;
1565
1566       ef_GlobalFSlideUp,
1567       ef_GlobalFSlideDown:
1568         begin
1569           If (event[chan].effect_def = ef_GlobalFSlideUp) then
1570             begin
1571               If (event[chan].effect_def2 = ef_Extended) and
1572                  (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
1573                 effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
1574                                             event[chan].effect)
1575               else If (event[chan].effect_def2 = ef_Extended) and
1576                       (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
1577                      effect_table[chan] := concw(ef_FSlideUpFine,event[chan].effect)
1578                    else effect_table[chan] := concw(ef_FSlideUp,event[chan].effect);
1579             end
1580           else
1581             begin
1582               If (event[chan].effect_def2 = ef_Extended) and
1583                  (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
1584                 effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
1585                                             event[chan].effect)
1586               else If (event[chan].effect_def2 = ef_Extended) and
1587                       (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
1588                      effect_table[chan] := concw(ef_FSlideDownFine,event[chan].effect)
1589                    else effect_table[chan] := concw(ef_FSlideDown,event[chan].effect);
1590             end;
1591           For idx := chan to songdata.nm_tracks do
1592             begin
1593               fslide_table[idx] := event[chan].effect;
1594               glfsld_table[idx] := effect_table[chan];
1595             end;
1596         end;
1597
1598       ef_FSlideUpVSlide,
1599       ef_FSlUpVSlF,
1600       ef_FSlideDownVSlide,
1601       ef_FSlDownVSlF,
1602       ef_FSlUpFineVSlide,
1603       ef_FSlUpFineVSlF,
1604       ef_FSlDownFineVSlide,
1605       ef_FSlDownFineVSlF:
1606         If (event[chan].effect <> 0) then
1607           effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1608         else If (eLo[chan] in [ef_FSlideUpVSlide,ef_FSlUpVSlF,ef_FSlideDownVSlide,
1609                          ef_FSlDownVSlF,ef_FSlUpFineVSlide,ef_FSlUpFineVSlF,
1610                          ef_FSlDownFineVSlide,ef_FSlDownFineVSlF]) and
1611                 (eHi[chan] <> 0) then
1612                effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
1613              else effect_table[chan] := effect_table[chan] AND $0ff00;
1614
1615       ef_TonePortamento:
1616         If (event[chan].note in [1..12*8+1]) then
1617           begin
1618             If (event[chan].effect <> 0) then
1619               effect_table[chan] := concw(ef_TonePortamento,event[chan].effect)
1620             else If (eLo[chan] = ef_TonePortamento) and
1621                     (eHi[chan] <> 0) then
1622                    effect_table[chan] := concw(ef_TonePortamento,eHi[chan])
1623                  else effect_table[chan] := ef_TonePortamento;
1624
1625             porta_table[chan].speed := HI(effect_table[chan]);
1626             porta_table[chan].freq := nFreq(event[chan].note-1)+
1627               SHORTINT(ins_parameter(event_table[chan].instr_def,12));
1628           end
1629         else If (eLo[chan] = ef_TonePortamento) then
1630                begin
1631                  If (event[chan].effect <> 0) then
1632                    effect_table[chan] := concw(ef_TonePortamento,event[chan].effect)
1633                  else If (eLo[chan] = ef_TonePortamento) and
1634                          (eHi[chan] <> 0) then
1635                         effect_table[chan] := concw(ef_TonePortamento,eHi[chan])
1636                       else effect_table[chan] := ef_TonePortamento;
1637                  porta_table[chan].speed := HI(effect_table[chan]);
1638                end;
1639
1640       ef_TPortamVolSlide,
1641       ef_TPortamVSlideFine:
1642         If (event[chan].effect <> 0) then
1643           effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1644         else If (eLo[chan] in [ef_TPortamVolSlide,ef_TPortamVSlideFine]) and
1645                 (eHi[chan] <> 0) then
1646                effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
1647              else effect_table[chan] := effect_table[chan] AND $0ff00;
1648
1649       ef_Vibrato,
1650       ef_ExtraFineVibrato:
1651         begin
1652           If (event[chan].effect <> 0) then
1653             effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1654           else If (eLo[chan] in [ef_Vibrato,ef_ExtraFineVibrato]) and
1655                   (eHi[chan] <> 0) then
1656                  effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
1657                else effect_table[chan] := event[chan].effect_def;
1658
1659           If (event[chan].effect_def2 = ef_Extended) and
1660              (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
1661             vibr_table[chan].fine := TRUE;
1662
1663           vibr_table[chan].speed := HI(effect_table[chan]) DIV 16;
1664           vibr_table[chan].depth := HI(effect_table[chan]) MOD 16;
1665         end;
1666
1667       ef_Tremolo,
1668       ef_ExtraFineTremolo:
1669         begin
1670           If (event[chan].effect <> 0) then
1671             effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1672           else If (eLo[chan] in [ef_Tremolo,ef_ExtraFineTremolo]) and
1673                   (eHi[chan] <> 0) then
1674                  effect_table[chan] := concw(event[chan].effect_def,eHi[chan])
1675                else effect_table[chan] := event[chan].effect_def;
1676
1677           If (event[chan].effect_def2 = ef_Extended) and
1678              (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
1679             trem_table[chan].fine := TRUE;
1680
1681           trem_table[chan].speed := HI(effect_table[chan]) DIV 16;
1682           trem_table[chan].depth := HI(effect_table[chan]) MOD 16;
1683         end;
1684
1685       ef_VibratoVolSlide,
1686       ef_VibratoVSlideFine:
1687         begin
1688           If (event[chan].effect <> 0) then
1689             effect_table[chan] := concw(event[chan].effect_def,event[chan].effect)
1690           else If (eLo[chan] in [ef_VibratoVolSlide,ef_VibratoVSlideFine]) and
1691                   (HI(effect_table[chan]) <> 0) then
1692                  effect_table[chan] := concw(event[chan].effect_def,HI(effect_table[chan]))
1693                else effect_table[chan] := effect_table[chan] AND $0ff00;
1694
1695           If (event[chan].effect_def2 = ef_Extended) and
1696              (event[chan].effect2 = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
1697             vibr_table[chan].fine := TRUE;
1698         end;
1699
1700       ef_SetCarrierVol:
1701         set_ins_volume(BYTE_NULL,63-event[chan].effect,chan);
1702
1703       ef_SetModulatorVol:
1704         set_ins_volume(63-event[chan].effect,BYTE_NULL,chan);
1705
1706       ef_SetInsVolume:
1707         If percussion_mode and (chan in [17..20]) then
1708           set_ins_volume(63-event[chan].effect,BYTE_NULL,chan)
1709         else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1710                set_ins_volume(BYTE_NULL,63-event[chan].effect,chan)
1711              else set_ins_volume(63-event[chan].effect,63-event[chan].effect,chan);
1712
1713       ef_ForceInsVolume:
1714         If percussion_mode and (chan in [17..20]) then
1715           set_ins_volume(63-event[chan].effect,BYTE_NULL,chan)
1716         else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
1717                set_ins_volume(scale_volume(ins_parameter(voice_table[chan],2) AND $3f,63-event[chan].effect),63-event[chan].effect,chan)
1718              else set_ins_volume(63-event[chan].effect,63-event[chan].effect,chan);
1719
1720       ef_PositionJump:
1721         If no_loop(chan,current_line) then
1722           begin
1723             pattern_break := TRUE;
1724             next_line := pattern_break_flag+chan;
1725           end;
1726
1727       ef_PatternBreak:
1728         If no_loop(chan,current_line) then
1729           begin
1730             pattern_break := TRUE;
1731             next_line := max(event[chan].effect,PRED(songdata.patt_len));
1732           end;
1733
1734       ef_SetSpeed:
1735         speed := event[chan].effect;
1736
1737       ef_SetTempo:
1738         update_timer(event[chan].effect);
1739
1740       ef_SetWaveform:
1741         begin
1742           If (event[chan].effect DIV 16 in [0..7]) then
1743             begin
1744               fmpar_table[chan].adsrw_car.wform := event[chan].effect DIV 16;
1745               update_carrier_adsrw(chan);
1746             end;
1747
1748           If (event[chan].effect MOD 16 in [0..7]) then
1749             begin
1750               fmpar_table[chan].adsrw_mod.wform := event[chan].effect MOD 16;
1751               update_modulator_adsrw(chan);
1752             end;
1753         end;
1754
1755       ef_VolSlide:
1756         effect_table[chan] := concw(ef_VolSlide,event[chan].effect);
1757
1758       ef_VolSlideFine:
1759         effect_table[chan] := concw(ef_VolSlideFine,event[chan].effect);
1760
1761       ef_RetrigNote:
1762         If (event[chan].effect <> 0) then
1763           begin
1764             If NOT (eLo[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
1765               retrig_table[chan] := 1;
1766             effect_table[chan] := concw(ef_RetrigNote,event[chan].effect);
1767           end;
1768
1769       ef_SetGlobalVolume:
1770         begin
1771           global_volume := event[chan].effect;
1772           set_global_volume;
1773         end;
1774
1775       ef_MultiRetrigNote:
1776         If (event[chan].effect DIV 16 <> 0) then
1777           begin
1778             If NOT (eLo[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
1779               retrig_table[chan] := 1;
1780             effect_table[chan] := concw(ef_MultiRetrigNote,event[chan].effect);
1781           end;
1782
1783       ef_Tremor:
1784         If (event[chan].effect DIV 16 <> 0) and
1785            (event[chan].effect MOD 16 <> 0) then
1786         begin
1787           If (eLo[chan] <> ef_Tremor) then
1788             begin
1789               tremor_table[chan].pos := 0;
1790               tremor_table[chan].volume := volume_table[chan];
1791             end;
1792           effect_table[chan] := concw(ef_Tremor,event[chan].effect);
1793         end;
1794
1795       ef_Extended:
1796         Case (event[chan].effect DIV 16) of
1797           ef_ex_SetTremDepth:
1798             Case (event[chan].effect MOD 16) of
1799               0: begin
1800                    opl3out(_instr[11],misc_register AND $07f);
1801                    current_tremolo_depth := 0;
1802                  end;
1803
1804               1: begin
1805                    opl3out(_instr[11],misc_register OR $080);
1806                    current_tremolo_depth := 1;
1807                  end;
1808             end;
1809
1810           ef_ex_SetVibDepth:
1811             Case (event[chan].effect MOD 16) of
1812               0: begin
1813                    opl3out(_instr[11],misc_register AND $0bf);
1814                    current_vibrato_depth := 0;
1815                  end;
1816
1817               1: begin
1818                    opl3out(_instr[11],misc_register OR $040);
1819                    current_vibrato_depth := 1;
1820                  end;
1821             end;
1822
1823           ef_ex_SetAttckRateM:
1824             begin
1825               fmpar_table[chan].adsrw_mod.attck := event[chan].effect MOD 16;
1826               update_modulator_adsrw(chan);
1827             end;
1828
1829           ef_ex_SetDecayRateM:
1830             begin
1831               fmpar_table[chan].adsrw_mod.dec := event[chan].effect MOD 16;
1832               update_modulator_adsrw(chan);
1833             end;
1834
1835           ef_ex_SetSustnLevelM:
1836             begin
1837               fmpar_table[chan].adsrw_mod.sustn := event[chan].effect MOD 16;
1838               update_modulator_adsrw(chan);
1839             end;
1840
1841           ef_ex_SetRelRateM:
1842             begin
1843               fmpar_table[chan].adsrw_mod.rel := event[chan].effect MOD 16;
1844               update_modulator_adsrw(chan);
1845             end;
1846
1847           ef_ex_SetAttckRateC:
1848             begin
1849               fmpar_table[chan].adsrw_car.attck := event[chan].effect MOD 16;
1850               update_carrier_adsrw(chan);
1851             end;
1852
1853           ef_ex_SetDecayRateC:
1854             begin
1855               fmpar_table[chan].adsrw_car.dec := event[chan].effect MOD 16;
1856               update_carrier_adsrw(chan);
1857             end;
1858
1859           ef_ex_SetSustnLevelC:
1860             begin
1861               fmpar_table[chan].adsrw_car.sustn := event[chan].effect MOD 16;
1862               update_carrier_adsrw(chan);
1863             end;
1864
1865           ef_ex_SetRelRateC:
1866             begin
1867               fmpar_table[chan].adsrw_car.rel := event[chan].effect MOD 16;
1868               update_carrier_adsrw(chan);
1869             end;
1870
1871           ef_ex_SetFeedback:
1872             begin
1873               fmpar_table[chan].feedb := event[chan].effect MOD 16;
1874               update_fmpar(chan);
1875             end;
1876
1877           ef_ex_SetPanningPos:
1878             begin
1879               panning_table[chan] := event[chan].effect MOD 16;
1880               update_fmpar(chan);
1881             end;
1882
1883           ef_ex_PatternLoop,
1884           ef_ex_PatternLoopRec:
1885             If (event[chan].effect MOD 16 = 0) then
1886               loopbck_table[chan] := current_line
1887             else If (loopbck_table[chan] <> BYTE_NULL) then
1888                    begin
1889                      If (loop_table[chan][current_line] = BYTE_NULL) then
1890                        loop_table[chan][current_line] := event[chan].effect MOD 16;
1891                      If (loop_table[chan][current_line] <> 0) then
1892                        begin
1893                          pattern_break := TRUE;
1894                          next_line := pattern_loop_flag+chan;
1895                        end
1896                      else If (event[chan].effect DIV 16 = ef_ex_PatternLoopRec) then
1897                             loop_table[chan][current_line] := BYTE_NULL;
1898                    end;
1899
1900           ef_ex_MacroKOffLoop:
1901             If (event[chan].effect MOD 16 <> 0) then
1902               keyoff_loop[chan] := TRUE
1903             else keyoff_loop[chan] := FALSE;
1904
1905           ef_ex_ExtendedCmd:
1906             Case (event[chan].effect MOD 16) of
1907               ef_ex_cmd_RSS:        release_sustaining_sound(chan);
1908               ef_ex_cmd_ResetVol:   reset_ins_volume(chan);
1909               ef_ex_cmd_LockVol:    volume_lock  [chan] := TRUE;
1910               ef_ex_cmd_UnlockVol:  volume_lock  [chan] := FALSE;
1911               ef_ex_cmd_LockVP:     peak_lock    [chan] := TRUE;
1912               ef_ex_cmd_UnlockVP:   peak_lock    [chan] := FALSE;
1913               ef_ex_cmd_VSlide_def: volslide_type[chan] := 0;
1914               ef_ex_cmd_LockPan:    pan_lock     [chan] := TRUE;
1915               ef_ex_cmd_UnlockPan:  pan_lock     [chan] := FALSE;
1916               ef_ex_cmd_VibrOff:    change_frequency(chan,freq_table[chan]);
1917               ef_ex_cmd_TremOff:    set_ins_volume(LO(volume_table[chan]),
1918                                                    HI(volume_table[chan]),chan);
1919               ef_ex_cmd_VSlide_car:
1920                 If (event[chan].effect_def2 = ef_Extended) and
1921                    (event[chan].effect2 = ef_ex_ExtendedCmd*16+
1922                                     ef_ex_cmd_VSlide_mod) then
1923                   volslide_type[chan] := 3
1924                 else volslide_type[chan] := 1;
1925
1926               ef_ex_cmd_VSlide_mod:
1927                 If (event[chan].effect_def2 = ef_Extended) and
1928                    (event[chan].effect2 = ef_ex_ExtendedCmd*16+
1929                                     ef_ex_cmd_VSlide_car) then
1930                   volslide_type[chan] := 3
1931                 else volslide_type[chan] := 2;
1932             end;
1933         end;
1934
1935       ef_Extended2:
1936         Case (event[chan].effect DIV 16) of
1937           ef_ex2_PatDelayFrame,
1938           ef_ex2_PatDelayRow:
1939             begin
1940               pattern_delay := TRUE;
1941               If (event[chan].effect DIV 16 = ef_ex2_PatDelayFrame) then
1942                 tickD := (event[chan].effect MOD 16)
1943               else tickD := speed*(event[chan].effect MOD 16);
1944             end;
1945
1946           ef_ex2_NoteDelay:
1947             begin
1948               effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteDelay,0);
1949               notedel_table[chan] := event[chan].effect MOD 16;
1950             end;
1951
1952           ef_ex2_NoteCut:
1953             begin
1954               effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteCut,0);
1955               notecut_table[chan] := event[chan].effect MOD 16;
1956             end;
1957
1958           ef_ex2_FineTuneUp:
1959             Inc(ftune_table[chan],event[chan].effect MOD 16);
1960
1961           ef_ex2_FineTuneDown:
1962             Dec(ftune_table[chan],event[chan].effect MOD 16);
1963
1964           ef_ex2_GlVolSlideUp:
1965             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp,
1966                                         event[chan].effect MOD 16);
1967           ef_ex2_GlVolSlideDn:
1968             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn,
1969                                         event[chan].effect MOD 16);
1970           ef_ex2_GlVolSlideUpF:
1971             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF,
1972                                         event[chan].effect MOD 16);
1973           ef_ex2_GlVolSlideDnF:
1974             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF,
1975                                         event[chan].effect MOD 16);
1976           ef_ex2_GlVolSldUpXF:
1977             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF,
1978                                         event[chan].effect MOD 16);
1979           ef_ex2_GlVolSldDnXF:
1980             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF,
1981                                         event[chan].effect MOD 16);
1982           ef_ex2_VolSlideUpXF:
1983             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF,
1984                                         event[chan].effect MOD 16);
1985           ef_ex2_VolSlideDnXF:
1986             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF,
1987                                         event[chan].effect MOD 16);
1988           ef_ex2_FreqSlideUpXF:
1989             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
1990                                         event[chan].effect MOD 16);
1991           ef_ex2_FreqSlideDnXF:
1992             effect_table[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
1993                                         event[chan].effect MOD 16);
1994         end;
1995
1996       ef_Extended3:
1997         Case (event[chan].effect DIV 16) of
1998           ef_ex3_SetConnection:
1999             begin
2000               fmpar_table[chan].connect := event[chan].effect MOD 16;
2001               update_fmpar(chan);
2002             end;
2003
2004           ef_ex3_SetMultipM:
2005             begin
2006               fmpar_table[chan].multipM := event[chan].effect MOD 16;
2007               update_fmpar(chan);
2008             end;
2009
2010           ef_ex3_SetKslM:
2011             begin
2012               fmpar_table[chan].kslM := event[chan].effect MOD 16;
2013               update_fmpar(chan);
2014             end;
2015
2016           ef_ex3_SetTremoloM:
2017             begin
2018               fmpar_table[chan].tremM := event[chan].effect MOD 16;
2019               update_fmpar(chan);
2020             end;
2021
2022           ef_ex3_SetVibratoM:
2023             begin
2024               fmpar_table[chan].vibrM := event[chan].effect MOD 16;
2025               update_fmpar(chan);
2026             end;
2027
2028           ef_ex3_SetKsrM:
2029             begin
2030               fmpar_table[chan].ksrM := event[chan].effect MOD 16;
2031               update_fmpar(chan);
2032             end;
2033
2034           ef_ex3_SetSustainM:
2035             begin
2036               fmpar_table[chan].sustM := event[chan].effect MOD 16;
2037               update_fmpar(chan);
2038             end;
2039
2040           ef_ex3_SetMultipC:
2041             begin
2042               fmpar_table[chan].multipC := event[chan].effect MOD 16;
2043               update_fmpar(chan);
2044             end;
2045
2046           ef_ex3_SetKslC:
2047             begin
2048               fmpar_table[chan].kslC := event[chan].effect MOD 16;
2049               update_fmpar(chan);
2050             end;
2051
2052           ef_ex3_SetTremoloC:
2053             begin
2054               fmpar_table[chan].tremC := event[chan].effect MOD 16;
2055               update_fmpar(chan);
2056             end;
2057
2058           ef_ex3_SetVibratoC:
2059             begin
2060               fmpar_table[chan].vibrC := event[chan].effect MOD 16;
2061               update_fmpar(chan);
2062             end;
2063
2064           ef_ex3_SetKsrC:
2065             begin
2066               fmpar_table[chan].ksrC := event[chan].effect MOD 16;
2067               update_fmpar(chan);
2068             end;
2069
2070           ef_ex3_SetSustainC:
2071             begin
2072               fmpar_table[chan].sustC := event[chan].effect MOD 16;
2073               update_fmpar(chan);
2074             end;
2075         end;
2076     end;
2077
2078   For chan := 1 to songdata.nm_tracks do
2079     Case event[chan].effect_def2 of
2080       ef_Arpeggio,
2081       ef_ExtraFineArpeggio,
2082       ef_ArpggVSlide,
2083       ef_ArpggVSlideFine:
2084         If (event[chan].effect_def2 <> ef_Arpeggio) or
2085            (event[chan].effect2 <> 0) then
2086           begin
2087             Case event[chan].effect_def2 of
2088               ef_Arpeggio:
2089                 effect_table2[chan] := concw(ef_Arpeggio+ef_fix1,event[chan].effect2);
2090
2091               ef_ExtraFineArpeggio:
2092                 effect_table2[chan] := concw(ef_ExtraFineArpeggio,event[chan].effect2);
2093
2094               ef_ArpggVSlide,
2095               ef_ArpggVSlideFine:
2096                 If (event[chan].effect2 <> 0) then
2097                   effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2098                 else If (eLo2[chan] in [ef_ArpggVSlide,ef_ArpggVSlideFine]) and
2099                         (eHi2[chan] <> 0) then
2100                        effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
2101                      else effect_table2[chan] := effect_table2[chan] AND $0ff00;
2102             end;
2103
2104             If (event[chan].note AND $7f in [1..12*8+1]) then
2105               begin
2106                 arpgg_table2[chan].state := 0;
2107                 arpgg_table2[chan].note := event[chan].note AND $7f;
2108                 If (event[chan].effect_def2 in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
2109                   begin
2110                     arpgg_table2[chan].add1 := event[chan].effect2 DIV 16;
2111                     arpgg_table2[chan].add2 := event[chan].effect2 MOD 16;
2112                   end;
2113               end
2114             else If (event[chan].note = 0) and
2115                     (event_table[chan].note AND $7f in [1..12*8+1]) then
2116                    begin
2117                      If NOT (eLo2[chan] in [ef_Arpeggio+ef_fix1,ef_ExtraFineArpeggio,
2118                                      ef_ArpggVSlide,ef_ArpggVSlideFine]) then
2119                        arpgg_table2[chan].state := 0;
2120
2121                      arpgg_table2[chan].note := event_table[chan].note AND $7f;
2122                      If (event[chan].effect_def2 in [ef_Arpeggio,ef_ExtraFineArpeggio]) then
2123                        begin
2124                          arpgg_table2[chan].add1 := event[chan].effect2 DIV 16;
2125                          arpgg_table2[chan].add2 := event[chan].effect2 MOD 16;
2126                        end;
2127                    end
2128                  else effect_table2[chan] := 0;
2129           end;
2130
2131       ef_FSlideUp,
2132       ef_FSlideDown,
2133       ef_FSlideUpFine,
2134       ef_FSlideDownFine:
2135         begin
2136           effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2);
2137           fslide_table2[chan] := event[chan].effect2;
2138         end;
2139
2140       ef_GlobalFSlideUp,
2141       ef_GlobalFSlideDown:
2142         begin
2143           If (event[chan].effect_def2 = ef_GlobalFSlideUp) then
2144             begin
2145               If (event[chan].effect_def = ef_Extended) and
2146                  (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
2147                 effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
2148                                              event[chan].effect2)
2149               else If (event[chan].effect_def = ef_Extended) and
2150                       (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
2151                      effect_table2[chan] := concw(ef_FSlideUpFine,event[chan].effect2)
2152                    else effect_table2[chan] := concw(ef_FSlideUp,event[chan].effect2);
2153             end
2154           else
2155             begin
2156               If (event[chan].effect_def = ef_Extended) and
2157                  (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
2158                 effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
2159                                              event[chan].effect2)
2160               else If (event[chan].effect_def = ef_Extended) and
2161                       (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
2162                      effect_table2[chan] := concw(ef_FSlideDownFine,event[chan].effect2)
2163                    else effect_table2[chan] := concw(ef_FSlideDown,event[chan].effect2);
2164             end;
2165           For idx := chan to songdata.nm_tracks do
2166             begin
2167               fslide_table2[idx] := event[chan].effect2;
2168               glfsld_table2[idx] := effect_table2[chan];
2169             end;
2170         end;
2171
2172       ef_FSlideUpVSlide,
2173       ef_FSlUpVSlF,
2174       ef_FSlideDownVSlide,
2175       ef_FSlDownVSlF,
2176       ef_FSlUpFineVSlide,
2177       ef_FSlUpFineVSlF,
2178       ef_FSlDownFineVSlide,
2179       ef_FSlDownFineVSlF:
2180         If (event[chan].effect2 <> 0) then
2181           effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2182         else If (eLo2[chan] in [ef_FSlideUpVSlide,ef_FSlUpVSlF,ef_FSlideDownVSlide,
2183                          ef_FSlDownVSlF,ef_FSlUpFineVSlide,ef_FSlUpFineVSlF,
2184                          ef_FSlDownFineVSlide,ef_FSlDownFineVSlF]) and
2185                 (eHi2[chan] <> 0) then
2186                effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
2187              else effect_table2[chan] := effect_table2[chan] AND $0ff00;
2188
2189       ef_TonePortamento:
2190         If (event[chan].note in [1..12*8+1]) then
2191           begin
2192             If (event[chan].effect2 <> 0) then
2193               effect_table2[chan] := concw(ef_TonePortamento,event[chan].effect2)
2194             else If (eLo2[chan] = ef_TonePortamento) and
2195                     (eHi2[chan] <> 0) then
2196                    effect_table2[chan] := concw(ef_TonePortamento,eHi2[chan])
2197                  else effect_table2[chan] := ef_TonePortamento;
2198
2199             porta_table2[chan].speed := HI(effect_table2[chan]);
2200             porta_table2[chan].freq := nFreq(event[chan].note-1)+
2201               SHORTINT(ins_parameter(event_table[chan].instr_def,12));
2202           end
2203         else If (eLo2[chan] = ef_TonePortamento) then
2204                begin
2205                  If (event[chan].effect2 <> 0) then
2206                    effect_table2[chan] := concw(ef_TonePortamento,event[chan].effect2)
2207                  else If (eLo2[chan] = ef_TonePortamento) and
2208                          (eHi2[chan] <> 0) then
2209                         effect_table2[chan] := concw(ef_TonePortamento,eHi2[chan])
2210                       else effect_table2[chan] := ef_TonePortamento;
2211                  porta_table2[chan].speed := HI(effect_table2[chan]);
2212                end;
2213
2214       ef_TPortamVolSlide,
2215       ef_TPortamVSlideFine:
2216         If (event[chan].effect2 <> 0) then
2217           effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2218         else If (eLo2[chan] in [ef_TPortamVolSlide,ef_TPortamVSlideFine]) and
2219                 (eHi2[chan] <> 0) then
2220                effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
2221              else effect_table2[chan] := effect_table2[chan] AND $0ff00;
2222
2223       ef_Vibrato,
2224       ef_ExtraFineVibrato:
2225         begin
2226           If (event[chan].effect2 <> 0) then
2227             effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2228           else If (eLo2[chan] in [ef_Vibrato,ef_ExtraFineVibrato]) and
2229                   (eHi2[chan] <> 0) then
2230                  effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
2231                else effect_table2[chan] := event[chan].effect_def2;
2232
2233           If (event[chan].effect_def = ef_Extended) and
2234              (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
2235             vibr_table2[chan].fine := TRUE;
2236
2237           vibr_table2[chan].speed := HI(effect_table2[chan]) DIV 16;
2238           vibr_table2[chan].depth := HI(effect_table2[chan]) MOD 16;
2239         end;
2240
2241       ef_Tremolo,
2242       ef_ExtraFineTremolo:
2243         begin
2244           If (event[chan].effect2 <> 0) then
2245             effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2246           else If (eLo2[chan] in [ef_Tremolo,ef_ExtraFineTremolo]) and
2247                   (eHi2[chan] <> 0) then
2248                  effect_table2[chan] := concw(event[chan].effect_def2,eHi2[chan])
2249                else effect_table2[chan] := event[chan].effect_def2;
2250
2251           If (event[chan].effect_def = ef_Extended) and
2252              (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FTrm_XFGFS) then
2253             trem_table2[chan].fine := TRUE;
2254
2255           trem_table2[chan].speed := HI(effect_table2[chan]) DIV 16;
2256           trem_table2[chan].depth := HI(effect_table2[chan]) MOD 16;
2257         end;
2258
2259       ef_VibratoVolSlide,
2260       ef_VibratoVSlideFine:
2261         begin
2262           If (event[chan].effect2 <> 0) then
2263             effect_table2[chan] := concw(event[chan].effect_def2,event[chan].effect2)
2264           else If (eLo2[chan] in [ef_VibratoVolSlide,ef_VibratoVSlideFine]) and
2265                   (HI(effect_table2[chan]) <> 0) then
2266                  effect_table2[chan] := concw(event[chan].effect_def2,HI(effect_table2[chan]))
2267                else effect_table2[chan] := effect_table2[chan] AND $0ff00;
2268
2269           If (event[chan].effect_def = ef_Extended) and
2270              (event[chan].effect = ef_ex_ExtendedCmd*16+ef_ex_cmd_FVib_FGFS) then
2271             vibr_table2[chan].fine := TRUE;
2272         end;
2273
2274       ef_SetCarrierVol:
2275         set_ins_volume(BYTE_NULL,63-event[chan].effect2,chan);
2276
2277       ef_SetModulatorVol:
2278         set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan);
2279
2280       ef_SetInsVolume:
2281         If percussion_mode and (chan in [17..20]) then
2282           set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan)
2283         else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
2284                set_ins_volume(BYTE_NULL,63-event[chan].effect2,chan)
2285              else set_ins_volume(63-event[chan].effect2,63-event[chan].effect2,chan);
2286
2287       ef_ForceInsVolume:
2288         If percussion_mode and (chan in [17..20]) then
2289           set_ins_volume(63-event[chan].effect2,BYTE_NULL,chan)
2290         else If (ins_parameter(voice_table[chan],10) AND 1 = 0) then
2291                set_ins_volume(scale_volume(ins_parameter(voice_table[chan],2) AND $3f,63-event[chan].effect2),63-event[chan].effect2,chan)
2292              else set_ins_volume(63-event[chan].effect2,63-event[chan].effect2,chan);
2293
2294       ef_PositionJump:
2295         If no_loop(chan,current_line) then
2296           begin
2297             pattern_break := TRUE;
2298             next_line := pattern_break_flag+chan;
2299           end;
2300
2301       ef_PatternBreak:
2302         If no_loop(chan,current_line) then
2303           begin
2304             pattern_break := TRUE;
2305             next_line := max(event[chan].effect2,PRED(songdata.patt_len));
2306           end;
2307
2308       ef_SetSpeed:
2309         speed := event[chan].effect2;
2310
2311       ef_SetTempo:
2312         update_timer(event[chan].effect2);
2313
2314       ef_SetWaveform:
2315         begin
2316           If (event[chan].effect2 DIV 16 in [0..7]) then
2317             begin
2318               fmpar_table[chan].adsrw_car.wform := event[chan].effect2 DIV 16;
2319               update_carrier_adsrw(chan);
2320             end;
2321
2322           If (event[chan].effect2 MOD 16 in [0..7]) then
2323             begin
2324               fmpar_table[chan].adsrw_mod.wform := event[chan].effect2 MOD 16;
2325               update_modulator_adsrw(chan);
2326             end;
2327         end;
2328
2329       ef_VolSlide:
2330         effect_table2[chan] := concw(ef_VolSlide,event[chan].effect2);
2331
2332       ef_VolSlideFine:
2333         effect_table2[chan] := concw(ef_VolSlideFine,event[chan].effect2);
2334
2335       ef_RetrigNote:
2336         If (event[chan].effect2 <> 0) then
2337           begin
2338             If NOT (eLo2[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
2339               retrig_table2[chan] := 1;
2340             effect_table2[chan] := concw(ef_RetrigNote,event[chan].effect2);
2341           end;
2342
2343       ef_SetGlobalVolume:
2344         begin
2345           global_volume := event[chan].effect2;
2346           set_global_volume;
2347         end;
2348
2349       ef_MultiRetrigNote:
2350         If (event[chan].effect2 DIV 16 <> 0) then
2351           begin
2352             If NOT (eLo2[chan] in [ef_RetrigNote,ef_MultiRetrigNote]) then
2353               retrig_table2[chan] := 1;
2354             effect_table2[chan] := concw(ef_MultiRetrigNote,event[chan].effect2);
2355           end;
2356
2357       ef_Tremor:
2358         If (event[chan].effect2 DIV 16 <> 0) and
2359            (event[chan].effect2 MOD 16 <> 0) then
2360         begin
2361           If (eLo2[chan] <> ef_Tremor) then
2362             begin
2363               tremor_table2[chan].pos := 0;
2364               tremor_table2[chan].volume := volume_table[chan];
2365             end;
2366           effect_table2[chan] := concw(ef_Tremor,event[chan].effect2);
2367         end;
2368
2369       ef_Extended:
2370         Case (event[chan].effect2 DIV 16) of
2371           ef_ex_SetTremDepth:
2372             Case (event[chan].effect2 MOD 16) of
2373               0: begin
2374                    opl3out(_instr[11],misc_register AND $07f);
2375                    current_tremolo_depth := 0;
2376                  end;
2377
2378               1: begin
2379                    opl3out(_instr[11],misc_register OR $080);
2380                    current_tremolo_depth := 1;
2381                  end;
2382             end;
2383
2384           ef_ex_SetVibDepth:
2385             Case (event[chan].effect2 MOD 16) of
2386               0: begin
2387                    opl3out(_instr[11],misc_register AND $0bf);
2388                    current_vibrato_depth := 0;
2389                  end;
2390
2391               1: begin
2392                    opl3out(_instr[11],misc_register OR $040);
2393                    current_vibrato_depth := 1;
2394                  end;
2395             end;
2396
2397           ef_ex_SetAttckRateM:
2398             begin
2399               fmpar_table[chan].adsrw_mod.attck := event[chan].effect2 MOD 16;
2400               update_modulator_adsrw(chan);
2401             end;
2402
2403           ef_ex_SetDecayRateM:
2404             begin
2405               fmpar_table[chan].adsrw_mod.dec := event[chan].effect2 MOD 16;
2406               update_modulator_adsrw(chan);
2407             end;
2408
2409           ef_ex_SetSustnLevelM:
2410             begin
2411               fmpar_table[chan].adsrw_mod.sustn := event[chan].effect2 MOD 16;
2412               update_modulator_adsrw(chan);
2413             end;
2414
2415           ef_ex_SetRelRateM:
2416             begin
2417               fmpar_table[chan].adsrw_mod.rel := event[chan].effect2 MOD 16;
2418               update_modulator_adsrw(chan);
2419             end;
2420
2421           ef_ex_SetAttckRateC:
2422             begin
2423               fmpar_table[chan].adsrw_car.attck := event[chan].effect2 MOD 16;
2424               update_carrier_adsrw(chan);
2425             end;
2426
2427           ef_ex_SetDecayRateC:
2428             begin
2429               fmpar_table[chan].adsrw_car.dec := event[chan].effect2 MOD 16;
2430               update_carrier_adsrw(chan);
2431             end;
2432
2433           ef_ex_SetSustnLevelC:
2434             begin
2435               fmpar_table[chan].adsrw_car.sustn := event[chan].effect2 MOD 16;
2436               update_carrier_adsrw(chan);
2437             end;
2438
2439           ef_ex_SetRelRateC:
2440             begin
2441               fmpar_table[chan].adsrw_car.rel := event[chan].effect2 MOD 16;
2442               update_carrier_adsrw(chan);
2443             end;
2444
2445           ef_ex_SetFeedback:
2446             begin
2447               fmpar_table[chan].feedb := event[chan].effect2 MOD 16;
2448               update_fmpar(chan);
2449             end;
2450
2451           ef_ex_SetPanningPos:
2452             begin
2453               panning_table[chan] := event[chan].effect2 MOD 16;
2454               update_fmpar(chan);
2455             end;
2456
2457           ef_ex_PatternLoop,
2458           ef_ex_PatternLoopRec:
2459             If (event[chan].effect2 MOD 16 = 0) then
2460               loopbck_table[chan] := current_line
2461             else If (loopbck_table[chan] <> BYTE_NULL) then
2462                    begin
2463                      If (loop_table[chan][current_line] = BYTE_NULL) then
2464                        loop_table[chan][current_line] := event[chan].effect2 MOD 16;
2465                      If (loop_table[chan][current_line] <> 0) then
2466                        begin
2467                          pattern_break := TRUE;
2468                          next_line := pattern_loop_flag+chan;
2469                        end
2470                      else If (event[chan].effect2 DIV 16 = ef_ex_PatternLoopRec) then
2471                             loop_table[chan][current_line] := BYTE_NULL;
2472                    end;
2473
2474           ef_ex_MacroKOffLoop:
2475             If (event[chan].effect2 MOD 16 <> 0) then
2476               keyoff_loop[chan] := TRUE
2477             else keyoff_loop[chan] := FALSE;
2478
2479           ef_ex_ExtendedCmd:
2480             Case (event[chan].effect2 MOD 16) of
2481               ef_ex_cmd_RSS:        release_sustaining_sound(chan);
2482               ef_ex_cmd_ResetVol:   reset_ins_volume(chan);
2483               ef_ex_cmd_LockVol:    volume_lock  [chan] := TRUE;
2484               ef_ex_cmd_UnlockVol:  volume_lock  [chan] := FALSE;
2485               ef_ex_cmd_LockVP:     peak_lock    [chan] := TRUE;
2486               ef_ex_cmd_UnlockVP:   peak_lock    [chan] := FALSE;
2487               ef_ex_cmd_VSlide_def: volslide_type[chan] := 0;
2488               ef_ex_cmd_LockPan:    pan_lock     [chan] := TRUE;
2489               ef_ex_cmd_UnlockPan:  pan_lock     [chan] := FALSE;
2490               ef_ex_cmd_VibrOff:    change_frequency(chan,freq_table[chan]);
2491               ef_ex_cmd_TremOff:    set_ins_volume(LO(volume_table[chan]),
2492                                                    HI(volume_table[chan]),chan);
2493               ef_ex_cmd_VSlide_car:
2494                 If NOT ((event[chan].effect_def = ef_Extended) and
2495                         (event[chan].effect = ef_ex_ExtendedCmd*16+
2496                                         ef_ex_cmd_VSlide_mod)) then
2497                   volslide_type[chan] := 1;
2498
2499               ef_ex_cmd_VSlide_mod:
2500                 If NOT ((event[chan].effect_def = ef_Extended) and
2501                         (event[chan].effect = ef_ex_ExtendedCmd*16+
2502                                         ef_ex_cmd_VSlide_car)) then
2503                   volslide_type[chan] := 2;
2504             end;
2505         end;
2506
2507       ef_Extended2:
2508         Case (event[chan].effect2 DIV 16) of
2509           ef_ex2_PatDelayFrame,
2510           ef_ex2_PatDelayRow:
2511             begin
2512               pattern_delay := TRUE;
2513               If (event[chan].effect2 DIV 16 = ef_ex2_PatDelayFrame) then
2514                 tickD := (event[chan].effect2 MOD 16)
2515               else tickD := speed*(event[chan].effect2 MOD 16);
2516             end;
2517
2518           ef_ex2_NoteDelay:
2519             begin
2520               effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteDelay,0);
2521               notedel_table[chan] := event[chan].effect2 MOD 16;
2522             end;
2523
2524           ef_ex2_NoteCut:
2525             begin
2526               effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_NoteCut,0);
2527               notecut_table[chan] := event[chan].effect2 MOD 16;
2528             end;
2529
2530           ef_ex2_FineTuneUp:
2531             Inc(ftune_table[chan],event[chan].effect2 MOD 16);
2532
2533           ef_ex2_FineTuneDown:
2534             Dec(ftune_table[chan],event[chan].effect2 MOD 16);
2535
2536           ef_ex2_GlVolSlideUp:
2537             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp,
2538                                          event[chan].effect2 MOD 16);
2539           ef_ex2_GlVolSlideDn:
2540             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn,
2541                                          event[chan].effect2 MOD 16);
2542           ef_ex2_GlVolSlideUpF:
2543             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF,
2544                                          event[chan].effect2 MOD 16);
2545           ef_ex2_GlVolSlideDnF:
2546             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF,
2547                                          event[chan].effect2 MOD 16);
2548           ef_ex2_GlVolSldUpXF:
2549             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF,
2550                                          event[chan].effect2 MOD 16);
2551           ef_ex2_GlVolSldDnXF:
2552             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF,
2553                                          event[chan].effect2 MOD 16);
2554           ef_ex2_VolSlideUpXF:
2555             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF,
2556                                          event[chan].effect2 MOD 16);
2557           ef_ex2_VolSlideDnXF:
2558             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF,
2559                                          event[chan].effect2 MOD 16);
2560           ef_ex2_FreqSlideUpXF:
2561             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF,
2562                                          event[chan].effect2 MOD 16);
2563           ef_ex2_FreqSlideDnXF:
2564             effect_table2[chan] := concw(ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF,
2565                                          event[chan].effect2 MOD 16);
2566         end;
2567
2568       ef_Extended3:
2569         Case (event[chan].effect2 DIV 16) of
2570           ef_ex3_SetConnection:
2571             begin
2572               fmpar_table[chan].connect := event[chan].effect2 MOD 16;
2573               update_fmpar(chan);
2574             end;
2575
2576           ef_ex3_SetMultipM:
2577             begin
2578               fmpar_table[chan].multipM := event[chan].effect2 MOD 16;
2579               update_fmpar(chan);
2580             end;
2581
2582           ef_ex3_SetKslM:
2583             begin
2584               fmpar_table[chan].kslM := event[chan].effect2 MOD 16;
2585               update_fmpar(chan);
2586             end;
2587
2588           ef_ex3_SetTremoloM:
2589             begin
2590               fmpar_table[chan].tremM := event[chan].effect2 MOD 16;
2591               update_fmpar(chan);
2592             end;
2593
2594           ef_ex3_SetVibratoM:
2595             begin
2596               fmpar_table[chan].vibrM := event[chan].effect2 MOD 16;
2597               update_fmpar(chan);
2598             end;
2599
2600           ef_ex3_SetKsrM:
2601             begin
2602               fmpar_table[chan].ksrM := event[chan].effect2 MOD 16;
2603               update_fmpar(chan);
2604             end;
2605
2606           ef_ex3_SetSustainM:
2607             begin
2608               fmpar_table[chan].sustM := event[chan].effect2 MOD 16;
2609               update_fmpar(chan);
2610             end;
2611
2612           ef_ex3_SetMultipC:
2613             begin
2614               fmpar_table[chan].multipC := event[chan].effect2 MOD 16;
2615               update_fmpar(chan);
2616             end;
2617
2618           ef_ex3_SetKslC:
2619             begin
2620               fmpar_table[chan].kslC := event[chan].effect2 MOD 16;
2621               update_fmpar(chan);
2622             end;
2623
2624           ef_ex3_SetTremoloC:
2625             begin
2626               fmpar_table[chan].tremC := event[chan].effect2 MOD 16;
2627               update_fmpar(chan);
2628             end;
2629
2630           ef_ex3_SetVibratoC:
2631             begin
2632               fmpar_table[chan].vibrC := event[chan].effect2 MOD 16;
2633               update_fmpar(chan);
2634             end;
2635
2636           ef_ex3_SetKsrC:
2637             begin
2638               fmpar_table[chan].ksrC := event[chan].effect2 MOD 16;
2639               update_fmpar(chan);
2640             end;
2641
2642           ef_ex3_SetSustainC:
2643             begin
2644               fmpar_table[chan].sustC := event[chan].effect2 MOD 16;
2645               update_fmpar(chan);
2646             end;
2647         end;
2648     end;
2649
2650   For chan := 1 to songdata.nm_tracks do
2651     begin
2652       If (event[chan].effect_def+event[chan].effect = 0) then
2653         If (glfsld_table[chan] = 0) then effect_table[chan] := 0
2654       else begin
2655              event_table[chan].effect_def := event[chan].effect_def;
2656              event_table[chan].effect := event[chan].effect;
2657            end;
2658
2659       If (event[chan].effect_def2+event[chan].effect2 = 0) then
2660         If (glfsld_table2[chan] = 0) then effect_table2[chan] := 0
2661       else begin
2662              event_table[chan].effect_def2 := event[chan].effect_def2;
2663              event_table[chan].effect2 := event[chan].effect2;
2664            end;
2665
2666       If (event[chan].note = event[chan].note OR keyoff_flag) then key_off(chan)
2667       else If NOT (LO(effect_table[chan]) in  [ef_TonePortamento,
2668                                                ef_TPortamVolSlide,
2669                                                ef_TPortamVSlideFine,
2670                                                ef_extended2+ef_fix2+ef_ex2_NoteDelay]) and
2671               NOT (LO(effect_table2[chan]) in [ef_TonePortamento,
2672                                                ef_TPortamVolSlide,
2673                                                ef_TPortamVSlideFine,
2674                                                ef_extended2+ef_fix2+ef_ex2_NoteDelay]) then
2675              If NOT (((event[chan].effect_def2 = ef_SwapArpeggio) or
2676                       (event[chan].effect_def2 = ef_SwapVibrato)) and
2677                      (event[chan].effect_def = ef_Extended) and
2678                      (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
2679                      (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart)) and
2680                 NOT (((event[chan].effect_def = ef_SwapArpeggio) or
2681                       (event[chan].effect_def = ef_SwapVibrato)) and
2682                      (event[chan].effect_def2 = ef_Extended) and
2683                      (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
2684                      (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart)) then
2685                output_note(event[chan].note,voice_table[chan],chan,TRUE)
2686              else output_note_NR(event[chan].note,voice_table[chan],chan,TRUE)
2687           else If (event[chan].note <> 0) and
2688                   (event_table[chan].note = event_table[chan].note OR keyoff_flag) and
2689                   ((event[chan].effect_def in [ef_TonePortamento,
2690                                          ef_TPortamVolSlide,
2691                                          ef_TPortamVSlideFine]) or
2692                    (event[chan].effect_def2 in [ef_TonePortamento,
2693                                           ef_TPortamVolSlide,
2694                                           ef_TPortamVSlideFine])) then
2695                  output_note(event_table[chan].note AND NOT keyoff_flag,voice_table[chan],chan,FALSE)
2696                else If (event[chan].note <> 0) then
2697                       event_table[chan].note := event[chan].note;
2698
2699       Case event[chan].effect_def of
2700         ef_SwapArpeggio:
2701           begin
2702             If (event[chan].effect_def2 = ef_Extended) and
2703                (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
2704                (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart) then
2705               begin
2706                 If (macro_table[chan].arpg_pos >
2707                     songdata.macro_table[event[chan].effect].arpeggio.length) then
2708                   macro_table[chan].arpg_pos :=
2709                     songdata.macro_table[event[chan].effect].arpeggio.length;
2710                 macro_table[chan].arpg_table := event[chan].effect;
2711               end
2712             else begin
2713                    macro_table[chan].arpg_count := 1;
2714                    macro_table[chan].arpg_pos := 0;
2715                    macro_table[chan].arpg_table := event[chan].effect;
2716                    macro_table[chan].arpg_note := event_table[chan].note;
2717                  end;
2718           end;
2719
2720         ef_SwapVibrato:
2721           begin
2722             If (event[chan].effect_def2 = ef_Extended) and
2723                (event[chan].effect2 DIV 16 = ef_ex_ExtendedCmd) and
2724                (event[chan].effect2 MOD 16 = ef_ex_cmd_NoRestart) then
2725               begin
2726                 If (macro_table[chan].vib_table >
2727                     songdata.macro_table[event[chan].effect].vibrato.length) then
2728                   macro_table[chan].vib_pos :=
2729                     songdata.macro_table[event[chan].effect].vibrato.length;
2730                 macro_table[chan].vib_table := event[chan].effect;
2731               end
2732             else begin
2733                    macro_table[chan].vib_count := 1;
2734                    macro_table[chan].vib_pos := 0;
2735                    macro_table[chan].vib_table := event[chan].effect;
2736                    macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
2737                  end;
2738           end;
2739
2740         ef_SetCustomSpeedTab:
2741           generate_custom_vibrato(event[chan].effect);
2742       end;
2743
2744       Case event[chan].effect_def2 of
2745         ef_SwapArpeggio:
2746           begin
2747             If (event[chan].effect_def = ef_Extended) and
2748                (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
2749                (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart) then
2750               begin
2751                 If (macro_table[chan].arpg_pos >
2752                     songdata.macro_table[event[chan].effect2].arpeggio.length) then
2753                   macro_table[chan].arpg_pos :=
2754                     songdata.macro_table[event[chan].effect2].arpeggio.length;
2755                 macro_table[chan].arpg_table := event[chan].effect2;
2756               end
2757             else begin
2758                    macro_table[chan].arpg_count := 1;
2759                    macro_table[chan].arpg_pos := 0;
2760                    macro_table[chan].arpg_table := event[chan].effect2;
2761                    macro_table[chan].arpg_note := event_table[chan].note;
2762                  end;
2763           end;
2764
2765         ef_SwapVibrato:
2766           begin
2767             If (event[chan].effect_def = ef_Extended) and
2768                (event[chan].effect DIV 16 = ef_ex_ExtendedCmd) and
2769                (event[chan].effect MOD 16 = ef_ex_cmd_NoRestart) then
2770               begin
2771                 If (macro_table[chan].vib_table >
2772                     songdata.macro_table[event[chan].effect2].vibrato.length) then
2773                   macro_table[chan].vib_pos :=
2774                     songdata.macro_table[event[chan].effect2].vibrato.length;
2775                 macro_table[chan].vib_table := event[chan].effect2;
2776               end
2777             else begin
2778                    macro_table[chan].vib_count := 1;
2779                    macro_table[chan].vib_pos := 0;
2780                    macro_table[chan].vib_table := event[chan].effect2;
2781                    macro_table[chan].vib_delay := songdata.macro_table[macro_table[chan].vib_table].vibrato.delay;
2782                  end;
2783           end;
2784
2785         ef_SetCustomSpeedTab:
2786           generate_custom_vibrato(event[chan].effect2);
2787       end;
2788
2789       update_fine_effects(chan);
2790     end;
2791
2792   If pattern_delay then
2793     begin
2794       time_playing := time_playing+1/tempo*tickD;
2795       If (time_playing > 3600-1) then time_playing := 0;
2796     end
2797   else begin
2798          time_playing := time_playing+1/tempo*speed;
2799          If (time_playing > 3600-1) then time_playing := 0;
2800        end;
2801 end;
2802
2803 procedure portamento_up(chan: Byte; slide: Word; limit: Word);
2804
2805 var
2806   freq: Word;
2807
2808 begin
2809   freq := calc_freq_shift_up(freq_table[chan] AND $1fff,slide);
2810   If (freq <= limit) then change_frequency(chan,freq)
2811   else change_frequency(chan,limit);
2812 end;
2813
2814 procedure portamento_down(chan: Byte; slide: Word; limit: Word);
2815
2816 var
2817   freq: Word;
2818
2819 begin
2820   freq := calc_freq_shift_down(freq_table[chan] AND $1fff,slide);
2821   If (freq >= limit) then change_frequency(chan,freq)
2822   else change_frequency(chan,limit);
2823 end;
2824
2825 procedure macro_vibrato__porta_up(chan: Byte; depth: Byte);
2826
2827 var
2828   freq: Word;
2829
2830 begin
2831   freq := calc_freq_shift_up(macro_table[chan].vib_freq AND $1fff,depth);
2832   If (freq <= nFreq(12*8+1)) then change_freq(chan,freq)
2833   else change_freq(chan,nFreq(12*8+1));
2834 end;
2835
2836 procedure macro_vibrato__porta_down(chan: Byte; depth: Byte);
2837
2838 var
2839   freq: Word;
2840
2841 begin
2842   freq := calc_freq_shift_down(macro_table[chan].vib_freq AND $1fff,depth);
2843   If (freq >= nFreq(0)) then change_freq(chan,freq)
2844   else change_freq(chan,nFreq(0));
2845 end;
2846
2847 procedure tone_portamento(chan: Byte);
2848 begin
2849   If (freq_table[chan] AND $1fff > porta_table[chan].freq) then
2850     portamento_down(chan,porta_table[chan].speed,porta_table[chan].freq)
2851   else If (freq_table[chan] AND $1fff < porta_table[chan].freq) then
2852          portamento_up(chan,porta_table[chan].speed,porta_table[chan].freq);
2853 end;
2854
2855 procedure tone_portamento2(chan: Byte);
2856 begin
2857   If (freq_table[chan] AND $1fff > porta_table2[chan].freq) then
2858     portamento_down(chan,porta_table2[chan].speed,porta_table2[chan].freq)
2859   else If (freq_table[chan] AND $1fff < porta_table2[chan].freq) then
2860          portamento_up(chan,porta_table2[chan].speed,porta_table2[chan].freq);
2861 end;
2862
2863 procedure slide_volume_up(chan,slide: Byte);
2864
2865 var
2866   temp: Word;
2867   limit1,limit2,vLo,vHi: Byte;
2868
2869 procedure slide_carrier_volume_up;
2870 begin
2871   vLo := LO(temp);
2872   vHi := HI(temp);
2873   If (vHi-slide >= limit1) then temp := concw(vLo,vHi-slide)
2874   else temp := concw(vLo,limit1);
2875   set_ins_volume(BYTE_NULL,HI(temp),chan);
2876   volume_table[chan] := temp;
2877 end;
2878
2879 procedure slide_modulator_volume_up;
2880 begin
2881   vLo := LO(temp);
2882   vHi := HI(temp);
2883   If (vLo-slide >= limit2) then temp := concw(vLo-slide,vHi)
2884   else temp := concw(limit2,vHi);
2885   set_ins_volume(LO(temp),BYTE_NULL,chan);
2886   volume_table[chan] := temp;
2887 end;
2888
2889 begin
2890   If NOT peak_lock[chan] then limit1 := 0
2891   else limit1 := ins_parameter(event_table[chan].instr_def,3) AND $3f;
2892
2893   If NOT peak_lock[chan] then limit2 := 0
2894   else limit2 := ins_parameter(event_table[chan].instr_def,2) AND $3f;
2895   temp := volume_table[chan];
2896
2897   Case volslide_type[chan] of
2898     0: begin
2899          slide_carrier_volume_up;
2900          If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
2901             (percussion_mode and (chan in [17..20])) then
2902            slide_modulator_volume_up;
2903        end;
2904     1: slide_carrier_volume_up;
2905     2: slide_modulator_volume_up;
2906     3: begin
2907          slide_carrier_volume_up;
2908          slide_modulator_volume_up;
2909        end;
2910   end;
2911 end;
2912
2913 procedure slide_volume_down(chan,slide: Byte);
2914
2915 var
2916   temp: Word;
2917   vLo,vHi: Byte;
2918
2919 procedure slide_carrier_volume_down;
2920 begin
2921   vLo := LO(temp);
2922   vHi := HI(temp);
2923   If (vHi+slide <= 63) then temp := concw(vLo,vHi+slide)
2924   else temp := concw(vLo,63);
2925   set_ins_volume(BYTE_NULL,HI(temp),chan);
2926   volume_table[chan] := temp;
2927 end;
2928
2929 procedure slide_modulator_volume_down;
2930 begin
2931   vLo := LO(temp);
2932   vHi := HI(temp);
2933   If (vLo+slide <= 63) then temp := concw(vLo+slide,vHi)
2934   else temp := concw(63,vHi);
2935   set_ins_volume(LO(temp),BYTE_NULL,chan);
2936   volume_table[chan] := temp;
2937 end;
2938
2939 begin
2940   temp := volume_table[chan];
2941   Case volslide_type[chan] of
2942     0: begin
2943          slide_carrier_volume_down;
2944          If (ins_parameter(voice_table[chan],10) AND 1 = 1) or
2945             (percussion_mode and (chan in [17..20])) then
2946            slide_modulator_volume_down;
2947        end;
2948     1: slide_carrier_volume_down;
2949     2: slide_modulator_volume_down;
2950     3: begin
2951          slide_carrier_volume_down;
2952          slide_modulator_volume_down;
2953        end;
2954   end;
2955 end;
2956
2957 procedure volume_slide(chan,up_speed,down_speed: Byte);
2958 begin
2959   If (up_speed <> 0) then slide_volume_up(chan,up_speed)
2960   else If (down_speed <> 0) then slide_volume_down(chan,down_speed);
2961 end;
2962
2963 procedure global_volume_slide(up_speed,down_speed: Byte);
2964 begin
2965   If (up_speed <> BYTE_NULL) then
2966     global_volume := max(global_volume+up_speed,63);
2967   If (down_speed <> BYTE_NULL) then
2968     If (global_volume >= down_speed) then Dec(global_volume,down_speed)
2969     else global_volume := 0;
2970   set_global_volume;
2971 end;
2972
2973 procedure arpeggio(chan: Byte);
2974
2975 const
2976   arpgg_state: array[0..2] of Byte = (1,2,0);
2977
2978 var
2979   freq: Word;
2980
2981 begin
2982   Case arpgg_table[chan].state of
2983     0: freq := nFreq(arpgg_table[chan].note-1);
2984     1: freq := nFreq(arpgg_table[chan].note-1 +arpgg_table[chan].add1);
2985     2: freq := nFreq(arpgg_table[chan].note-1 +arpgg_table[chan].add2);
2986   end;
2987
2988   arpgg_table[chan].state := arpgg_state[arpgg_table[chan].state];
2989   change_frequency(chan,freq+
2990     SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
2991 end;
2992
2993 procedure arpeggio2(chan: Byte);
2994
2995 const
2996   arpgg_state: array[0..2] of Byte = (1,2,0);
2997
2998 var
2999   freq: Word;
3000
3001 begin
3002   Case arpgg_table2[chan].state of
3003     0: freq := nFreq(arpgg_table2[chan].note-1);
3004     1: freq := nFreq(arpgg_table2[chan].note-1 +arpgg_table2[chan].add1);
3005     2: freq := nFreq(arpgg_table2[chan].note-1 +arpgg_table2[chan].add2);
3006   end;
3007
3008   arpgg_table2[chan].state := arpgg_state[arpgg_table2[chan].state];
3009   change_frequency(chan,freq+
3010     SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
3011 end;
3012
3013 procedure vibrato(chan: Byte);
3014
3015 var
3016   freq,old_freq: Word;
3017   direction: Byte;
3018
3019 begin
3020   Inc(vibr_table[chan].pos,vibr_table[chan].speed*vibtrem_speed_factor);
3021   freq := calc_vibtrem_shift(vibr_table[chan].depth,
3022                              vibr_table[chan].pos,direction);
3023   old_freq := freq_table[chan];
3024   If (direction = 0) then portamento_down(chan,freq,nFreq(0))
3025   else portamento_up(chan,freq,nFreq(12*8+1));
3026   freq_table[chan] := old_freq;
3027 end;
3028
3029 procedure vibrato2(chan: Byte);
3030
3031 var
3032   freq,old_freq: Word;
3033   direction: Byte;
3034
3035 begin
3036   Inc(vibr_table2[chan].pos,vibr_table2[chan].speed*vibtrem_speed_factor);
3037   freq := calc_vibtrem_shift(vibr_table2[chan].depth,
3038                              vibr_table2[chan].pos,direction);
3039   old_freq := freq_table[chan];
3040   If (direction = 0) then portamento_down(chan,freq,nFreq(0))
3041   else portamento_up(chan,freq,nFreq(12*8+1));
3042   freq_table[chan] := old_freq;
3043 end;
3044
3045 procedure tremolo(chan: Byte);
3046
3047 var
3048   vol,old_vol: Word;
3049   direction: Byte;
3050
3051 begin
3052   Inc(trem_table[chan].pos,trem_table[chan].speed*vibtrem_speed_factor);
3053   vol := calc_vibtrem_shift(trem_table[chan].depth,
3054                             trem_table[chan].pos,direction);
3055   old_vol := volume_table[chan];
3056   If (direction = 0) then slide_volume_down(chan,vol)
3057   else slide_volume_up(chan,vol);
3058   volume_table[chan] := old_vol;
3059 end;
3060
3061 procedure tremolo2(chan: Byte);
3062
3063 var
3064   vol,old_vol: Word;
3065   direction: Byte;
3066
3067 begin
3068   Inc(trem_table2[chan].pos,trem_table2[chan].speed*vibtrem_speed_factor);
3069   vol := calc_vibtrem_shift(trem_table2[chan].depth,
3070                             trem_table2[chan].pos,direction);
3071   old_vol := volume_table[chan];
3072   If (direction = 0) then slide_volume_down(chan,vol)
3073   else slide_volume_up(chan,vol);
3074   volume_table[chan] := old_vol;
3075 end;
3076
3077 procedure update_effects;
3078
3079 var
3080   chan,eLo,eHi,
3081   eLo2,eHi2: Byte;
3082
3083 function chanvol(chan: Byte): Byte;
3084 begin
3085   If (ins_parameter(voice_table[chan],10) AND 1 = 0) then chanvol := 63-HI(volume_table[chan])
3086   else chanvol := 63-Round((LO(volume_table[chan])+HI(volume_table[chan]))/2);
3087 end;
3088
3089 begin
3090   For chan := 1 to songdata.nm_tracks do
3091     begin
3092       eLo  := LO(effect_table[chan]);
3093       eHi  := HI(effect_table[chan]);
3094       eLo2 := LO(effect_table2[chan]);
3095       eHi2 := HI(effect_table2[chan]);
3096
3097       Case eLo of
3098         ef_Arpeggio+ef_fix1:
3099           arpeggio(chan);
3100
3101         ef_ArpggVSlide:
3102           begin
3103             volume_slide(chan,eHi DIV 16,eHi MOD 16);
3104             arpeggio(chan);
3105           end;
3106
3107         ef_ArpggVSlideFine:
3108           arpeggio(chan);
3109
3110         ef_FSlideUp:
3111           portamento_up(chan,eHi,nFreq(12*8+1));
3112
3113         ef_FSlideDown:
3114           portamento_down(chan,eHi,nFreq(0));
3115
3116         ef_FSlideUpVSlide:
3117           begin
3118             portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
3119             volume_slide(chan,eHi DIV 16,eHi MOD 16);
3120           end;
3121
3122         ef_FSlUpVSlF:
3123           portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
3124
3125         ef_FSlideDownVSlide:
3126           begin
3127             portamento_down(chan,fslide_table[chan],nFreq(0));
3128             volume_slide(chan,eHi DIV 16,eHi MOD 16);
3129           end;
3130
3131         ef_FSlDownVSlF:
3132           portamento_down(chan,fslide_table[chan],nFreq(0));
3133
3134         ef_FSlUpFineVSlide:
3135           volume_slide(chan,eHi DIV 16,eHi MOD 16);
3136
3137         ef_FSlDownFineVSlide:
3138           volume_slide(chan,eHi DIV 16,eHi MOD 16);
3139
3140         ef_TonePortamento:
3141           tone_portamento(chan);
3142
3143         ef_TPortamVolSlide:
3144           begin
3145             volume_slide(chan,eHi DIV 16,eHi MOD 16);
3146             tone_portamento(chan);
3147           end;
3148
3149         ef_TPortamVSlideFine:
3150           tone_portamento(chan);
3151
3152         ef_Vibrato:
3153           If NOT vibr_table[chan].fine then
3154             vibrato(chan);
3155
3156         ef_Tremolo:
3157           If NOT trem_table[chan].fine then
3158             tremolo(chan);
3159
3160         ef_VibratoVolSlide:
3161           begin
3162             volume_slide(chan,eHi DIV 16,eHi MOD 16);
3163             If NOT vibr_table[chan].fine then
3164               vibrato(chan);
3165           end;
3166
3167         ef_VibratoVSlideFine:
3168           If NOT vibr_table[chan].fine then
3169             vibrato(chan);
3170
3171         ef_VolSlide:
3172           volume_slide(chan,eHi DIV 16,eHi MOD 16);
3173
3174         ef_RetrigNote:
3175           If (retrig_table[chan] >= eHi) then
3176             begin
3177               retrig_table[chan] := 0;
3178               output_note(event_table[chan].note,
3179                           event_table[chan].instr_def,chan,TRUE);
3180             end
3181           else Inc(retrig_table[chan]);
3182
3183         ef_MultiRetrigNote:
3184           If (retrig_table[chan] >= eHi DIV 16) then
3185             begin
3186               Case eHi MOD 16 of
3187                 0,8: ;
3188
3189                 1: slide_volume_down(chan,1);
3190                 2: slide_volume_down(chan,2);
3191                 3: slide_volume_down(chan,4);
3192                 4: slide_volume_down(chan,8);
3193                 5: slide_volume_down(chan,16);
3194
3195                 9: slide_volume_up(chan,1);
3196                10: slide_volume_up(chan,2);
3197                11: slide_volume_up(chan,4);
3198                12: slide_volume_up(chan,8);
3199                13: slide_volume_up(chan,16);
3200
3201
3202                 6: slide_volume_down(chan,chanvol(chan)-
3203                                           Round(chanvol(chan)*2/3));
3204                 7: slide_volume_down(chan,chanvol(chan)-
3205                                           Round(chanvol(chan)*1/2));
3206
3207                14: slide_volume_up(chan,max(Round(chanvol(chan)*3/2)-
3208                                             chanvol(chan),63));
3209                15: slide_volume_up(chan,max(Round(chanvol(chan)*2)-
3210                                             chanvol(chan),63));
3211               end;
3212
3213              retrig_table[chan] := 0;
3214              output_note(event_table[chan].note,
3215                          event_table[chan].instr_def,chan,TRUE);
3216             end
3217           else Inc(retrig_table[chan]);
3218
3219         ef_Tremor:
3220           If (tremor_table[chan].pos >= 0) then
3221             begin
3222               If (SUCC(tremor_table[chan].pos) <= eHi DIV 16) then
3223                 Inc(tremor_table[chan].pos)
3224               else begin
3225                      slide_volume_down(chan,63);
3226                      tremor_table[chan].pos := -1;
3227                    end;
3228             end
3229           else If (PRED(tremor_table[chan].pos) >= -(eHi MOD 16)) then
3230                  Dec(tremor_table[chan].pos)
3231                else begin
3232                       set_ins_volume(LO(tremor_table[chan].volume),
3233                                      HI(tremor_table[chan].volume),chan);
3234                       tremor_table[chan].pos := 1;
3235                     end;
3236
3237         ef_extended2+ef_fix2+ef_ex2_NoteDelay:
3238           If (notedel_table[chan] = 0) then
3239             begin
3240               notedel_table[chan] := BYTE_NULL;
3241               output_note(event_table[chan].note,
3242                           event_table[chan].instr_def,chan,TRUE);
3243             end
3244           else Dec(notedel_table[chan]);
3245
3246         ef_extended2+ef_fix2+ef_ex2_NoteCut:
3247           If (notecut_table[chan] = 0) then
3248             begin
3249               notecut_table[chan] := BYTE_NULL;
3250               key_off(chan);
3251             end
3252           else Dec(notecut_table[chan]);
3253
3254         ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp:
3255           global_volume_slide(eHi,BYTE_NULL);
3256
3257         ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn:
3258           global_volume_slide(BYTE_NULL,eHi);
3259       end;
3260
3261       Case eLo2 of
3262         ef_Arpeggio+ef_fix1:
3263           arpeggio2(chan);
3264
3265         ef_ArpggVSlide:
3266           begin
3267             volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3268             arpeggio2(chan);
3269           end;
3270
3271         ef_ArpggVSlideFine:
3272           arpeggio2(chan);
3273
3274         ef_FSlideUp:
3275           portamento_up(chan,eHi2,nFreq(12*8+1));
3276
3277         ef_FSlideDown:
3278           portamento_down(chan,eHi2,nFreq(0));
3279
3280         ef_FSlideUpVSlide:
3281           begin
3282             portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
3283             volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3284           end;
3285
3286         ef_FSlUpVSlF:
3287           portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
3288
3289         ef_FSlideDownVSlide:
3290           begin
3291             portamento_down(chan,fslide_table2[chan],nFreq(0));
3292             volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3293           end;
3294
3295         ef_FSlDownVSlF:
3296           portamento_down(chan,fslide_table2[chan],nFreq(0));
3297
3298         ef_FSlUpFineVSlide:
3299           volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3300
3301         ef_FSlDownFineVSlide:
3302           volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3303
3304         ef_TonePortamento:
3305           tone_portamento2(chan);
3306
3307         ef_TPortamVolSlide:
3308           begin
3309             volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3310             tone_portamento2(chan);
3311           end;
3312
3313         ef_TPortamVSlideFine:
3314           tone_portamento2(chan);
3315
3316         ef_Vibrato:
3317           If NOT vibr_table2[chan].fine then
3318             vibrato2(chan);
3319
3320         ef_Tremolo:
3321           If NOT trem_table2[chan].fine then
3322             tremolo2(chan);
3323
3324         ef_VibratoVolSlide:
3325           begin
3326             volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3327             If NOT vibr_table2[chan].fine then
3328               vibrato2(chan);
3329           end;
3330
3331         ef_VibratoVSlideFine:
3332           If NOT vibr_table2[chan].fine then
3333             vibrato2(chan);
3334
3335         ef_VolSlide:
3336           volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3337
3338         ef_RetrigNote:
3339           If (retrig_table2[chan] >= eHi2) then
3340             begin
3341               retrig_table2[chan] := 0;
3342               output_note(event_table[chan].note,
3343                           event_table[chan].instr_def,chan,TRUE);
3344             end
3345           else Inc(retrig_table2[chan]);
3346
3347         ef_MultiRetrigNote:
3348           If (retrig_table2[chan] >= eHi2 DIV 16) then
3349             begin
3350               Case eHi2 MOD 16 of
3351                 0,8: ;
3352
3353                 1: slide_volume_down(chan,1);
3354                 2: slide_volume_down(chan,2);
3355                 3: slide_volume_down(chan,4);
3356                 4: slide_volume_down(chan,8);
3357                 5: slide_volume_down(chan,16);
3358
3359                 9: slide_volume_up(chan,1);
3360                10: slide_volume_up(chan,2);
3361                11: slide_volume_up(chan,4);
3362                12: slide_volume_up(chan,8);
3363                13: slide_volume_up(chan,16);
3364
3365
3366                 6: slide_volume_down(chan,chanvol(chan)-
3367                                           Round(chanvol(chan)*2/3));
3368                 7: slide_volume_down(chan,chanvol(chan)-
3369                                           Round(chanvol(chan)*1/2));
3370
3371                14: slide_volume_up(chan,max(Round(chanvol(chan)*3/2)-
3372                                             chanvol(chan),63));
3373                15: slide_volume_up(chan,max(Round(chanvol(chan)*2)-
3374                                             chanvol(chan),63));
3375               end;
3376
3377               retrig_table2[chan] := 0;
3378               output_note(event_table[chan].note,
3379                           event_table[chan].instr_def,chan,TRUE);
3380             end
3381           else Inc(retrig_table2[chan]);
3382
3383         ef_Tremor:
3384           If (tremor_table2[chan].pos >= 0) then
3385             begin
3386               If (SUCC(tremor_table2[chan].pos) <= eHi2 DIV 16) then
3387                 Inc(tremor_table2[chan].pos)
3388               else begin
3389                      slide_volume_down(chan,63);
3390                      tremor_table2[chan].pos := -1;
3391                    end;
3392             end
3393           else If (PRED(tremor_table2[chan].pos) >= -(eHi2 MOD 16)) then
3394                  Dec(tremor_table2[chan].pos)
3395                else begin
3396                       set_ins_volume(LO(tremor_table2[chan].volume),
3397                                      HI(tremor_table2[chan].volume),chan);
3398                       tremor_table2[chan].pos := 1;
3399                     end;
3400
3401         ef_extended2+ef_fix2+ef_ex2_NoteDelay:
3402           If (notedel_table[chan] = 0) then
3403             begin
3404               notedel_table[chan] := BYTE_NULL;
3405               output_note(event_table[chan].note,
3406                           event_table[chan].instr_def,chan,TRUE);
3407             end
3408           else Dec(notedel_table[chan]);
3409
3410         ef_extended2+ef_fix2+ef_ex2_NoteCut:
3411           If (notecut_table[chan] = 0) then
3412             begin
3413               notecut_table[chan] := BYTE_NULL;
3414               key_off(chan);
3415             end
3416           else Dec(notecut_table[chan]);
3417
3418         ef_extended2+ef_fix2+ef_ex2_GlVolSlideUp:
3419           global_volume_slide(eHi2,BYTE_NULL);
3420
3421         ef_extended2+ef_fix2+ef_ex2_GlVolSlideDn:
3422           global_volume_slide(BYTE_NULL,eHi2);
3423       end;
3424     end;
3425 end;
3426
3427 procedure update_fine_effects(chan: Byte);
3428
3429 var
3430   eLo,eHi,
3431   eLo2,eHi2: Byte;
3432
3433 begin
3434   eLo  := LO(effect_table[chan]);
3435   eHi  := HI(effect_table[chan]);
3436   eLo2 := LO(effect_table2[chan]);
3437   eHi2 := HI(effect_table2[chan]);
3438
3439   Case eLo of
3440     ef_ArpggVSlideFine:
3441       volume_slide(chan,eHi DIV 16,eHi MOD 16);
3442
3443     ef_FSlideUpFine:
3444       portamento_up(chan,eHi,nFreq(12*8+1));
3445
3446     ef_FSlideDownFine:
3447       portamento_down(chan,eHi,nFreq(0));
3448
3449     ef_FSlUpVSlF:
3450       volume_slide(chan,eHi DIV 16,eHi MOD 16);
3451
3452     ef_FSlDownVSlF:
3453       volume_slide(chan,eHi DIV 16,eHi MOD 16);
3454
3455     ef_FSlUpFineVSlide:
3456       portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
3457
3458     ef_FSlUpFineVSlF:
3459       begin
3460         portamento_up(chan,fslide_table[chan],nFreq(12*8+1));
3461         volume_slide(chan,eHi DIV 16,eHi MOD 16);
3462       end;
3463
3464     ef_FSlDownFineVSlide:
3465       portamento_down(chan,fslide_table[chan],nFreq(0));
3466
3467     ef_FSlDownFineVSlF:
3468       begin
3469         portamento_down(chan,fslide_table[chan],nFreq(0));
3470         volume_slide(chan,eHi DIV 16,eHi MOD 16);
3471       end;
3472
3473     ef_TPortamVSlideFine:
3474       volume_slide(chan,eHi DIV 16,eHi MOD 16);
3475
3476     ef_Vibrato:
3477       If vibr_table[chan].fine then
3478         vibrato(chan);
3479
3480     ef_Tremolo:
3481       If trem_table[chan].fine then
3482         tremolo(chan);
3483
3484     ef_VibratoVolSlide:
3485       If vibr_table[chan].fine then
3486         vibrato(chan);
3487
3488     ef_VibratoVSlideFine:
3489       begin
3490         volume_slide(chan,eHi DIV 16,eHi MOD 16);
3491         If vibr_table[chan].fine then
3492           vibrato(chan);
3493       end;
3494
3495     ef_VolSlideFine:
3496       volume_slide(chan,eHi DIV 16,eHi MOD 16);
3497
3498     ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF:
3499       global_volume_slide(eHi,BYTE_NULL);
3500
3501     ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF:
3502       global_volume_slide(BYTE_NULL,eHi);
3503   end;
3504
3505   Case eLo2 of
3506     ef_ArpggVSlideFine:
3507       volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3508
3509     ef_FSlideUpFine:
3510       portamento_up(chan,eHi2,nFreq(12*8+1));
3511
3512     ef_FSlideDownFine:
3513       portamento_down(chan,eHi2,nFreq(0));
3514
3515     ef_FSlUpVSlF:
3516       volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3517
3518     ef_FSlDownVSlF:
3519       volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3520
3521     ef_FSlUpFineVSlide:
3522       portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
3523
3524     ef_FSlUpFineVSlF:
3525       begin
3526         portamento_up(chan,fslide_table2[chan],nFreq(12*8+1));
3527         volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3528       end;
3529
3530     ef_FSlDownFineVSlide:
3531       portamento_down(chan,fslide_table2[chan],nFreq(0));
3532
3533     ef_FSlDownFineVSlF:
3534       begin
3535         portamento_down(chan,fslide_table2[chan],nFreq(0));
3536         volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3537       end;
3538
3539     ef_TPortamVSlideFine:
3540       volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3541
3542     ef_Vibrato:
3543       If vibr_table2[chan].fine then
3544         vibrato2(chan);
3545
3546     ef_Tremolo:
3547       If trem_table2[chan].fine then
3548         tremolo2(chan);
3549
3550     ef_VibratoVolSlide:
3551       If vibr_table2[chan].fine then
3552         vibrato2(chan);
3553
3554     ef_VibratoVSlideFine:
3555       begin
3556         volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3557         If vibr_table2[chan].fine then
3558           vibrato2(chan);
3559       end;
3560
3561     ef_VolSlideFine:
3562       volume_slide(chan,eHi2 DIV 16,eHi2 MOD 16);
3563
3564     ef_extended2+ef_fix2+ef_ex2_GlVolSlideUpF:
3565       global_volume_slide(eHi2,BYTE_NULL);
3566
3567     ef_extended2+ef_fix2+ef_ex2_GlVolSlideDnF:
3568       global_volume_slide(BYTE_NULL,eHi2);
3569   end;
3570 end;
3571
3572 procedure update_extra_fine_effects;
3573
3574 var
3575   chan,eLo,eHi,
3576   eLo2,eHi2: Byte;
3577
3578 begin
3579   For chan := 1 to songdata.nm_tracks do
3580     begin
3581       eLo  := LO(effect_table[chan]);
3582       eHi  := HI(effect_table[chan]);
3583       eLo2 := LO(effect_table2[chan]);
3584       eHi2 := HI(effect_table2[chan]);
3585
3586       Case eLo of
3587         ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF:
3588           global_volume_slide(eHi,BYTE_NULL);
3589
3590         ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF:
3591           global_volume_slide(BYTE_NULL,eHi);
3592
3593         ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF:
3594           volume_slide(chan,eHi,0);
3595
3596         ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF:
3597           volume_slide(chan,0,eHi);
3598
3599         ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF:
3600           portamento_up(chan,eHi,nFreq(12*8+1));
3601
3602         ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF:
3603           portamento_down(chan,eHi,nFreq(0));
3604
3605         ef_ExtraFineArpeggio:
3606           arpeggio(chan);
3607
3608         ef_ExtraFineVibrato:
3609           If NOT vibr_table[chan].fine then
3610             vibrato(chan);
3611
3612         ef_ExtraFineTremolo:
3613           If NOT trem_table[chan].fine then
3614             tremolo(chan);
3615       end;
3616
3617       Case eLo2 of
3618         ef_extended2+ef_fix2+ef_ex2_GlVolSldUpXF:
3619           global_volume_slide(eHi2,BYTE_NULL);
3620
3621         ef_extended2+ef_fix2+ef_ex2_GlVolSldDnXF:
3622           global_volume_slide(BYTE_NULL,eHi2);
3623
3624         ef_extended2+ef_fix2+ef_ex2_VolSlideUpXF:
3625           volume_slide(chan,eHi2,0);
3626
3627         ef_extended2+ef_fix2+ef_ex2_VolSlideDnXF:
3628           volume_slide(chan,0,eHi2);
3629
3630         ef_extended2+ef_fix2+ef_ex2_FreqSlideUpXF:
3631           portamento_up(chan,eHi2,nFreq(12*8+1));
3632
3633         ef_extended2+ef_fix2+ef_ex2_FreqSlideDnXF:
3634           portamento_down(chan,eHi2,nFreq(0));
3635
3636         ef_ExtraFineArpeggio:
3637           arpeggio2(chan);
3638
3639         ef_ExtraFineVibrato:
3640           If NOT vibr_table2[chan].fine then
3641             vibrato2(chan);
3642
3643         ef_ExtraFineTremolo:
3644           If NOT trem_table2[chan].fine then
3645             tremolo2(chan);
3646       end;
3647     end;
3648 end;
3649
3650 function calc_following_order(order: Byte): Integer;
3651
3652 var
3653   result: Integer;
3654   index,jump_count: Byte;
3655
3656 begin
3657   _debug_str_ := 'A2PLAYER.PAS:calc_following_order';
3658   result := -1;
3659   index := order;
3660   jump_count := 0;
3661
3662   Repeat
3663     If (songdata.pattern_order[index] < $80) then result := index
3664     else begin
3665            index := songdata.pattern_order[index]-$80;
3666            Inc(jump_count);
3667          end;
3668   until (jump_count > $7f) or
3669         (result <> -1);
3670
3671   calc_following_order := result;
3672 end;
3673
3674 function calc_order_jump: Integer;
3675
3676 var
3677   temp: Byte;
3678   result: Integer;
3679
3680 begin
3681   _debug_str_ := 'A2PLAYER.PAS:calc_order_jump';
3682   result := 0;
3683   temp := 0;
3684
3685   Repeat
3686     If (songdata.pattern_order[current_order] > $7f) then
3687       current_order := songdata.pattern_order[current_order]-$80;
3688     Inc(temp);
3689   until (temp > $7f) or (songdata.pattern_order[current_order] < $80);
3690
3691   If (temp > $7f) then begin stop_playing; result := -1; end;
3692   calc_order_jump := result;
3693 end;
3694
3695 procedure update_song_position;
3696
3697 var
3698   temp: Byte;
3699
3700 begin
3701   _debug_str_ := 'A2PLAYER.PAS:update_song_position';
3702   If (current_line < PRED(songdata.patt_len)) and NOT pattern_break then Inc(current_line)
3703   else begin
3704          If NOT (pattern_break and (next_line AND $0f0 = pattern_loop_flag)) and
3705                 (current_order < $7f) then
3706            begin
3707              FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
3708              FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
3709              Inc(current_order);
3710            end;
3711
3712          If pattern_break and (next_line AND $0f0 = pattern_loop_flag) then
3713            begin
3714              temp := next_line-pattern_loop_flag;
3715              next_line := loopbck_table[temp];
3716              If (loop_table[temp][current_line] <> 0) then
3717                Dec(loop_table[temp][current_line]);
3718            end
3719          else If pattern_break and (next_line AND $0f0 = pattern_break_flag) then
3720                 begin
3721                   current_order := event_table[next_line-pattern_break_flag].effect;
3722                   pattern_break := FALSE;
3723                 end
3724               else If (current_order > $7f) then
3725                      current_order := 0;
3726
3727          If (songdata.pattern_order[current_order] > $7f) then
3728            If (calc_order_jump = -1) then EXIT;
3729
3730          current_pattern := songdata.pattern_order[current_order];
3731          If NOT pattern_break then current_line := 0
3732          else begin
3733                 pattern_break := FALSE;
3734                 current_line := next_line;
3735               end;
3736        end;
3737
3738   For temp := 1 to songdata.nm_tracks do
3739     begin
3740       glfsld_table[temp] := 0;
3741       glfsld_table2[temp] := 0;
3742     end;
3743
3744   If (current_line = 0) and
3745      (current_order = calc_following_order(0)) and speed_update then
3746     begin
3747       tempo := songdata.tempo;
3748       speed := songdata.speed;
3749       update_timer(tempo);
3750     end;
3751 end;
3752
3753 procedure poll_proc;
3754
3755 var
3756   temp: Byte;
3757
3758 var
3759   _debug_str_bak_: String;
3760
3761 begin
3762   _debug_str_bak_ := _debug_str_;
3763   _debug_str_ := 'A2PLAYER.PAS:_poll_proc';
3764
3765   If (NOT pattern_delay and (ticks-tick0+1 >= speed)) or
3766      fast_forward then
3767     begin
3768       If (songdata.pattern_order[current_order] > $7f) then
3769         If (calc_order_jump = -1) then EXIT;
3770
3771       current_pattern := songdata.pattern_order[current_order];
3772       play_line;
3773       If NOT fast_forward then update_effects
3774       else For temp := 1 to speed do
3775              begin
3776                update_effects;
3777                If (temp MOD 4 = temp) then
3778                  update_extra_fine_effects;
3779                Inc(ticks);
3780              end;
3781
3782       If fast_forward or NOT pattern_delay then
3783         update_song_position;
3784
3785       tick0 := ticks;
3786       If fast_forward then
3787         If NOT pattern_delay then synchronize_song_timer;
3788
3789       If fast_forward and pattern_delay then
3790         begin
3791           tickD := 0;
3792           pattern_delay := FALSE;
3793         end;
3794
3795       If fast_forward then fast_forward := FALSE;
3796     end
3797   else
3798     begin
3799       update_effects;
3800       Inc(ticks);
3801       If pattern_delay and (tickD > 1) then Dec(tickD)
3802       else begin
3803              If pattern_delay then
3804                begin
3805                  tick0 := ticks;
3806                  update_song_position;
3807                end;
3808              pattern_delay := FALSE;
3809            end;
3810     end;
3811
3812   Inc(tickXF);
3813   If (tickXF MOD 4 = 0) then
3814     begin
3815       update_extra_fine_effects;
3816       Dec(tickXF,4);
3817     end;
3818   _debug_str_ := _debug_str_bak_;
3819 end;
3820
3821 procedure macro_poll_proc;
3822
3823 const
3824   IDLE = $0fff;
3825   FINISHED = $0ffff;
3826
3827 var
3828   chan: Byte;
3829   finished_flag: Word;
3830
3831 var
3832   _debug_str_bak_: String;
3833
3834 function _ins_adsr_data_empty(ins: Byte): Boolean;
3835 begin
3836   _ins_adsr_data_empty :=
3837     (ins_parameter(ins,5) SHR 4 = 0) and
3838     (ins_parameter(ins,4) SHR 4 = 0) and
3839     (ins_parameter(ins,5) AND $0f = 0) and
3840     (ins_parameter(ins,4) AND $0f = 0) and
3841     (ins_parameter(ins,7) SHR 4 = 0) and
3842     (ins_parameter(ins,6) SHR 4 = 0) and
3843     (ins_parameter(ins,7) AND $0f = 0) and
3844     (ins_parameter(ins,6) AND $0f = 0);
3845 end;
3846
3847 begin
3848   _debug_str_bak_ := _debug_str_;
3849   _debug_str_ := 'ADT2UNIT.PAS:macro_poll_proc';
3850   For chan := 1 to songdata.nm_tracks do
3851     begin
3852       If NOT keyoff_loop[chan] then finished_flag := FINISHED
3853       else finished_flag := IDLE;
3854
3855       With macro_table[chan] do
3856         begin
3857           With songdata.instr_macros[fmreg_table] do
3858             If (fmreg_table <> 0) and (speed <> 0) then
3859               If (fmreg_duration > 1) then Dec(fmreg_duration)
3860               else begin
3861                      fmreg_count := 1;
3862                      If (fmreg_pos <= length) then
3863                        If (loop_begin <> 0) and (loop_length <> 0) then
3864                          If (fmreg_pos = loop_begin+PRED(loop_length)) then
3865                            fmreg_pos := loop_begin
3866                          else If (fmreg_pos < length) then Inc(fmreg_pos)
3867                               else fmreg_pos := finished_flag
3868                        else If (fmreg_pos < length) then Inc(fmreg_pos)
3869                             else fmreg_pos := finished_flag
3870                      else fmreg_pos := finished_flag;
3871
3872                      If (freq_table[chan] OR $2000 = freq_table[chan]) and
3873                         (keyoff_pos <> 0) and
3874                         (fmreg_pos >= keyoff_pos) then
3875                        fmreg_pos := IDLE
3876                      else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
3877                              (fmreg_pos <> 0) and (keyoff_pos <> 0) and
3878                              ((fmreg_pos < keyoff_pos) or (fmreg_pos = IDLE)) then
3879                             fmreg_pos := keyoff_pos;
3880
3881                      If (fmreg_pos <> 0) and
3882                         (fmreg_pos <> IDLE) and (fmreg_pos <> finished_flag) then
3883                        begin
3884                          fmreg_duration := data[fmreg_pos].duration;
3885                          If (fmreg_duration <> 0) then
3886                            With data[fmreg_pos] do
3887                              begin
3888                                // force KEY-ON with missing ADSR instrument data
3889                                force_macro_keyon := FALSE;
3890                                If (fmreg_pos = 1) then
3891                                  If _ins_adsr_data_empty(voice_table[chan]) and
3892                                     NOT (songdata.dis_fmreg_col[fmreg_table][0] and
3893                                          songdata.dis_fmreg_col[fmreg_table][1] and
3894                                          songdata.dis_fmreg_col[fmreg_table][2] and
3895                                          songdata.dis_fmreg_col[fmreg_table][3] and
3896                                          songdata.dis_fmreg_col[fmreg_table][12] and
3897                                          songdata.dis_fmreg_col[fmreg_table][13] and
3898                                          songdata.dis_fmreg_col[fmreg_table][14] and
3899                                          songdata.dis_fmreg_col[fmreg_table][15]) then
3900                                    force_macro_keyon := TRUE;
3901
3902                                If NOT songdata.dis_fmreg_col[fmreg_table][0] then
3903                                  fmpar_table[chan].adsrw_mod.attck := fm_data.ATTCK_DEC_modulator SHR 4;
3904
3905                                If NOT songdata.dis_fmreg_col[fmreg_table][1] then
3906                                  fmpar_table[chan].adsrw_mod.dec := fm_data.ATTCK_DEC_modulator AND $0f;
3907
3908                                If NOT songdata.dis_fmreg_col[fmreg_table][2] then
3909                                  fmpar_table[chan].adsrw_mod.sustn := fm_data.SUSTN_REL_modulator SHR 4;
3910
3911                                If NOT songdata.dis_fmreg_col[fmreg_table][3] then
3912                                  fmpar_table[chan].adsrw_mod.rel := fm_data.SUSTN_REL_modulator AND $0f;
3913
3914                                If NOT songdata.dis_fmreg_col[fmreg_table][4] then
3915                                  fmpar_table[chan].adsrw_mod.wform := fm_data.WAVEFORM_modulator AND $07;
3916
3917                                If NOT songdata.dis_fmreg_col[fmreg_table][6] then
3918                                  fmpar_table[chan].kslM := fm_data.KSL_VOLUM_modulator SHR 6;
3919
3920                                If NOT songdata.dis_fmreg_col[fmreg_table][7] then
3921                                  fmpar_table[chan].multipM := fm_data.AM_VIB_EG_modulator AND $0f;
3922
3923                                If NOT songdata.dis_fmreg_col[fmreg_table][8] then
3924                                  fmpar_table[chan].tremM := fm_data.AM_VIB_EG_modulator SHR 7;
3925
3926                                If NOT songdata.dis_fmreg_col[fmreg_table][9] then
3927                                  fmpar_table[chan].vibrM := fm_data.AM_VIB_EG_modulator SHR 6 AND 1;
3928
3929                                If NOT songdata.dis_fmreg_col[fmreg_table][10] then
3930                                  fmpar_table[chan].ksrM := fm_data.AM_VIB_EG_modulator SHR 4 AND 1;
3931
3932                                If NOT songdata.dis_fmreg_col[fmreg_table][11] then
3933                                  fmpar_table[chan].sustM := fm_data.AM_VIB_EG_modulator SHR 5 AND 1;
3934
3935                                If NOT songdata.dis_fmreg_col[fmreg_table][12] then
3936                                  fmpar_table[chan].adsrw_car.attck := fm_data.ATTCK_DEC_carrier SHR 4;
3937
3938                                If NOT songdata.dis_fmreg_col[fmreg_table][13] then
3939                                  fmpar_table[chan].adsrw_car.dec := fm_data.ATTCK_DEC_carrier AND $0f;
3940
3941                                If NOT songdata.dis_fmreg_col[fmreg_table][14] then
3942                                  fmpar_table[chan].adsrw_car.sustn := fm_data.SUSTN_REL_carrier SHR 4;
3943
3944                                If NOT songdata.dis_fmreg_col[fmreg_table][15] then
3945                                  fmpar_table[chan].adsrw_car.rel := fm_data.SUSTN_REL_carrier AND $0f;
3946
3947                                If NOT songdata.dis_fmreg_col[fmreg_table][16] then
3948                                  fmpar_table[chan].adsrw_car.wform := fm_data.WAVEFORM_carrier AND $07;
3949
3950                                If NOT songdata.dis_fmreg_col[fmreg_table][18] then
3951                                  fmpar_table[chan].kslC := fm_data.KSL_VOLUM_carrier SHR 6;
3952
3953                                If NOT songdata.dis_fmreg_col[fmreg_table][19] then
3954                                  fmpar_table[chan].multipC := fm_data.AM_VIB_EG_carrier AND $0f;
3955
3956                                If NOT songdata.dis_fmreg_col[fmreg_table][20] then
3957                                  fmpar_table[chan].tremC := fm_data.AM_VIB_EG_carrier SHR 7;
3958
3959                                If NOT songdata.dis_fmreg_col[fmreg_table][21] then
3960                                  fmpar_table[chan].vibrC := fm_data.AM_VIB_EG_carrier SHR 6 AND 1;
3961
3962                                If NOT songdata.dis_fmreg_col[fmreg_table][22] then
3963                                  fmpar_table[chan].ksrC := fm_data.AM_VIB_EG_carrier SHR 4 AND 1;
3964
3965                                If NOT songdata.dis_fmreg_col[fmreg_table][23] then
3966                                  fmpar_table[chan].sustC := fm_data.AM_VIB_EG_carrier SHR 5 AND 1;
3967
3968                                If NOT songdata.dis_fmreg_col[fmreg_table][24] then
3969                                  fmpar_table[chan].connect := fm_data.FEEDBACK_FM AND 1;
3970
3971                                If NOT songdata.dis_fmreg_col[fmreg_table][25] then
3972                                  fmpar_table[chan].feedb := fm_data.FEEDBACK_FM SHR 1 AND 7;
3973
3974                                If NOT songdata.dis_fmreg_col[fmreg_table][27] then
3975                                  If NOT pan_lock[chan] then
3976                                    panning_table[chan] := panning;
3977
3978                                If NOT songdata.dis_fmreg_col[fmreg_table][5] then
3979                                  set_ins_volume(63-fm_data.KSL_VOLUM_modulator AND $3f,
3980                                                 BYTE_NULL,chan);
3981
3982                                If NOT songdata.dis_fmreg_col[fmreg_table][17] then
3983                                  set_ins_volume(BYTE_NULL,
3984                                                 63-fm_data.KSL_VOLUM_carrier AND $3f,chan);
3985
3986                                update_modulator_adsrw(chan);
3987                                update_carrier_adsrw(chan);
3988                                update_fmpar(chan);
3989
3990                                If force_macro_keyon or
3991                                   NOT (fm_data.FEEDBACK_FM OR $80 <> fm_data.FEEDBACK_FM) then
3992                                  output_note(event_table[chan].note,
3993                                              event_table[chan].instr_def,chan,FALSE);
3994
3995                                If NOT songdata.dis_fmreg_col[fmreg_table][26] then
3996                                  If (freq_slide > 0) then
3997                                    portamento_up(chan,freq_slide,nFreq(12*8+1))
3998                                  else If (freq_slide < 0) then
3999                                         portamento_down(chan,Abs(freq_slide),nFreq(0));
4000                              end;
4001                        end;
4002                    end;
4003
4004           With songdata.macro_table[arpg_table].arpeggio do
4005             If (arpg_table <> 0) and (speed <> 0) then
4006               If (arpg_count = speed) then
4007                 begin
4008                   arpg_count := 1;
4009                   If (arpg_pos <= length) then
4010                     If (loop_begin <> 0) and (loop_length <> 0) then
4011                       If (arpg_pos = loop_begin+PRED(loop_length)) then
4012                         arpg_pos := loop_begin
4013                       else If (arpg_pos < length) then Inc(arpg_pos)
4014                            else arpg_pos := finished_flag
4015                     else If (arpg_pos < length) then Inc(arpg_pos)
4016                          else arpg_pos := finished_flag
4017                   else arpg_pos := finished_flag;
4018
4019                   If (freq_table[chan] OR $2000 = freq_table[chan]) and
4020                      (keyoff_pos <> 0) and
4021                      (arpg_pos >= keyoff_pos) then
4022                     arpg_pos := IDLE
4023                   else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
4024                           (keyoff_pos <> 0) and (keyoff_pos <> 0) and
4025                           ((arpg_pos < keyoff_pos) or (arpg_pos = IDLE)) then
4026                          arpg_pos := keyoff_pos;
4027
4028                   If (arpg_pos <> 0) and
4029                      (arpg_pos <> IDLE) and (arpg_pos <> finished_flag) then
4030                     Case data[arpg_pos] of
4031                       0: change_frequency(chan,
4032                            nFreq(arpg_note-1)+
4033                            SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
4034
4035                       1..96:
4036                         change_frequency(chan,
4037                           nFreq(max(arpg_note+data[arpg_pos],97)-1)+
4038                           SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
4039
4040                       $80..$80+12*8+1:
4041                         change_frequency(chan,nFreq(data[arpg_pos]-$80-1)+
4042                           SHORTINT(ins_parameter(event_table[chan].instr_def,12)));
4043                     end;
4044                 end
4045               else Inc(arpg_count);
4046
4047           With songdata.macro_table[vib_table].vibrato do
4048             If NOT vib_paused and
4049                (vib_table <> 0) and (speed <> 0) then
4050               If (vib_count = speed) then
4051                 If (vib_delay <> 0) then Dec(vib_delay)
4052                 else begin
4053                        vib_count := 1;
4054                        If (vib_pos <= length) then
4055                          If (loop_begin <> 0) and (loop_length <> 0) then
4056                            If (vib_pos = loop_begin+PRED(loop_length)) then
4057                              vib_pos := loop_begin
4058                            else If (vib_pos < length) then Inc(vib_pos)
4059                                 else vib_pos := finished_flag
4060                          else If (vib_pos < length) then Inc(vib_pos)
4061                               else vib_pos := finished_flag
4062                        else vib_pos := finished_flag;
4063
4064                        If (freq_table[chan] OR $2000 = freq_table[chan]) and
4065                           (keyoff_pos <> 0) and
4066                           (vib_pos >= keyoff_pos) then
4067                          vib_pos := IDLE
4068                        else If (freq_table[chan] OR $2000 <> freq_table[chan]) and
4069                                (vib_pos <> 0) and (keyoff_pos <> 0) and
4070                                ((vib_pos < keyoff_pos) or (vib_pos = IDLE)) then
4071                               vib_pos := keyoff_pos;
4072
4073                        If (vib_pos <> 0) and
4074                           (vib_pos <> IDLE) and (vib_pos <> finished_flag) then
4075                          If (data[vib_pos] > 0) then
4076                            macro_vibrato__porta_up(chan,data[vib_pos])
4077                          else If (data[vib_pos] < 0) then
4078                                 macro_vibrato__porta_down(chan,Abs(data[vib_pos]))
4079                               else change_freq(chan,vib_freq);
4080                      end
4081               else Inc(vib_count);
4082         end;
4083     end;
4084   _debug_str_ := _debug_str_bak_;
4085 end;
4086
4087 var
4088   ticklooper,
4089   macro_ticklooper: Longint;
4090
4091 procedure timer_poll_proc;
4092
4093 var
4094   _debug_str_bak_: String;
4095
4096 begin
4097   _debug_str_bak_ := _debug_str_;
4098   _debug_str_ := 'A2PLAYER.PAS:timer_poll_proc';
4099
4100   If (timer_det < IRQ_freq DIV 200) then Inc(timer_det)
4101   else begin
4102          timer_det := 1;
4103          Inc(_delay_counter);
4104        end;
4105
4106   If (current_order = 0) and (current_line = 0) and
4107      (tick0 = ticks) then
4108     begin
4109       song_timer := 0;
4110       timer_temp := 0;
4111       song_timer_tenths := 0;
4112     end;
4113
4114   If (play_status = isPlaying) then
4115     begin
4116       song_timer_tenths := Trunc(100/IRQ_freq*timer_temp);
4117       If (song_timer_tenths = 100) then song_timer_tenths := 0;
4118       If (timer_temp < IRQ_freq) then Inc(timer_temp)
4119       else begin
4120              Inc(song_timer);
4121              timer_temp := 1;
4122            end;
4123     end;
4124
4125   If (song_timer > 3600-1) then
4126     begin
4127       song_timer := 0;
4128       timer_temp := 0;
4129       song_timer_tenths := 0;
4130     end;
4131
4132   If (ticklooper = 0) and NOT replay_forbidden then
4133     poll_proc;
4134
4135   If (macro_ticklooper = 0) then
4136     macro_poll_proc;
4137
4138   Inc(ticklooper);
4139   If (ticklooper >= IRQ_freq DIV tempo) or fast_forward then
4140     ticklooper := 0;
4141
4142   Inc(macro_ticklooper);
4143   If (macro_ticklooper >= IRQ_freq DIV (tempo*_macro_speedup)) then
4144     macro_ticklooper := 0;
4145
4146   _debug_str_ := _debug_str_bak_;
4147 end;
4148
4149 procedure newtimer;
4150 begin
4151   _debug_str_ := 'A2PLAYER.PAS:newtimer';
4152   If irq_mode then timer_poll_proc;
4153   If (@external_irq_hook <> NIL) then external_irq_hook;
4154 end;
4155
4156 procedure init_irq;
4157 begin
4158   _debug_str_ := 'A2PLAYER.PAS:init_irq';
4159   If irq_initialized then EXIT;
4160   irq_initialized := TRUE;
4161   TimerInstallHandler(@newtimer);
4162   TimerSetup(50);
4163 end;
4164
4165 procedure done_irq;
4166 begin
4167   _debug_str_ := 'A2PLAYER.PAS:done_irq';
4168   If NOT irq_initialized then EXIT;
4169   irq_initialized := FALSE;
4170   irq_mode := TRUE;
4171   TimerDone;
4172   TimerRemoveHandler;
4173   irq_mode := FALSE;
4174 end;
4175
4176 function calc_pattern_pos(pattern: Byte): Byte;
4177
4178 var
4179   index: Integer;
4180   jump_count,pattern_pos: Byte;
4181
4182 begin
4183   _debug_str_ := 'A2PLAYER.PAS:calc_pattern_pos';
4184   pattern_pos := BYTE_NULL;
4185   jump_count := 0;
4186   index := calc_following_order(0);
4187   While (index <> -1) and (jump_count < $7f) do
4188     If (songdata.pattern_order[index] <> pattern) then
4189       If NOT (index < $7f) then BREAK
4190       else begin
4191              Inc(index);
4192              index := calc_following_order(index);
4193              Inc(jump_count);
4194            end
4195     else begin
4196            pattern_pos := index;
4197            BREAK;
4198          end;
4199   calc_pattern_pos := pattern_pos;
4200 end;
4201
4202 procedure init_buffers;
4203
4204 var
4205   temp: Byte;
4206
4207 begin
4208   _debug_str_ := 'A2PLAYER.PAS:init_buffers';
4209   FillChar(fmpar_table,SizeOf(fmpar_table),0);
4210   FillChar(pan_lock,SizeOf(pan_lock),BYTE(panlock));
4211   FillChar(volume_table,SizeOf(volume_table),0);
4212   FillChar(vscale_table,SizeOf(vscale_table),0);
4213   FillChar(modulator_vol,SizeOf(modulator_vol),0);
4214   FillChar(carrier_vol,SizeOf(carrier_vol),0);
4215   FillChar(event_table,SizeOf(event_table),0);
4216   FillChar(freq_table,SizeOf(freq_table),0);
4217   FillChar(effect_table,SizeOf(effect_table),0);
4218   FillChar(effect_table2,SizeOf(effect_table2),0);
4219   FillChar(fslide_table,SizeOf(fslide_table),0);
4220   FillChar(fslide_table2,SizeOf(fslide_table2),0);
4221   FillChar(glfsld_table,SizeOf(glfsld_table),0);
4222   FillChar(glfsld_table2,SizeOf(glfsld_table2),0);
4223   FillChar(porta_table,SizeOf(porta_table),0);
4224   FillChar(porta_table2,SizeOf(porta_table2),0);
4225   FillChar(arpgg_table,SizeOf(arpgg_table),0);
4226   FillChar(arpgg_table2,SizeOf(arpgg_table2),0);
4227   FillChar(vibr_table,SizeOf(vibr_table),0);
4228   FillChar(vibr_table2,SizeOf(vibr_table2),0);
4229   FillChar(trem_table,SizeOf(trem_table),0);
4230   FillChar(trem_table2,SizeOf(trem_table2),0);
4231   FillChar(retrig_table,SizeOf(retrig_table),0);
4232   FillChar(retrig_table2,SizeOf(retrig_table2),0);
4233   FillChar(tremor_table,SizeOf(tremor_table),0);
4234   FillChar(tremor_table2,SizeOf(tremor_table2),0);
4235   FillChar(panning_table,SizeOf(panning_table),0);
4236   FillChar(last_effect,SizeOf(last_effect),0);
4237   FillChar(last_effect2,SizeOf(last_effect2),0);
4238   FillChar(voice_table,SizeOf(voice_table),0);
4239   FillChar(event_new,SizeOf(event_new),0);
4240   FillChar(notedel_table,SizeOf(notedel_table),BYTE_NULL);
4241   FillChar(notecut_table,SizeOf(notecut_table),BYTE_NULL);
4242   FillChar(ftune_table,SizeOf(ftune_table),0);
4243   FillChar(loopbck_table,SizeOf(loopbck_table),BYTE_NULL);
4244   FillChar(loop_table,SizeOf(loop_table),BYTE_NULL);
4245   FillChar(reset_chan,SizeOf(reset_chan),BYTE(FALSE));
4246   FillChar(keyoff_loop,SizeOf(keyoff_loop),BYTE(FALSE));
4247   FillChar(macro_table,SizeOf(macro_table),0);
4248
4249   If NOT lockvol then FillChar(volume_lock,SizeOf(volume_lock),0)
4250   else For temp := 1 to 20 do volume_lock[temp] := BOOLEAN(songdata.lock_flags[temp] SHR 4 AND 1);
4251
4252   If NOT panlock then FillChar(panning_table,SizeOf(panning_table),0)
4253   else For temp := 1 to 20 do panning_table[temp] := songdata.lock_flags[temp] AND 3;
4254
4255   If NOT lockVP then FillChar(peak_lock,SizeOf(peak_lock),0)
4256   else For temp := 1 to 20 do peak_lock[temp] := BOOLEAN(songdata.lock_flags[temp] SHR 5 AND 1);
4257
4258   For temp := 1 to 20 do
4259     volslide_type[temp] := songdata.lock_flags[temp] SHR 2 AND 3;
4260 end;
4261
4262 procedure init_player;
4263
4264 var
4265   temp: Byte;
4266
4267 begin
4268   _debug_str_ := 'A2PLAYER.PAS:init_player';
4269   opl2out($01,0);
4270
4271   For temp := 1 to 18 do opl2out($0b0+_chan_n[temp],0);
4272   For temp := $080 to $08d do opl2out(temp,BYTE_NULL);
4273   For temp := $090 to $095 do opl2out(temp,BYTE_NULL);
4274
4275   speed_update    := BOOLEAN(songdata.common_flag AND 1);
4276   lockvol         := BOOLEAN(songdata.common_flag SHR 1 AND 1);
4277   lockVP          := BOOLEAN(songdata.common_flag SHR 2 AND 1);
4278   tremolo_depth   :=         songdata.common_flag SHR 3 AND 1;
4279   vibrato_depth   :=         songdata.common_flag SHR 4 AND 1;
4280   panlock         := BOOLEAN(songdata.common_flag SHR 5 AND 1);
4281   percussion_mode := BOOLEAN(songdata.common_flag SHR 6 AND 1);
4282   volume_scaling  := BOOLEAN(songdata.common_flag SHR 7 AND 1);
4283
4284   current_tremolo_depth := tremolo_depth;
4285   current_vibrato_depth := vibrato_depth;
4286   init_buffers;
4287
4288   If NOT percussion_mode then
4289     begin
4290       _chan_n := _chmm_n;
4291       _chan_m := _chmm_m;
4292       _chan_c := _chmm_c;
4293     end
4294   else
4295     begin
4296       _chan_n := _chpm_n;
4297       _chan_m := _chpm_m;
4298       _chan_c := _chpm_c;
4299     end;
4300
4301   misc_register := tremolo_depth SHL 7+
4302                    vibrato_depth SHL 6+
4303                    BYTE(percussion_mode) SHL 5;
4304
4305   opl2out($01,$20);
4306   opl2out($08,$40);
4307   opl3exp($0105);
4308   opl3exp($04+songdata.flag_4op SHL 8);
4309
4310   key_off(17);
4311   key_off(18);
4312   opl2out(_instr[11],misc_register);
4313
4314   current_tremolo_depth := tremolo_depth;
4315   current_vibrato_depth := vibrato_depth;
4316   global_volume := 63;
4317   vibtrem_speed_factor := def_vibtrem_speed_factor;
4318   vibtrem_table_size := def_vibtrem_table_size;
4319   Move(def_vibtrem_table,vibtrem_table,SizeOf(vibtrem_table));
4320
4321   For temp := 1 to 20 do
4322     begin
4323       arpgg_table[temp].state := 1;
4324       voice_table[temp] := temp;
4325     end;
4326 end;
4327
4328 procedure stop_playing;
4329
4330 var
4331   temp: Byte;
4332
4333 begin
4334   _debug_str_ := 'A2PLAYER.PAS:stop_playing';
4335   irq_mode := FALSE;
4336   play_status := isStopped;
4337   global_volume := 63;
4338   current_tremolo_depth := tremolo_depth;
4339   current_vibrato_depth := vibrato_depth;
4340   pattern_break := FALSE;
4341   current_order := 0;
4342   current_pattern := 0;
4343   current_line := 0;
4344   song_timer := 0;
4345   timer_temp := 0;
4346   song_timer_tenths := 0;
4347
4348   For temp := 1 to 20 do release_sustaining_sound(temp);
4349   opl2out(_instr[11],0);
4350   opl3exp($0004);
4351   opl3exp($0005);
4352   init_buffers;
4353
4354   speed := songdata.speed;
4355   update_timer(songdata.tempo);
4356 end;
4357
4358 procedure init_old_songdata;
4359 begin
4360   _debug_str_ := 'A2PLAYER.PAS:init_old_songdata';
4361   FillChar(old_songdata,SizeOf(old_songdata),0);
4362   FillChar(old_songdata.pattern_order,SizeOf(old_songdata.pattern_order),$080);
4363   FillChar(old_songdata.instr_data,SizeOf(old_songdata.instr_data),0);
4364 end;
4365
4366 procedure init_songdata;
4367 begin
4368   _debug_str_ := 'A2PLAYER.PAS:init_songdata';
4369   If (play_status <> isStopped) then stop_playing
4370   else init_buffers;
4371
4372   FillChar(songdata,SizeOf(songdata),0);
4373   FillChar(songdata.pattern_order,SizeOf(songdata.pattern_order),$080);
4374   FillChar(pattdata^,PATTERN_SIZE*max_patterns,0);
4375
4376   songdata.patt_len := 64;
4377   songdata.nm_tracks := 9;
4378   songdata.tempo := tempo;
4379   songdata.speed := speed;
4380   songdata.macro_speedup := 1;
4381   speed_update := FALSE;
4382   lockvol := FALSE;
4383   panlock := FALSE;
4384   lockVP  := FALSE;
4385   tremolo_depth := 0;
4386   vibrato_depth := 0;
4387   volume_scaling := FALSE;
4388
4389   If (songdata.nm_tracks <= 18) then
4390     begin
4391       percussion_mode := FALSE;
4392       _chan_n := _chmm_n;
4393       _chan_m := _chmm_m;
4394       _chan_c := _chmm_c;
4395     end
4396   else
4397     begin
4398       percussion_mode := TRUE;
4399       _chan_n := _chpm_n;
4400       _chan_m := _chpm_m;
4401       _chan_c := _chpm_c;
4402     end;
4403 end;
4404
4405 procedure start_playing;
4406 begin
4407   _debug_str_ := 'A2PLAYER.PAS:start_playing';
4408   stop_playing;
4409   If (error_code <> 0) then EXIT
4410   else init_player;
4411
4412   current_order := 0;
4413   If (songdata.pattern_order[current_order] > $7f) then
4414     If (calc_order_jump = -1) then EXIT;
4415
4416   current_pattern := songdata.pattern_order[current_order];
4417   current_line := 0;
4418   pattern_break := FALSE;
4419   pattern_delay := FALSE;
4420   tickXF := 0;
4421   ticks := 0;
4422   tick0 := 0;
4423   next_line := 0;
4424   song_timer := 0;
4425   timer_temp := 0;
4426   song_timer_tenths := 0;
4427   irq_mode := TRUE;
4428   replay_forbidden := FALSE;
4429   play_status := isPlaying;
4430   time_playing := 0;
4431   ticklooper := 0;
4432   macro_ticklooper := 0;
4433   speed := songdata.speed;
4434   macro_speedup := songdata.macro_speedup;
4435   update_timer(songdata.tempo);
4436 end;
4437
4438 procedure get_chunk(pattern,line,channel: Byte;
4439                     var chunk: tADTRACK2_EVENT); assembler;
4440 asm
4441         mov     esi,dword ptr [pattdata]
4442         mov     edi,[chunk]
4443         mov     al,pattern
4444         inc     al
4445         cmp     al,max_patterns
4446         jbe     @@1
4447         mov     ecx,CHUNK_SIZE
4448         xor     al,al
4449         rep     stosb
4450         jmp     @@2
4451 @@1:    xor     eax,eax
4452         mov     al,line
4453         mov     ebx,CHUNK_SIZE
4454         mul     ebx
4455         mov     ecx,eax
4456         xor     eax,eax
4457         mov     al,channel
4458         dec     eax
4459         mov     ebx,256*CHUNK_SIZE
4460         mul     ebx
4461         add     ecx,eax
4462         xor     eax,eax
4463         mov     al,pattern
4464         mov     ebx,8
4465         div     ebx
4466         push    eax
4467         mov     eax,edx
4468         mov     ebx,20*256*CHUNK_SIZE
4469         mul     ebx
4470         add     ecx,eax
4471         pop     eax
4472         mov     ebx,8*20*256*CHUNK_SIZE
4473         mul     ebx
4474         add     ecx,eax
4475         add     esi,ecx
4476         mov     ecx,CHUNK_SIZE
4477         rep     movsb
4478 @@2:
4479 end;
4480
4481 procedure put_chunk(pattern,line,channel: Byte;
4482                     chunk: tADTRACK2_EVENT); assembler;
4483 asm
4484         mov     esi,[chunk]
4485         mov     edi,dword ptr [pattdata]
4486         mov     al,pattern
4487         inc     al
4488         cmp     al,max_patterns
4489         jbe     @@1
4490         mov     limit_exceeded,TRUE
4491         jmp     @@2
4492 @@1:    xor     eax,eax
4493         mov     al,line
4494         mov     ebx,CHUNK_SIZE
4495         mul     ebx
4496         mov     ecx,eax
4497         xor     eax,eax
4498         mov     al,channel
4499         dec     eax
4500         mov     ebx,256*CHUNK_SIZE
4501         mul     ebx
4502         add     ecx,eax
4503         xor     eax,eax
4504         mov     al,pattern
4505         mov     ebx,8
4506         div     ebx
4507         push    eax
4508         mov     eax,edx
4509         mov     ebx,20*256*CHUNK_SIZE
4510         mul     ebx
4511         add     ecx,eax
4512         pop     eax
4513         mov     ebx,8*20*256*CHUNK_SIZE
4514         mul     ebx
4515         add     ecx,eax
4516         add     edi,ecx
4517         mov     ecx,CHUNK_SIZE
4518         rep     movsb
4519 @@2:
4520 end;
4521
4522 procedure count_order(var entries: Byte);
4523
4524 var
4525   index,
4526   index2: Byte;
4527
4528 begin
4529   _debug_str_ := 'A2PLAYER.PAS:count_order';
4530   index := 0;
4531   index2 := 0;
4532
4533   Repeat
4534     If (songdata.pattern_order[index] <> $80) then
4535       begin
4536         If (songdata.pattern_order[index] > $80) then
4537           If (songdata.pattern_order[index]-$80 <> index2) then
4538             begin
4539               index := songdata.pattern_order[index]-$80;
4540               index2 := index;
4541             end
4542           else BREAK;
4543       end
4544     else BREAK;
4545     If (index < $80) then Inc(index);
4546   until (index > $7f);
4547
4548   entries := index;
4549 end;
4550
4551 var
4552   old_exit_proc: Pointer;
4553   temp: Byte;
4554
4555 procedure new_exit_proc;
4556 begin
4557   _debug_str_ := 'A2PLAYER.PAS:new_exit_proc';
4558   stop_playing;
4559   done_irq;
4560   FreeMem(pattdata,PATTERN_SIZE*max_patterns);
4561 end;
4562
4563 begin
4564   old_exit_proc := ExitProc;
4565   ExitProc := @new_exit_proc;
4566
4567   error_code := 0;
4568   temp := $80;
4569   Repeat
4570     If (MemAvail > PATTERN_SIZE*temp) then
4571       begin
4572         max_patterns := temp;
4573         BREAK;
4574       end
4575     else If (temp-$10 >= $10) then Dec(temp,$10)
4576          else begin
4577                 error_code := -2;
4578                 BREAK;
4579               end;
4580   until FALSE;
4581
4582   If (error_code <> -2) then
4583     GetMem(pattdata,PATTERN_SIZE*max_patterns);
4584
4585   FillChar(decay_bar,SizeOf(decay_bar),0);
4586   play_status := isStopped;
4587   init_songdata;
4588   init_irq;
4589   timer_det := 1;
4590 end.