PROTRACKER372 PT3PLAY H

From MSX MUSIC WIKI
Revision as of 20:15, 8 March 2020 by Kumokosi (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

PT3Play C���_�`�*

;Vortex Tracker II v1.0 PT3 player for ZX Spectrum
;(c)2004,2007 S.V.Bulba <vorobey@mail.khstu.ru>
;http://bulba.untergrund.net (http://bulba.at.kz)

;Release number
Release="7"

IFN ?Id
Id=1
ENDIF 
;Features
;--------
;-Can be compiled at any address (i.e. no need rounding ORG
; address).
;-Variables (VARS) can be located at any address (not only after
;code block).
;-INIT subroutine detects module version and rightly generates
; both note and volume tables outside of code block (in VARS).
;-Two portamento (spc. command 3xxx) algorithms (depending of
; module version).
;-New 1.XX and 2.XX special command behaviour (only for PT v3.7
; and higher).
;-Any Tempo value are accepted (including Tempo=1 and Tempo=2).
;-Fully compatible with Ay_Emul PT3 player codes.
;-See also notes at the end of this source code.

;Limitations
;-----------
;-Can run in RAM only (self-modified code is used).

;Warning!!! PLAY subroutine can crash if no module are loaded
;into RAM or INIT subroutine was not called before.

;Call MUTE or INIT one more time to mute sound after stopping
;playing

;       ORG #C000

;Test codes (commented)
;       CALL START
;       EI
;_LP    HALT
;       CALL START+5
;       XOR A
;       IN A,(#FE)
;       CPL
;       AND 15
;       JR Z,_LP
;       JR START+8

TonA=0
TonB=2
TonC=4
Noise=6
Mixer=7
AmplA=8
AmplB=9
AmplC=10
Env=11
EnvTp=13

;ChannelsVars
;       STRUCT  CHP
;reset group
PsInOr=0
PsInSm=1
CrAmSl=2
CrNsSl=3
CrEnSl=4
TSlCnt=5
CrTnSl=6
TnAcc=8
COnOff=10
;reset group

OnOffD=11

;IX for PTDECOD here (+12)
OffOnD=12
OrnPtr=13
SamPtr=15
NNtSkp=17
Note=18
SlToNt=19
Env_En=20
Flags=21
 ;Enabled - 0,SimpleGliss - 2
TnSlDl=22
TSlStp=23
TnDelt=25
NtSkCn=27
Volume=28
;       ENDS
CHP=29

;Entry and other points
;START initialization
;START+3 initialization with module address in HL
;START+5 play one quark
;START+8 mute
;START+10 setup and status flags
;START+11 pointer to current position value in PT3 module;
;After INIT (START+11) points to Postion0-1 (optimization)

START
        LD HL,MDLADDR
        JR INIT
        JP PLAY
        JR MUTE
SETUP   DB 0 ;set bit0 to 1, if you want to play without looping
             ;bit7 is set each time, when loop point is passed
CrPsPtr DW 0
        IFN Id
;Identifier
        DB "=VTII PT3 Player r.",Release,"="
        ENDIF 
CHECKLP LD HL,SETUP
        SET 7,(HL)
        BIT 0,(HL)
        RET Z
        POP HL
        LD HL,DelyCnt
        INC (HL)
        LD HL,ChanA+NtSkCn
        INC (HL)
MUTE    XOR A
        LD H,A
        LD L,A
        LD (AYREGS+AmplA),A
        LD (AYREGS+AmplB),HL
        JP ROUT_A0

INIT
;HL - AddressOfModule

        LD (MODADDR),HL
        LD (MDADDR2),HL
        PUSH HL
        LD DE,100
        ADD HL,DE
        LD A,(HL)
        LD (Delay),A
        PUSH HL
        POP IX
        ADD HL,DE
        LD (CrPsPtr),HL
        LD E,(IX+102-100)
        ADD HL,DE
        INC HL
        LD (LPosPtr),HL
        POP DE
        LD L,(IX+103-100)
        LD H,(IX+104-100)
        ADD HL,DE
        LD (PatsPtr),HL
        LD HL,169
        ADD HL,DE
        LD (OrnPtrs),HL
        LD HL,105
        ADD HL,DE
        LD (SamPtrs),HL
        LD HL,SETUP
        RES 7,(HL)

;note table data depacker
        LD DE,T_PACK
        LD BC,T1_+(2*49)-1
TP_0    LD A,(DE)
        INC DE
        CP 15*2
        JR NC,TP_1
        LD H,A
        LD A,(DE)
        LD L,A
        INC DE
        JR TP_2
TP_1    PUSH DE
        LD D,0
        LD E,A
        ADD HL,DE
        ADD HL,DE
        POP DE
TP_2    LD A,H
        LD (BC),A
        DEC BC
        LD A,L
        LD (BC),A
        DEC BC
        SUB #F8*2
        JR NZ,TP_0

        LD HL,VARS
        LD (HL),A
        LD DE,VARS+1
        LD BC,VAR0END-VARS-1
        LDIR 
        INC A
        LD (DelyCnt),A
        LD HL,#F001 ;H - Volume, L - NtSkCn
        LD (ChanA+NtSkCn),HL
        LD (ChanB+NtSkCn),HL
        LD (ChanC+NtSkCn),HL

        LD HL,EMPTYSAMORN
        LD (AdInPtA),HL ;ptr to zero
        LD (ChanA+OrnPtr),HL ;ornament 0 is "0,1,0"
        LD (ChanB+OrnPtr),HL ;in all versions from
        LD (ChanC+OrnPtr),HL ;3.xx to 3.6x and VTII

        LD (ChanA+SamPtr),HL ;S1 There is no default
        LD (ChanB+SamPtr),HL ;S2 sample in PT3, so, you
        LD (ChanC+SamPtr),HL ;S3 can comment S1,2,3; see
                                    ;also EMPTYSAMORN comment

        LD A,(IX+13-100) ;EXTRACT VERSION NUMBER
        SUB #30
        JR C,L20
        CP 10
        JR C,L21
L20     LD A,6
L21     LD (Version),A
        PUSH AF
        CP 4
        LD A,(IX+99-100) ;TONE TABLE NUMBER
        RLA 
        AND 7

;NoteTableCreator (c) Ivan Roshin
;A - NoteTableNumber*2+VersionForNoteTable
;(xx1b - 3.xx..3.4r, xx0b - 3.4x..3.6x..VTII1.0)

        LD HL,NT_DATA
        PUSH DE
        LD D,B
        ADD A,A
        LD E,A
        ADD HL,DE
        LD E,(HL)
        INC HL
        SRL E
        SBC A,A
        AND #A7 ;#00 (NOP) or #A7 (AND A)
        LD (L3),A
        EX DE,HL
        POP BC ;BC=T1_
        ADD HL,BC

        LD A,(DE)
        ADD A,T_
        LD C,A
        ADC A,'T_
        SUB C
        LD B,A
        PUSH BC
        LD DE,NT_
        PUSH DE

        LD B,12
L1      PUSH BC
        LD C,(HL)
        INC HL
        PUSH HL
        LD B,(HL)

        PUSH DE
        EX DE,HL
        LD DE,23
        LD HX,8

L2      SRL B
        RR C
L3      DB #19  ;AND A or NOP
        LD A,C
        ADC A,D ;=ADC 0
        LD (HL),A
        INC HL
        LD A,B
        ADC A,D
        LD (HL),A
        ADD HL,DE
        DEC HX
        JR NZ,L2

        POP DE
        INC DE
        INC DE
        POP HL
        INC HL
        POP BC
        DJNZ L1

        POP HL
        POP DE

        LD A,E
        CP TCOLD_1
        JR NZ,CORR_1
        LD A,#FD
        LD (NT_+#2E),A

CORR_1  LD A,(DE)
        AND A
        JR Z,TC_EXIT
        RRA 
        PUSH AF
        ADD A,A
        LD C,A
        ADD HL,BC
        POP AF
        JR NC,CORR_2
        DEC (HL)
        DEC (HL)
CORR_2  INC (HL)
        AND A
        SBC HL,BC
        INC DE
        JR CORR_1

TC_EXIT

        POP AF

;VolTableCreator (c) Ivan Roshin
;A - VersionForVolumeTable (0..4 - 3.xx..3.4x;
                           ;5.. - 3.5x..3.6x..VTII1.0)

        CP 5
        LD HL,#11
        LD D,H
        LD E,H
        LD A,#17
        JR NC,M1
        DEC L
        LD E,L
        XOR A
M1      LD (M2),A

        LD IX,VT_+16
        LD C,#10

INITV2  PUSH HL

        ADD HL,DE
        EX DE,HL
        SBC HL,HL

INITV1  LD A,L
M2      DB #7D
        LD A,H
        ADC A,0
        LD (IX),A
        INC IX
        ADD HL,DE
        INC C
        LD A,C
        AND 15
        JR NZ,INITV1

        POP HL
        LD A,E
        CP #77
        JR NZ,M3
        INC E
M3      LD A,C
        AND A
        JR NZ,INITV2

        JP ROUT_A0

;pattern decoder
PD_OrSm LD (IX-12+Env_En),0
        CALL SETORN
        LD A,(BC)
        INC BC
        RRCA 

PD_SAM  ADD A,A
PD_SAM_ LD E,A
        LD D,0
SamPtrs=$+1
        LD HL,#2121
        ADD HL,DE
        LD E,(HL)
        INC HL
        LD D,(HL)
MODADDR=$+1
        LD HL,#2121
        ADD HL,DE
        LD (IX-12+SamPtr),L
        LD (IX-12+SamPtr+1),H
        JR PD_LOOP

PD_VOL  RLCA 
        RLCA 
        RLCA 
        RLCA 
        LD (IX-12+Volume),A
        JR PD_LP2

PD_EOff LD (IX-12+Env_En),A
        LD (IX-12+PsInOr),A
        JR PD_LP2

PD_SorE DEC A
        JR NZ,PD_ENV
        LD A,(BC)
        INC BC
        LD (IX-12+NNtSkp),A
        JR PD_LP2

PD_ENV  CALL SETENV
        JR PD_LP2

PD_ORN  CALL SETORN
        JR PD_LOOP

PD_ESAM LD (IX-12+Env_En),A
        LD (IX-12+PsInOr),A
        CALL NZ,SETENV
        LD A,(BC)
        INC BC
        JR PD_SAM_

PTDECOD LD A,(IX-12+Note)
        LD (PrNote+1),A
        LD L,(IX-12+CrTnSl)
        LD H,(IX-12+CrTnSl+1)
        LD (PrSlide+1),HL

PD_LOOP LD DE,#2010
PD_LP2  LD A,(BC)
        INC BC
        ADD A,E
        JR C,PD_OrSm
        ADD A,D
        JR Z,PD_FIN
        JR C,PD_SAM
        ADD A,E
        JR Z,PD_REL
        JR C,PD_VOL
        ADD A,E
        JR Z,PD_EOff
        JR C,PD_SorE
        ADD A,96
        JR C,PD_NOTE
        ADD A,E
        JR C,PD_ORN
        ADD A,D
        JR C,PD_NOIS
        ADD A,E
        JR C,PD_ESAM
        ADD A,A
        LD E,A
        LD HL,SPCCOMS+#FF20-#2000
        ADD HL,DE
        LD E,(HL)
        INC HL
        LD D,(HL)
        PUSH DE
        JR PD_LOOP

PD_NOIS LD (Ns_Base),A
        JR PD_LP2

PD_REL  RES 0,(IX-12+Flags)
        JR PD_RES

PD_NOTE LD (IX-12+Note),A
        SET 0,(IX-12+Flags)
        XOR A

PD_RES  LD (PDSP_+1),SP
        LD SP,IX
        LD H,A
        LD L,A
        PUSH HL
        PUSH HL
        PUSH HL
        PUSH HL
        PUSH HL
        PUSH HL
PDSP_   LD SP,#3131

PD_FIN  LD A,(IX-12+NNtSkp)
        LD (IX-12+NtSkCn),A
        RET 

C_PORTM RES 2,(IX-12+Flags)
        LD A,(BC)
        INC BC
;SKIP PRECALCULATED TONE DELTA (BECAUSE
;CANNOT BE RIGHT AFTER PT3 COMPILATION)
        INC BC
        INC BC
        LD (IX-12+TnSlDl),A
        LD (IX-12+TSlCnt),A
        LD DE,NT_
        LD A,(IX-12+Note)
        LD (IX-12+SlToNt),A
        ADD A,A
        LD L,A
        LD H,0
        ADD HL,DE
        LD A,(HL)
        INC HL
        LD H,(HL)
        LD L,A
        PUSH HL
PrNote  LD A,#3E
        LD (IX-12+Note),A
        ADD A,A
        LD L,A
        LD H,0
        ADD HL,DE
        LD E,(HL)
        INC HL
        LD D,(HL)
        POP HL
        SBC HL,DE
        LD (IX-12+TnDelt),L
        LD (IX-12+TnDelt+1),H
        LD E,(IX-12+CrTnSl)
        LD D,(IX-12+CrTnSl+1)
Version=$+1
        LD A,#3E
        CP 6
        JR C,OLDPRTM ;Old 3xxx for PT v3.5-
PrSlide LD DE,#1111
        LD (IX-12+CrTnSl),E
        LD (IX-12+CrTnSl+1),D
OLDPRTM LD A,(BC) ;SIGNED TONE STEP
        INC BC
        EXA 
        LD A,(BC)
        INC BC
        AND A
        JR Z,NOSIG
        EX DE,HL
NOSIG   SBC HL,DE
        JP P,SET_STP
        CPL 
        EXA 
        NEG 
        EXA 
SET_STP LD (IX-12+TSlStp+1),A
        EXA 
        LD (IX-12+TSlStp),A
        LD (IX-12+COnOff),0
        RET 

C_GLISS SET 2,(IX-12+Flags)
        LD A,(BC)
        INC BC
        LD (IX-12+TnSlDl),A
        AND A
        JR NZ,GL36
        LD A,(Version) ;AlCo PT3.7+
        CP 7
        SBC A,A
        INC A
GL36    LD (IX-12+TSlCnt),A
        LD A,(BC)
        INC BC
        EXA 
        LD A,(BC)
        INC BC
        JR SET_STP

C_SMPOS LD A,(BC)
        INC BC
        LD (IX-12+PsInSm),A
        RET 

C_ORPOS LD A,(BC)
        INC BC
        LD (IX-12+PsInOr),A
        RET 

C_VIBRT LD A,(BC)
        INC BC
        LD (IX-12+OnOffD),A
        LD (IX-12+COnOff),A
        LD A,(BC)
        INC BC
        LD (IX-12+OffOnD),A
        XOR A
        LD (IX-12+TSlCnt),A
        LD (IX-12+CrTnSl),A
        LD (IX-12+CrTnSl+1),A
        RET 

C_ENGLS LD A,(BC)
        INC BC
        LD (Env_Del),A
        LD (CurEDel),A
        LD A,(BC)
        INC BC
        LD L,A
        LD A,(BC)
        INC BC
        LD H,A
        LD (ESldAdd),HL
        RET 

C_DELAY LD A,(BC)
        INC BC
        LD (Delay),A
        RET 

SETENV  LD (IX-12+Env_En),E
        LD (AYREGS+EnvTp),A
        LD A,(BC)
        INC BC
        LD H,A
        LD A,(BC)
        INC BC
        LD L,A
        LD (EnvBase),HL
        XOR A
        LD (IX-12+PsInOr),A
        LD (CurEDel),A
        LD H,A
        LD L,A
        LD (CurESld),HL
C_NOP   RET 

SETORN  ADD A,A
        LD E,A
        LD D,0
        LD (IX-12+PsInOr),D
OrnPtrs=$+1
        LD HL,#2121
        ADD HL,DE
        LD E,(HL)
        INC HL
        LD D,(HL)
MDADDR2=$+1
        LD HL,#2121
        ADD HL,DE
        LD (IX-12+OrnPtr),L
        LD (IX-12+OrnPtr+1),H
        RET 

;ALL 16 ADDRESSES TO PROTECT FROM BROKEN PT3 MODULES
SPCCOMS DW C_NOP
        DW C_GLISS
        DW C_PORTM
        DW C_SMPOS
        DW C_ORPOS
        DW C_VIBRT
        DW C_NOP
        DW C_NOP
        DW C_ENGLS
        DW C_DELAY
        DW C_NOP
        DW C_NOP
        DW C_NOP
        DW C_NOP
        DW C_NOP
        DW C_NOP

CHREGS  XOR A
        LD (Ampl),A
        BIT 0,(IX+Flags)
        PUSH HL
        JP Z,CH_EXIT
        LD (CSP_+1),SP
        LD L,(IX+OrnPtr)
        LD H,(IX+OrnPtr+1)
        LD SP,HL
        POP DE
        LD H,A
        LD A,(IX+PsInOr)
        LD L,A
        ADD HL,SP
        INC A
        CP D
        JR C,CH_ORPS
        LD A,E
CH_ORPS LD (IX+PsInOr),A
        LD A,(IX+Note)
        ADD A,(HL)
        JP P,CH_NTP
        XOR A
CH_NTP  CP 96
        JR C,CH_NOK
        LD A,95
CH_NOK  ADD A,A
        EXA 
        LD L,(IX+SamPtr)
        LD H,(IX+SamPtr+1)
        LD SP,HL
        POP DE
        LD H,0
        LD A,(IX+PsInSm)
        LD B,A
        ADD A,A
        ADD A,A
        LD L,A
        ADD HL,SP
        LD SP,HL
        LD A,B
        INC A
        CP D
        JR C,CH_SMPS
        LD A,E
CH_SMPS LD (IX+PsInSm),A
        POP BC
        POP HL
        LD E,(IX+TnAcc)
        LD D,(IX+TnAcc+1)
        ADD HL,DE
        BIT 6,B
        JR Z,CH_NOAC
        LD (IX+TnAcc),L
        LD (IX+TnAcc+1),H
CH_NOAC EX DE,HL
        EXA 
        LD L,A
        LD H,0
        LD SP,NT_
        ADD HL,SP
        LD SP,HL
        POP HL
        ADD HL,DE
        LD E,(IX+CrTnSl)
        LD D,(IX+CrTnSl+1)
        ADD HL,DE
CSP_    LD SP,#3131
        EX (SP),HL
        XOR A
        OR (IX+TSlCnt)
        JR Z,CH_AMP
        DEC (IX+TSlCnt)
        JR NZ,CH_AMP
        LD A,(IX+TnSlDl)
        LD (IX+TSlCnt),A
        LD L,(IX+TSlStp)
        LD H,(IX+TSlStp+1)
        LD A,H
        ADD HL,DE
        LD (IX+CrTnSl),L
        LD (IX+CrTnSl+1),H
        BIT 2,(IX+Flags)
        JR NZ,CH_AMP
        LD E,(IX+TnDelt)
        LD D,(IX+TnDelt+1)
        AND A
        JR Z,CH_STPP
        EX DE,HL
CH_STPP SBC HL,DE
        JP M,CH_AMP
        LD A,(IX+SlToNt)
        LD (IX+Note),A
        XOR A
        LD (IX+TSlCnt),A
        LD (IX+CrTnSl),A
        LD (IX+CrTnSl+1),A
CH_AMP  LD A,(IX+CrAmSl)
        BIT 7,C
        JR Z,CH_NOAM
        BIT 6,C
        JR Z,CH_AMIN
        CP 15
        JR Z,CH_NOAM
        INC A
        JR CH_SVAM
CH_AMIN CP -15
        JR Z,CH_NOAM
        DEC A
CH_SVAM LD (IX+CrAmSl),A
CH_NOAM LD L,A
        LD A,B
        AND 15
        ADD A,L
        JP P,CH_APOS
        XOR A
CH_APOS CP 16
        JR C,CH_VOL
        LD A,15
CH_VOL  OR (IX+Volume)
        LD L,A
        LD H,0
        LD DE,VT_
        ADD HL,DE
        LD A,(HL)
CH_ENV  BIT 0,C
        JR NZ,CH_NOEN
        OR (IX+Env_En)
CH_NOEN LD (Ampl),A
        BIT 7,B
        LD A,C
        JR Z,NO_ENSL
        RLA 
        RLA 
        SRA A
        SRA A
        SRA A
        ADD A,(IX+CrEnSl) ;SEE COMMENT BELOW
        BIT 5,B
        JR Z,NO_ENAC
        LD (IX+CrEnSl),A
NO_ENAC LD HL,AddToEn
        ADD A,(HL) ;BUG IN PT3 - NEED WORD HERE.
                   ;FIX IT IN NEXT VERSION?
        LD (HL),A
        JR CH_MIX
NO_ENSL RRA 
        ADD A,(IX+CrNsSl)
        LD (AddToNs),A
        BIT 5,B
        JR Z,CH_MIX
        LD (IX+CrNsSl),A
CH_MIX  LD A,B
        RRA 
        AND #48
CH_EXIT LD HL,AYREGS+Mixer
        OR (HL)
        RRCA 
        LD (HL),A
        POP HL
        XOR A
        OR (IX+COnOff)
        RET Z
        DEC (IX+COnOff)
        RET NZ
        XOR (IX+Flags)
        LD (IX+Flags),A
        RRA 
        LD A,(IX+OnOffD)
        JR C,CH_ONDL
        LD A,(IX+OffOnD)
CH_ONDL LD (IX+COnOff),A
        RET 

PLAY    XOR A
        LD (AddToEn),A
        LD (AYREGS+Mixer),A
        DEC A
        LD (AYREGS+EnvTp),A
        LD HL,DelyCnt
        DEC (HL)
        JR NZ,PL2
        LD HL,ChanA+NtSkCn
        DEC (HL)
        JR NZ,PL1B
AdInPtA=$+1
        LD BC,#0101
        LD A,(BC)
        AND A
        JR NZ,PL1A
        LD D,A
        LD (Ns_Base),A
        LD HL,(CrPsPtr)
        INC HL
        LD A,(HL)
        INC A
        JR NZ,PLNLP
        CALL CHECKLP
LPosPtr=$+1
        LD HL,#2121
        LD A,(HL)
        INC A
PLNLP   LD (CrPsPtr),HL
        DEC A
        ADD A,A
        LD E,A
        RL D
PatsPtr=$+1
        LD HL,#2121
        ADD HL,DE
        LD DE,(MODADDR)
        LD (PSP_+1),SP
        LD SP,HL
        POP HL
        ADD HL,DE
        LD B,H
        LD C,L
        POP HL
        ADD HL,DE
        LD (AdInPtB),HL
        POP HL
        ADD HL,DE
        LD (AdInPtC),HL
PSP_    LD SP,#3131
PL1A    LD IX,ChanA+12
        CALL PTDECOD
        LD (AdInPtA),BC

PL1B    LD HL,ChanB+NtSkCn
        DEC (HL)
        JR NZ,PL1C
        LD IX,ChanB+12
AdInPtB=$+1
        LD BC,#0101
        CALL PTDECOD
        LD (AdInPtB),BC

PL1C    LD HL,ChanC+NtSkCn
        DEC (HL)
        JR NZ,PL1D
        LD IX,ChanC+12
AdInPtC=$+1
        LD BC,#0101
        CALL PTDECOD
        LD (AdInPtC),BC

Delay=$+1
PL1D    LD A,#3E
        LD (DelyCnt),A

PL2     LD IX,ChanA
        LD HL,(AYREGS+TonA)
        CALL CHREGS
        LD (AYREGS+TonA),HL
        LD A,(Ampl)
        LD (AYREGS+AmplA),A
        LD IX,ChanB
        LD HL,(AYREGS+TonB)
        CALL CHREGS
        LD (AYREGS+TonB),HL
        LD A,(Ampl)
        LD (AYREGS+AmplB),A
        LD IX,ChanC
        LD HL,(AYREGS+TonC)
        CALL CHREGS
;       LD A,(Ampl) ;Ampl = AYREGS+AmplC
;       LD (AYREGS+AmplC),A
        LD (AYREGS+TonC),HL

        LD HL,(Ns_Base_AddToNs)
        LD A,H
        ADD A,L
        LD (AYREGS+Noise),A

AddToEn=$+1
        LD A,#3E
        LD E,A
        ADD A,A
        SBC A,A
        LD D,A
        LD HL,(EnvBase)
        ADD HL,DE
        LD DE,(CurESld)
        ADD HL,DE
        LD (AYREGS+Env),HL

        XOR A
        LD HL,CurEDel
        OR (HL)
        JR Z,ROUT_A0
        DEC (HL)
        JR NZ,ROUT
Env_Del=$+1
        LD A,#3E
        LD (HL),A
ESldAdd=$+1
        LD HL,#2121
        ADD HL,DE
        LD (CurESld),HL

ROUT    XOR A
ROUT_A0 LD DE,#FFBF
        LD BC,#FFFD
        LD HL,AYREGS
LOUT    OUT (C),A
        LD B,E
        OUTI 
        LD B,D
        INC A
        CP 13
        JR NZ,LOUT
        OUT (C),A
        LD A,(HL)
        AND A
        RET M
        LD B,E
        OUT (C),A
        RET 

;Stupid ALASM limitations
NT_DATA DB 50*2 ;(T_NEW_0-T1_)*2
        DB TCNEW_0-T_
        DB 50*2+1 ;(T_OLD_0-T1_)*2+1
        DB TCOLD_0-T_
        DB 0*2+1 ;(T_NEW_1-T1_)*2+1
        DB TCNEW_1-T_
        DB 0*2+1 ;(T_OLD_1-T1_)*2+1
        DB TCOLD_1-T_
        DB 74*2;(T_NEW_2-T1_)*2
        DB TCNEW_2-T_
        DB 24*2 ;(T_OLD_2-T1_)*2
        DB TCOLD_2-T_
        DB 48*2 ;(T_NEW_3-T1_)*2
        DB TCNEW_3-T_
        DB 48*2 ;(T_OLD_3-T1_)*2
        DB TCOLD_3-T_

T_

TCOLD_0 DB #00+1,#04+1,#08+1,#0A+1,#0C+1,#0E+1,#12+1,#14+1
        DB #18+1,#24+1,#3C+1,0
TCOLD_1 DB #5C+1,0
TCOLD_2 DB #30+1,#36+1,#4C+1,#52+1,#5E+1,#70+1,#82,#8C,#9C
        DB #9E,#A0,#A6,#A8,#AA,#AC,#AE,#AE,0
TCNEW_3 DB #56+1
TCOLD_3 DB #1E+1,#22+1,#24+1,#28+1,#2C+1,#2E+1,#32+1,#BE+1,0
TCNEW_0 DB #1C+1,#20+1,#22+1,#26+1,#2A+1,#2C+1,#30+1,#54+1
        DB #BC+1,#BE+1,0
TCNEW_1=TCOLD_1
TCNEW_2 DB #1A+1,#20+1,#24+1,#28+1,#2A+1,#3A+1,#4C+1,#5E+1
        DB #BA+1,#BC+1,#BE+1,0

EMPTYSAMORN=$-1
        DB 1,0,#90 ;delete #90 if you don't need default sample

;first 12 values of tone tables (packed)

T_PACK  DB #06EC*2/256,#06EC*2
        DB #0755-#06EC
        DB #07C5-#0755
        DB #083B-#07C5
        DB #08B8-#083B
        DB #093D-#08B8
        DB #09CA-#093D
        DB #0A5F-#09CA
        DB #0AFC-#0A5F
        DB #0BA4-#0AFC
        DB #0C55-#0BA4
        DB #0D10-#0C55
        DB #066D*2/256,#066D*2
        DB #06CF-#066D
        DB #0737-#06CF
        DB #07A4-#0737
        DB #0819-#07A4
        DB #0894-#0819
        DB #0917-#0894
        DB #09A1-#0917
        DB #0A33-#09A1
        DB #0ACF-#0A33
        DB #0B73-#0ACF
        DB #0C22-#0B73
        DB #0CDA-#0C22
        DB #0704*2/256,#0704*2
        DB #076E-#0704
        DB #07E0-#076E
        DB #0858-#07E0
        DB #08D6-#0858
        DB #095C-#08D6
        DB #09EC-#095C
        DB #0A82-#09EC
        DB #0B22-#0A82
        DB #0BCC-#0B22
        DB #0C80-#0BCC
        DB #0D3E-#0C80
        DB #07E0*2/256,#07E0*2
        DB #0858-#07E0
        DB #08E0-#0858
        DB #0960-#08E0
        DB #09F0-#0960
        DB #0A88-#09F0
        DB #0B28-#0A88
        DB #0BD8-#0B28
        DB #0C80-#0BD8
        DB #0D60-#0C80
        DB #0E10-#0D60
        DB #0EF8-#0E10

        DISPLAY $

;vars from here can be stripped
;you can move VARS to any other address

VARS

ChanA   DS CHP
ChanB   DS CHP
ChanC   DS CHP

;GlobalVars
DelyCnt DB 0
CurESld DW 0
CurEDel DB 0
Ns_Base_AddToNs
Ns_Base DB 0
AddToNs DB 0

AYREGS

VT_     DS 256 ;CreatedVolumeTableAddress

EnvBase=VT_+14

T1_=VT_+16 ;Tone tables data depacked here

T_OLD_1=T1_
T_OLD_2=T_OLD_1+24
T_OLD_3=T_OLD_2+24
T_OLD_0=T_OLD_3+2
T_NEW_0=T_OLD_0
T_NEW_1=T_OLD_1
T_NEW_2=T_NEW_0+24
T_NEW_3=T_OLD_3

NT_     DS 192 ;CreatedNoteTableAddress

;local var
Ampl=AYREGS+AmplC

VAR0END=VT_+16 ;INIT zeroes from VARS to VAR0END-1

VARSEND=$

MDLADDR=$

        DISPLAY $

;Release 0 steps:
;11.Sep.2004 - Note tables creator
;12.Sep.2004 - Volume tables creator; INIT subroutine
;13.Sep.2004 - Play counters, position counters
;14.Sep.2004 - Patterns decoder subroutine
;15.Sep.2004 - Resting (no code)
;16.Sep.2004 - CHREGS subroutine; global debugging; 1st stable
;version was born
;17.Sep.2004 - Debugging and optimization. First release!
;Release 1 steps:
;20.Sep.2004 - local vars moved to code (selfmodified code
;smaller and faster)
;22.Sep.2004 - added mute sound entry at START+8; position
;pointer moved to START+11; added setup and status byte at
;START+10 noloop mode and loop passed flags added
;Release 2 steps:
;28.Sep.2004 - Optimization: code around CHREGS's volume and
;vibrato faster now; zeroing PD_RES through stack; Ton and Ampl
;moved from channel vars to global ones; first position selector
;removed from INIT; optimization for packers(Ivan Roshin method)
;Release 3 steps:
;2.Oct.2004 - optimization in INIT and PD_LOOP (thanks to Ivan
;Roshin)
;4.Oct.2004 - load delay from (hl) in INIT (2 bytes shorter)
;5.Oct.2004 - optimization in PD_LOOP (->PD_LP2)
;7.Oct.2004 - swaping some commands for better packing
;Release 4 steps:
;9.Oct.2004 - optimization around LD HL,SPCCOMS (thanks to Ivan
;Roshin); in PTDECOD swapped BC and DE to optimize C_PORTM;
;removed sam and orn len and loop channel vars; CHREGS totally
;optimized
;Release 5 steps:
;11.Oct.2004 - PD_OrSm and C_PORTM optimized; Ivan Roshin's
;volume tables creator algorithm (51 bytes shorter than mine)
;12.Oct.2004 - Ivan Roshin's note tables creator algorithm (74
;bytes shorter than mine)
;Release 6 steps:
;14.Oct.2004 - loop and next position calculations moved to INIT
;15.Oct.2004 - AdInPt moved to code
;19.Oct.2004 - Env_Del moved to code
;20.Oct.2004 - Version PUSH and POP (1 byte shorter, thanks to
;Ivan Roshin)
;22.Oct.2004 - Env_En moved from Flags' bit to byte (shorter and
;faster code)
;25.Oct.2004 - SETENV optimized
;29.Oct.2004 - Optimized around AddToEn (SBC A,A, thanks to Ivan
;Roshin)
;3.Nov.2004 - Note tables data was compressed; with depacker it
;is 9 bytes shorter than uncompressed (thanks to Ivan Roshin)
;4.Nov.2004 - default sample and ornament both are fixed now
;and placed into code block (6 bytes shorter)
;7.Nov.2004 - LD A,(Ns_Base):LD L,A changed to LD HL,(Ns_Base)
;(thanks to Dima Bystrov)
;9.Nov.2004 - Ns_Base and AddToNs are merged to Ns_Base_AddToNs;
;LD A,255 changed to DEC A (at start of PLAY); added ROUT_A0
;12.Nov.2004 - NtSkCn&Volume are merged (8 bytes smaller init);
;LD BC,T1_ changed to PUSH DE...POP BC in note table creator
;19.Dec.2004 - NT_DATA reorganized (6 bytes shorter, thanks to
;Ivan Roshin); C_PORTM and C_GLISS are merged via SET_STP (48
;tacts slower, but 8 bytes smaller, thanks to Ivan Roshin)
;Release 7 steps:
;29.Apr.2007 - SjAsm adaptation; new 1.xx and 2.xx
;interpretation for PT 3.7+.

;Tests in IMMATION TESTER V1.0 by Andy Man/POS (thanks to
;Himik's ZxZ for help):
;Module name/author     Min tacts       Max tacts       Average
;Spleen/Nik-O           1720            9256            5500
;Chuta/Miguel           1720            9496            5500
;Zhara/Macros           4536            8744            5500

;Size:
;Code block #651 bytes
;Variables #21D bytes (can be stripped)
;Size in RAM #651+#21D=#86E (2158) bytes

;Notes:
;Pro Tracker 3.4r can not be detected by header, so PT3.4r tone
;tables really used only for modules of 3.3 and older versions.

0.Sep.2004 - local vars moved to code (selfmodified code
;smaller and faster)
;22.Sep.2004 - added mute s