pt3_commands=pt3_sld12+pt3_port3+pt3_dsmp4+pt3_dorn5+pt3_vib6+pt3_Esld9A+pt3_tempoB
pt3_shortay=pt3_msx+pt3_timex
	if pt3_msx
pt3_aysel=#a0
pt3_aydat=#a1
	else
pt3_aysel=#f5
pt3_aydat=#f6
	endif

	module pt3player
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;$                                                             $
;$     PRO TRACKER 3.X PLAYER v3x0B by Dr.Lion/RSM             $
;$                                                             $
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;Based on RC367 by Alone Coder;
;Last edit by Dr.Lion: 8.07.2004 (#06CE bytes)
;Last edit by Alone Coder: 27.05.2015 (#026F..#041D bytes)
;old stats:
;- maximum execution time: 8864 t-states (test song)
;- average execution time: 5440 t-states (test song)

	if pt3_vol
maxvol=#f0
	else
minvol=#f0
maxvol=minvol+#0f
	endif

        ;ORG  #C000              ;Адрес компиляции
Compile
	macro INITS
;------ Main entry points ------
        LD   HL,module          ;Адрес модуля
        JR   INIT
        JP   PLAY
        JP   STOP
;------ Install ------
INIT	DI 
        PUSH HL
        LD   BC,99
        ADD  HL,BC
        LD   A,(HL)
        INC  HL
        PUSH HL
        LD   HL,Tb_PT-24
        LD   C,24
Find_FT ADD  HL,BC
        DEC  A
        JP   P,Find_FT
        LD   IX,tab_frq
;------ Frequency Table Generator ------
        LD   (SP_SV+1),SP
        LD   SP,HL
        LD   C,12
MkFT_L0 POP  HL
        LD   DE,24
        LD   B,8
MkFT_L1 SRL  H
        RR   L
        LD   A,L
        ADC  A,D
        LD   (IX+0),A
        LD   A,H
        ADC  A,D
        LD   (IX+1),A
        ADD  IX,DE
        DJNZ MkFT_L1
        LD   DE,-8*24+2
        ADD  IX,DE
        DEC  C
        JR   NZ,MkFT_L0
SP_SV   LD   SP,0
;------ Continue install ------
        POP  HL
        LD   A,(HL)
        LD   (curtempo),A
        INC  HL
        INC  HL
        LD   A,(HL)
        INC  HL
        LD   E,(HL)
        INC  HL
        LD   D,(HL)
        INC  HL
        LD   (smpPP_addr),HL
        LD   C,64
        ADD  HL,BC
        LD   (ornPP_addr),HL
        LD   C,32
        ADD  HL,BC
        LD   (Psa_beg_addr),HL
        LD   C,A
        ADD  HL,BC
        LD   (Psa_loop_addr),HL
        POP  HL
        ADD  HL,DE
        LD   (Psa_chn_addr),HL
        LD   A,B ;0
        LD   (Am_vol),A
        LD   (Bm_vol),A
        LD   (Cm_vol),A
        INC  A
        LD   (A_qty),A
        LD   (B_qty),A
        LD   (C_qty),A
        LD   HL,ZERO_M
        LD   (Ao_adr),HL
        LD   (Bo_adr),HL
        LD   (Co_adr),HL
        LD   (As_adr),HL
        LD   (Bs_adr),HL
        LD   (Cs_adr),HL
        LD   (Ach_adr),HL
        SUB  1-maxvol ;a=#f0 or #0f
        LD   (Ag_vol),A
        LD   (Bg_vol),A
        LD   (Cg_vol),A
        SBC  A,A
        LD   (Avb_lok),A
        LD   (Cvb_lok),A
        LD   (Bvb_lok),A
STOP    LD   DE,#0E00
STOP0   DEC  D
	if pt3_shortay
        LD   BC,pt3_aysel
        OUT  (C),D
        LD   c,pt3_aydat
        OUT  (C),E
	else
        LD   BC,#FFFD
        OUT  (C),D
        LD   B,#BF
        OUT  (C),E
	endif
        JR   NZ,STOP0
        RET 
	endm

	macro SUBROUTINES
;------ Count ornament/sample address ------
ornPP   
	if pt3_init
ornPP_addr=$+1
	LD   HL,ZERO_M
	endif
        add a,32
	call smpPPmul2
         LD   (IY+do_adr),L          ;Xo_adr=HL
         LD   (IY+do_adr+1),H
	ret
smpPPmul2
        ADD  A,A
;smpPP
smpPP_addr=$+1
	LD   HL,ZERO_M
         LD   C,A
         XOR  A
         LD   B,A
         ADD  HL,BC ;TODO add a,l:ld l,a:xor a if module+105 address allows +94 without crossing a paragraph
	if pt3_init
        LD   C,(HL)
        INC  HL
        LD   B,(HL)
        LD   HL,(Compile+1)
        ADD  HL,BC
	else
        LD b,(HL)
        INC HL
        LD h,(HL)
	ld l,b
	endif
        RET ;A=0, Z needed for ornPP
;------ Set form and frequency of Envelope ------
EiPP    LD   (E_form),A
        EX   DE,HL
        LD   D,(HL)
        INC  HL
        LD   E,(HL)
        INC  HL
        EX   DE,HL
        LD   (Env_frq),HL
	 if pt3_Esld9A 
        XOR  A
        LD   L,A
        LD   H,A
        LD   (Esl_frq),HL
        JR   Eipp
;------ Special Effects COM.9XXX ------
Eef_sld LD   A,(DE)             ;sld_env
        INC  DE
        EX   DE,HL
        LD   E,(HL)
        INC  HL
        LD   D,(HL)
        INC  HL
        EX   DE,HL
        LD   (Esl_sds+1),HL     ;sds
        LD   (Esl_sts+1),A
Eipp    LD   (Esl_stp+1),A      ;stp
	 endif
        LD   A,%00010000
        RET 
	endm

	macro AYDATA
	 if pt3_jpplay
	jp PLAY
	 endif
frq_A   ;DW   0
	db 0
	dw PLAY
	db 0
frq_B=$-2   ;DW   0
frq_C   DW   0
Noise   DB   0
Mixer   DB   0
vol_A   DB   0
vol_B   DB   0
vol_C   DB   0
frq_E   DW   0
	 if !(pt3_vol&&pt3_jpplay) ;not here if vol&jpplay
E_form  DB   #80;0
	 endif
	endm

	if pt3_init
	INITS
	SUBROUTINES
	endif

	if pt3_vol
;------ #C100 volume table ------
        DISPLAY "Volume Table :",$
tab_vol
	AYDATA
	;dw 0
	ds tab_vol+16-$
	DB 0,0,0,0,0,0,0,0,01,01,01,01,01,01,01,01
	DB 0,0,0,0,1,1,1,1,01,01,01,01,02,02,02,02
	DB 0,0,0,1,1,1,1,1,02,02,02,02,02,03,03,03
	DB 0,0,1,1,1,1,2,2,02,02,03,03,03,03,04,04
	DB 0,0,1,1,1,2,2,2,03,03,03,04,04,04,05,05
	DB 0,0,1,1,2,2,2,3,03,04,04,04,05,05,06,06
	DB 0,0,1,1,2,2,3,3,04,04,05,05,06,06,07,07
	DB 0,1,1,2,2,3,3,4,04,05,05,06,06,07,07,08
	DB 0,1,1,2,2,3,4,4,05,05,06,07,07,08,08,09
	DB 0,1,1,2,3,3,4,5,05,06,07,07,08,09,09,10
	DB 0,1,1,2,3,4,4,5,06,07,07,08,09,10,10,11
	DB 0,1,2,2,3,4,5,6,06,07,08,09,10,10,11,12
	DB 0,1,2,3,3,4,5,6,07,08,09,10,10,11,12,13
	DB 0,1,2,3,4,5,6,7,07,08,09,10,11,12,13,14
	DB 0,1,2,3,4,5,6,7,08,09,10,11,12,13,14,15
	 if pt3_jpplay
E_form  DB   #80;0
	 endif
	endif
;------ #C200 note frequency table -------
	if !pt3_vol
	AYDATA
	endif

pt3_frqsz=pt3_frqmax+1-pt3_frqmin ;number of existing notes
true_tab_frq=$
virtual_tab_frq=$-(pt3_frqmin*2)
tab_frq=($&#ff00)+(virtual_tab_frq&#ff) ;keep H
        DISPLAY "true_tab_frq=",true_tab_frq
        DISPLAY "tab_frq=",tab_frq
	 if pt3_init
	if (!pt3_msx) && (!pt3_timex)
Test_AY 
	LD   DE,#FFBF
        LD   C,#FD
        LD   A,#02
        LD   B,D
        OUT  (C),A
        LD   B,E
        OUT  (C),E
        LD   B,D
        IN   A,(C)
        CP   E
        LD   HL,DC_StrA
        JR   NZ,AY_Exit
AY_Pres LD   A,#10
        OUT  (C),A
        IN   A,(C)
        CP   D
        LD   HL,AY_StrA
        JR   NZ,AY_Exit
        LD   HL,YM_StrA
AY_Exit JP   STOP
        DS   8
        DB   "Pro Tracker 3.x Player v3x0B"
        DB   " by Dr.Lion 2004, AlCo 2015 "
        DS   8
DC_StrA DB   "Disconnected",0
AY_StrA DB   "AY-3-8910",0
YM_StrA DB   "YM2149F",0
	endif
	 endif
        DS   true_tab_frq+(pt3_frqsz*2)-$
        DISPLAY "end of tab_frq=",$

	if pt3_commands
;------ Effect subroutines table ------
X_eff   DW   Xef_slT ;1xxx,2xxx - sld_tone
        DW   Xef_nsT ;3xxx      - port_note
        DW   Xef_dSm ;4.xx      - dsp_smp
        DW   Xef_dOr ;5.xx      - dsp_orn
        DW   Xef_vib ;6.xx      - vibrato
        DW   0;res
        DW   0;res
;ZERO_M  DW   0
        DW   Eef_sld ;9xxx,Axxx - sld_env
        DW   eff_tmp ;B.xx      - temp
	else
	if pt3_init
ZERO_M
	DW   0 ;not needed with auto_init
	endif
	endif

;------ All the variables of channel A ------
        DISPLAY "Ach_adr=",$
Ai_qty  DB   #01                ;-02 STEP COUNTER PRESET (2)
A_qty   DB   #01                ;-01 STEP COUNTER (2)
;-- this is cleared as a block
clblockstart
	if pt3_smpfix
As_Vsl  DB   #10                ;+11 VOLUME SLIDE ACC (4)
As_Nsl  DB   0                  ;+14 NOISE SLIDE ACC (3)
As_Esl  DB   0                  ;+15 ENVELOPMENT SLIDE ACC (3)
As_dtn  DW   0                  ;+16 SAMP FRQ DSP ACC (3 + 3)
	endif
As_dsp  DB   0                  ;+18 SAMPLE POSITION (4)
Ao_dsp  DB   0                  ;+19 ORNAMENT POSITION (6)
Asl_dsp DW   0                  ;+20 SLIDE DSP (4 + 4)
Asl_stp DB   0                  ;+22 SLIDE STEP (DELAY) (5)
clblocksize=$-clblockstart
;-- ~this
iybase
di_qty=Ai_qty-iybase
d_qty=A_qty-iybase
	if pt3_smpfix
ds_Vsl=As_Vsl-iybase
ds_Nsl=As_Nsl-iybase
ds_Esl=As_Esl-iybase
ds_dtn=As_dtn-iybase
	endif
ds_dsp=As_dsp-iybase
do_dsp=Ao_dsp-iybase
dsl_dsp=Asl_dsp-iybase
dsl_stp=Asl_stp-iybase

dch_adr=$-iybase
Ach_adr DW   ZERO_M             ;-04 POSITION ADR (2 + 2)
;--- this is loaded via stack
dfrq_Ad=$-iybase
Afrq_Ad DW   frq_A              ;+00 ADR IN MEM OF FRQ REG (0 + 0)
dvol_Ad=$-iybase
Avol_Ad DW   vol_A              ;+02 ADR IN MEM OF VOL REG (0 + 0)
ds_adr=$-iybase
As_adr  DW   ZERO_M             ;+04 SAMPLE ADR (1 + 1)
do_adr=$-iybase
Ao_adr  DW   ZERO_M             ;+06 ORNAMENT ADR (2 + 2)
dCh_IDN=$-iybase
ACh_IDN DB   4                  ;+08 CHANNEL ROLL FOR MIXER (0)
	if pt3_sld12||pt3_port3||pt3_vib6
dsl_plk=$-iybase
Asl_plk DB   Xsl_sts-Xsl_plk    ;+09 DSP FOR PORT ON/OFF (2) ;0 or Xsl_sts-Xsl_plk
	endif
;--- ~this
dvb_lok=$-iybase
Avb_lok DB   #FF                ;+10 SOUND LOCK(vol0 or VIBRATO) (6) ;loaded via stack if no slides
dg_vol=$-iybase
Ag_vol  DB maxvol;#F0                ;+12 GLOBAL VOLUME (2)
dm_vol=$-iybase
Am_vol  DB   0                  ;+13 ENVELOPE MASK (3)
ds_note=$-iybase
As_note DB   0                  ;+26 SAMPLE NOTE (7)
	if pt3_sld12||pt3_port3||pt3_vib6
dsl_tfr=$-iybase
Asl_tfr DW   0                  ;+23 SLIDE ADD DSP (3 + 3)
dsl_not=$-iybase
Asl_not DB   0                  ;+25 SLIDE TO NOTE (2)
dsl_sts=$-iybase
Asl_sts DB   0                  ;+27 SLIDE COUNTER PRESET (2)
	endif
	if pt3_vib6
dvb_stp=$-iybase
Avb_stp DB   0                  ;+28 VIBRATO COUNTER (6)
dvb_frq=$-iybase
Avb_frq DB   0                  ;+29 SOUND OFF DELAY (VIBRATO) (2)
dvb_sts=$-iybase
Avb_sts DB   0                  ;+30 VIBRATO COUNTER PRESET (2)
	endif
;------ All the variables of channel B ------
        DISPLAY "Bch_adr=",$
Bi_qty  DB   #01
B_qty   DB   #01
;-- this is cleared as a block
	if pt3_smpfix
Bs_Vsl  DB   #10
Bs_Nsl  DB   0
Bs_Esl  DB   0
Bs_dtn  DW   0
	endif
Bs_dsp  DB   0
Bo_dsp  DB   0
Bsl_dsp DW   0
Bsl_stp DB   0
;-- ~this
Bch_adr DW   ZERO_M
;--- this is loaded via stack
Bfrq_Ad DW   frq_B
Bvol_Ad DW   vol_B
Bs_adr  DW   ZERO_M
Bo_adr  DW   ZERO_M
BCh_IDN DB   3
	if pt3_sld12||pt3_port3||pt3_vib6
Bsl_plk DB   Xsl_sts-Xsl_plk
	endif
;--- ~this
Bvb_lok DB   #FF
Bg_vol  DB maxvol;#F0
Bm_vol  DB   0
Bs_note DB   0
	if pt3_sld12||pt3_port3||pt3_vib6
Bsl_tfr DW   0
Bsl_not DB   0
Bsl_sts DB   0
	endif
	if pt3_vib6
Bvb_stp DB   0
Bvb_frq DB   0
Bvb_sts DB   0
	endif
;------ All the variables of channel C ------
        DISPLAY "Cch_adr=",$
Ci_qty  DB   #01
C_qty   DB   #01
;-- this is cleared as a block
	if pt3_smpfix
Cs_Vsl  DB   #10
Cs_Nsl  DB   0
Cs_Esl  DB   0
Cs_dtn  DW   0
	endif
Cs_dsp  DB   0
Co_dsp  DB   0
Csl_dsp DW   0
Csl_stp DB   0
;-- ~this
Cch_adr DW   ZERO_M
;--- this is loaded via stack
Cfrq_Ad DW   frq_C
Cvol_Ad DW   vol_C
Cs_adr  DW   ZERO_M
Co_adr  DW   ZERO_M
CCh_IDN DB   2
	if pt3_sld12||pt3_port3||pt3_vib6
Csl_plk DB   Xsl_sts-Xsl_plk
	endif
;--- ~this
Cvb_lok DB   #FF
Cg_vol  DB maxvol;#F0
Cm_vol  DB   0
Cs_note DB   0
	if pt3_sld12||pt3_port3||pt3_vib6
Csl_tfr DW   0
Csl_not DB   0
Csl_sts DB   0
	endif
	if pt3_vib6
Cvb_stp DB   0
Cvb_frq DB   0
Cvb_sts DB   0
	endif
        DISPLAY "end of Xch_adr=",$

	ifndef ZERO_M
ZERO_M=Am_vol ;has 0 in it
	endif


;------ Play one Frame of module ------
        DISPLAY "PLAY=",$
PLAY    ;PUSH IY
int_qty=$+1
	LD   A,1
        DEC  A
        JR   NZ,SamplIT
;------ Parse the next line of a pattern ------
        LD   hl,Ach_adr ;Afrq_Ad
        CALL Get_Pos
        LD   hl,Bch_adr ;Bfrq_Ad
        CALL Get_Pos
        LD   hl,Cch_adr ;Cfrq_Ad
        CALL Get_Pos
curtempo=$+1
	LD   A,3                ;tempo
SamplIT
	LD   (int_qty),A
;------ Play channels ABC with sampler ------
N_add=$+3
	LD   IX,0               ;HX=noise LX=mix
	 if pt3_smpenv
        LD   BC,0               ;smp_sl_env
        EXX 
	 endif
        LD   IY,Ach_adr ;Afrq_Ad
        CALL OneChan
        LD   IY,Bch_adr ;Bfrq_Ad
        CALL OneChan
        LD   IY,Cch_adr ;Cfrq_Ad
        CALL OneChan
;------ Modified samples for Envelope ------
	 if pt3_Esld9A||pt3_smpenv
;Sampl_E
	EXX
	 if pt3_Esld9A 
Esl_frq=$+1
	LD   DE,0              ;stp_sl_env
	 endif
Env_frq=$+1
	LD   HL,0              ;frq_env
        ADD  HL,BC
	 if pt3_Esld9A 
        ADD  HL,DE
	 endif
        LD   (frq_E),HL
	 else
Env_frq=frq_E
	 endif
;------ Find Slide DSP for Envelope ------
	 if pt3_Esld9A 
Esl_stp LD   A,0
        DEC  A
        JP   M,MPU_Out
        JR   NZ,Esl_n0
Esl_sds LD   HL,0
        ADD  HL,DE
        LD   (Esl_frq),HL
Esl_sts LD   A,0
Esl_n0  LD   (Esl_stp+1),A
	 endif
;---- Update Noise & Mixer for Out ----
MPU_Out LD   A,HX               ;noise value
        LD   (N_add),A
N_frq=$+1
	ADD  A,0
        LD   (Noise),A
        LD   A,LX               ;mixer bits
        LD   (Mixer),A
        ;POP  IY                 ;old IY value
        LD   HL,frq_A ;l=0 if !jpplay
	if pt3_shortay
	ld c,pt3_aysel
	else
        ;LD   DE,#FFBF
        ;LD   C,#FD
	endif
	 if pt3_jpplay
	ld d,0
	 endif
        LD   A,14
AY_Out  
	if pt3_shortay
	 if pt3_jpplay
        OUT  (C),d
	inc d
	 else
        OUT  (C),l
	 endif
	else
	ld bc,#fffd ;LD   B,D
	 if pt3_jpplay
        OUT  (C),d
	inc d
	 else
        OUT  (C),l
	 endif
        ld b,#bf ;LD   B,E
	endif
        DEC  A
        JR   Z,EN_Out
        OUTI 
        JR   AY_Out
EN_Out  
	 if (pt3_vol&&pt3_jpplay) ;not here if vol&jpplay
	ld hl,E_form
	 endif
	OR   (HL)
        RET  m;Z ;no envelope init
	if pt3_shortay
	out (pt3_aydat),a
	else
        OUT  (C),A ;init the envelope
	endif
        LD   (HL),c;0 ;no envelope init
        RET 

;------ Universal sampler for ABC channels ------
OneChan
	LD   (Quit_S+1),SP ;TODO optimize? (it's fixed if called from fixed interrupt stack)
        LD   SP,IY
	pop hl
        POP  HL
        LD   (FrqR_adr),HL
        POP  HL
        LD   (VolR_adr),HL
        POP  HL
        LD   (Xs_adr+1),HL
        POP  HL
        LD   (Xo_adr+1),HL
        POP  HL
        LD   A,L
        LD   (Ch_Roll+1),A
	 if pt3_sld12||pt3_port3
        LD   A,H
        LD   (Xsl_plk-1),A
	 endif
;------ Modified PT3.67 sampler ------
	if pt3_sld12||pt3_port3||pt3_vib6
        LD   A,(IY+dvb_lok)          ;Xvb_lok
        LD   H,A
	else
	ld a,h
	endif
        INC  A
        JP   Z,Xvb_n0 ;A=0 (for volume)!
Xs_adr  LD   SP,0               ;sample
        POP  DE                 ;loop E=beg D=end
        LD   A,(IY+ds_dsp)          ;Xs_dsp
        LD   L,A
        INC  A
        CP   D
        JR   C,Xs_n0
        LD   A,E
Xs_n0   LD   (IY+ds_dsp),A
        ADD  HL,HL
        ADD  HL,HL
        ADD  HL,SP
        LD   SP,HL
        POP  DE                 ;D= Nm ts ns Tm v3 v2 v1 v0
        LD   A,D                ;E= sv +- N4 N3 N2 N1 N0 Em
	 if pt3_smpfix
        OR   #F0
        LD   L,A
        LD   A,E
        ADD  A,A
        LD   A,(IY+ds_Vsl)          ;Xs_Vsl
        JR   NC,Xs_VslG
        JP   M,Xs_n2
        SUB  1
        JR   Xs_n3
Xs_n2   CP   31
Xs_n3   ADC  A,0
        LD   (IY+ds_Vsl),A
Xs_VslG ADD  A,L
        JR   C,Xs_n4
        XOR  A
Xs_n4   CP   16
        JR   C,Xg_vol
        LD   A,15
Xg_vol  
	 else
	and 15
	 endif
	ADD  A,(IY+dg_vol)          ;Xg_vol
	 if pt3_vol
        LD   L,A
        LD   H,tab_vol/256
        LD   A,(HL)
	 else
;#0..f + #f1 (minvol) = NC, 0
;#0..f + #ff (maxvol) = C, 0..f
	inc a
	jr c,$+3
	xor a
	 endif
        SRL  E 			;envmask
        JR   C,Xm_vo0
        OR   (IY+dm_vol)            ;Xm_vol
Xm_vo0  EXA 

        LD   A,D
        RLCA 
	 if pt3_smpenv
        JR   C,Xs_n5
	 else
        JR   C,Xs_n7
	 endif
	 if pt3_smpfix
        LD   A,(IY+ds_Nsl)          ;Xs_Nsl
        ADD  A,E
        BIT  5,D
        JR   Z,Xs_n6
        LD   (IY+ds_Nsl),A
Xs_n6   LD   HX,A
	 else
	ld hx,e
	 endif
	 if pt3_smpenv
        JR   Xs_n7
Xs_n5   LD   A,E
        AND  31
        CP   16
        JR   C,Xs_Esl
        OR   #F0
Xs_Esl
	 if pt3_smpfix
	ADD  A,(IY+ds_Esl)          ;Xs_Esl
        BIT  5,D
        JR   Z,Xs_n9
        LD   (IY+ds_Esl),A
Xs_n9
	 endif
	EXX 
        ADD  A,C
        LD   C,A
        EXX 
	 endif
Xs_n7

	LD   A,D
        AND  %10010000
Ch_Roll LD   B,0
MixLoop RRCA 
        DJNZ MixLoop
        OR   LX
        LD   LX,A
	 if pt3_smpfix
        POP  BC                 ;smp_frq_dsp
        LD   L,(IY+ds_dtn)          ;dsp accumulator
        LD   H,(IY+ds_dtn+1)
        ADD  HL,BC
        BIT  6,D
        JR   Z,Xs_n10
        LD   (IY+ds_dtn),L          ;new value
        LD   (IY+ds_dtn+1),H          ;of dsp accumulator
Xs_n10  EX   DE,HL
	 else
	pop de
	 endif
Xo_adr  LD   SP,0               ;ornament
        POP  BC                 ;loop C=beg B=end
        LD   A,(IY+do_dsp)          ;Xo_dsp
        LD   L,A
        INC  A
        CP   B
        JR   C,Xo_n0
        LD   A,C
Xo_n0   LD   (IY+do_dsp),A
        LD   H,0
        ADD  HL,SP
        LD   A,(IY+ds_note)          ;Xs_note
        ADD  A,(HL)             ;dsp_orn  (ORNAMENTS ON/OFF)
        ADD  A,A
	 if pt3_ornrange
        JR   NC,$+3             ;;
        XOR  A                  ;;
	 endif
;Xo_n1   
	if tab_frq&255
	add a,tab_frq&255
	endif
	 if pt3_ornrange
	LD   L,95*2 + (tab_frq&255)             ;;
        CP   L                  ;;
        JR   NC,$+3             ;;
	 endif
        LD   L,A                ;;
        LD   H,tab_frq/256
        LD   SP,HL
        POP  HL                 ;note frequency+
        ADD  HL,DE              ;+sample frq disp accumulator (shift)+
	 if pt3_sld12||pt3_port3
        LD   C,(IY+dsl_dsp)
        LD   B,(IY+dsl_dsp+1)
        ADD HL,BC               ;+SLIDE TONE/PORT accumulator
	 endif
FrqR_adr=$+1
	LD   (frq_A),HL
	 if pt3_sld12||pt3_port3
        LD   A,(IY+dsl_stp)          ;Xsl_stp
        DEC  A
        JP   M,Xsl_s0           ;If Xsl_stp=0 then SLIDE OFF
        JR   NZ,Xsl_s1
        LD   E,(IY+dsl_tfr)          ;Xsl_tfr - delta for
        LD   D,(IY+dsl_tfr+1)          ;SLIDE TONE/PORT accumulator when it changed
        ADD  HL,DE              
        EX   DE,HL
        ADD  HL,BC
        LD   (IY+dsl_dsp),L          ;new value of changed
        LD   (IY+dsl_dsp+1),H          ;SLIDE TONE/PORT accumulator
        JR   Xsl_sts            ;PORT ON/OFF switch!
Xsl_plk EQU  $
        LD   A,(IY+dsl_not)          ;destination note for
        LD   L,A                ;PORT command.
        ADD  HL,HL
        LD   H,tab_frq/256
        LD   SP,HL
        POP  HL
        CP   (IY+ds_note)            ;the last note seen, HL contains
        JR   NC,Xsl_n0          ;its frequency.
        EX   DE,HL
Xsl_n0  SBC  HL,DE
        JR   C,Xsl_sts ;BUG if the portamento step exceeds the distance between notes?
        LD   (IY+ds_note),A          ;frequencies match, so:
        XOR  A                  ;- Xs_note=Xsl_not
        LD   (IY+dsl_dsp),A          ;- Xsl_dsp=0
        LD   (IY+dsl_dsp+1),A
        JR   Xsl_s1
Xsl_sts LD   A,(IY+dsl_sts)
Xsl_s1  LD   (IY+dsl_stp),A
	 endif
Xsl_s0  EXA 
Xvb_n0  EQU  $
VolR_adr=$+1
	LD   (vol_A),A
	 if pt3_vib6
        LD   A,(IY+dvb_stp)
        DEC  A
        JP   M,Quit_S
        JR   NZ,Xvb_n1
        DEC  A                  ;A=#FF
        XOR  (IY+dvb_lok)            ;A XOR Xvb_lok
        LD   (IY+dvb_lok),A
        LD   A,(IY+dvb_frq)
        JR   NZ,Xvb_n1
        LD   A,(IY+dvb_sts)
Xvb_n1  LD   (IY+dvb_stp),A
	 endif
Quit_S  LD   SP,0
        RET 
;------ Get Position + Next Pattern ------
Get_Pos
	ld (curiy),hl
	push hl
	pop iy
	ld e,(hl)      ;adr_chan
	inc hl
	ld d,(hl)
	DEC  (IY+d_qty)            ;X_qty (lines counter for this channel)
        RET  NZ
        ;LD   E,(IY+dch_adr)          ;adr_chan
        ;LD   D,(IY+dch_adr+1)
        LD   A,(DE)
        AND  A
        JR   NZ,Cont_0
        LD   (N_frq),A
        LD   D,A
        LD   (Sv_SP0+1),SP
Psa_beg_addr=$+1
	LD   HL,module+201
        LD   A,(HL)
        INC  A
        JR   NZ,Cont_1
Psa_loop_addr=$+1
	LD   HL,module+201
Cont_1  
	if pt3_ts2
	ld a,47*3
	sub (hl)
	ld e,a
	else
	LD   E,(HL)
	endif
        INC  HL
        LD   (Psa_beg_addr),HL
Psa_chn_addr=$+1
	LD   HL,0
        ADD  HL,DE
        ADD  HL,DE
        LD   SP,HL
;ia_pos0
	 if pt3_init 
	LD   BC,(Compile+1)
        POP  HL
        ADD  HL,BC
        EX   DE,HL              ;DE=adr_chn_A
        POP  HL
        ADD  HL,BC              ;HL=adr_chn_B
        LD   (Bch_adr),HL
        POP  HL
        ADD  HL,BC              ;HL=adr_chn_C
        LD   (Cch_adr),HL
	 else
        pop de  ;DE=adr_chn_A
        POP  HL  ;HL=adr_chn_B
        LD   (Bch_adr),HL
        POP  HL   ;HL=adr_chn_C
        LD   (Cch_adr),HL
	 endif
Sv_SP0  LD   SP,0
Cont_0  CALL Xn_clc1
        ;LD   (IY+dch_adr),E
        ;LD   (IY+dch_adr+1),D
curiy=$+2
	ld (0),de
        LD   A,(IY+di_qty)          ;Xi_qty
        LD   (IY+d_qty),A          ;X_qty
        RET 

	;include "pt3parse.asm"

	if !pt3_init
	SUBROUTINES
;Xni_not
	;module local
	include "pt3parse.asm"
	;XNI_NOT
	;EFFECTS
	;endmodule
moduleaddr=$-105
	;org progcopy
	org $-105
        DISPLAY "Player Length (without init):",$-Compile
	;INITS
	endif

	if pt3_init
	include "pt3parse.asm"
	;XNI_NOT
	;EFFECTS
;------ Frequency Tables for Generate ------
Tb_PT   DW   #0C22*2,#0B72*2,#0ACF*2,#0A33*2
        DW   #09A1*2,#0917*2,#0894*2,#0819*2
        DW   #07A4*2,#0737*2,#06CF*2,#066D*2
Tb_ST   DW   #0EF8*2,#0E10*2,#0D60*2,#0C80*2
        DW   #0BD8*2,#0B28*2,#0A88*2,#09F0*2
        DW   #0960*2,#08E0*2,#0858*2,#07E0*2
Tb_REAL DW   #0CDA*2,#0C22*2,#0B72*2,#0ACF*2
        DW   #0A33*2,#09A1*2,#0917*2,#0894*2
        DW   #0819*2,#07A4*2,#0737*2,#06CF*2
Tb_ASM  DW   #0D10*2,#0C55*2,#0BA4*2,#0AFC*2
        DW   #0A5F*2,#09CA*2,#093D*2,#08B8*2
        DW   #083B*2,#07C5*2,#0755*2,#06EC*2
;------ end of player, start of module ------
	endif

;module  DISPLAY "Module Adress:",module
        DISPLAY "Player Length:",$-Compile

	if 1==0
;------ usage example (with pt3_init=1) -------
        INCBIN  "ace.m"
        ORG  #7000
        DI 
        CALL Compile
play_l  EI 
        HALT 
        CALL Compile+5
        LD   A,#7F
        IN   A,(-2)
        RRA 
        JR   C,play_l
        JP   Compile+8
	endif

	endmodule
