Login

Subversion Repositories NedoOS

Rev

Rev 1460 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

        DEVICE ZXSPECTRUM128
        include "../_sdk/sys_h.asm"

OLDTTYPES=0

;freemem_start=0x8000

MAXTIME=65536;4096

MAXNTRACKS=64

SCRNTRACKS=23;8
TRACKX=8
SCRTRACKWID=64-TRACKX

NOTE_SPACE=0 ;надо удобно на уровне mem! на уровне mem упаковывать
NOTE_GLISS=0xfe
NOTE_PAUSE=0xff
NOTE_RLE=0xe0
NOTE_LOWEST=1;0

COLOR=7
TIMECOLOR=0x04
TYPESCOLOR=0x06

MAXSONGNAME=64

;pgsamples содержит 256 байт на сэмпл (там все, кроме smp_pause), т.е. 37 строчек + зацикливание

        include "struct.asm"

smp_pause=0x4000
smp_snare=0x4000+(_s*256)
smp_tone=0x4000+(_t*256)
smp_maj=0x4000+(_p*256)
smp_bass=0x4000+(_b*256)
smp_crash=0x4000+(_c*256)
smp_drum=0x4000+(_d*256)
smp_hihat=0x4000+(_h*256)
smp_orn1of3=0x4000+(_1*256)
smp_orn2of6=0x4000+(_2*256)

        org PROGSTART
cmd_begin
        ld sp,0x4000 ;не должен опускаться ниже 0x3b00! иначе возможна порча OS
        OS_HIDEFROMPARENT
        ld e,3+0x80 ;6912 + keep gfx pages
        OS_SETGFX ;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+128=keep gfx ;+SET FOCUS ;e=-1: disable gfx (out: e=old gfxmode)
        ;ld e,0
        ;OS_CLS

        OS_GETMAINPAGES
;dehl=номера страниц в 0000,4000,8000,c000
        ld a,e
        ld (pgroots),a
        ;ld a,h
        ld (player4000page),a

        OS_NEWPAGE
        ld a,e
        ld (pgsamples),a

        call cls
        call setscrpg
        ld hl,0x5800
        ld de,0x5801
        ld bc,0x0020
        ld (hl),TIMECOLOR
        ldir
        push hl
        ld bc,4
        ld (hl),TYPESCOLOR
        ldir
        ld bc,31-4
        ld (hl),COLOR
        ldir
        pop hl
        ld bc,0x02c0
        ldir
        call gennotefont
       
        call setpgsamples
        ld de,0x4000;smp_pause
        ld a,0x40
killsamples0
        ld hl,wassmp_pause
        ld bc,256;szsmp_pause
        ldir
        dec a
        jr nz,killsamples0
        ld hl,wassmp_snare
        ld de,smp_snare
        ld bc,szsmp_snare
        ldir
        ld hl,wassmp_bass
        ld de,smp_bass
        ld bc,szsmp_bass
        ldir
        ld hl,wassmp_maj
        ld de,smp_maj
        ld bc,szsmp_maj
        ldir
        ld hl,wassmp_tone
        ld de,smp_tone
        ld bc,szsmp_tone
        ldir
        ld hl,wassmp_crash
        ld de,smp_crash
        ld bc,szsmp_crash
        ldir
        ld hl,wassmp_drum
        ld de,smp_drum
        ld bc,szsmp_drum
        ldir
        ld hl,wassmp_hihat
        ld de,smp_hihat
        ld bc,szsmp_hihat
        ldir
        ld hl,wassmp_orn1of3
        ld de,smp_orn1of3
        ld bc,szsmp_orn1of3
        ldir
        ld hl,wassmp_orn2of6
        ld de,smp_orn2of6
        ld bc,szsmp_orn2of6
        ldir
       
        call setpgroots

        ld hl,0x4000
        ld de,0x4001
        ld bc,0x3fff
        ld (hl),l;0
        ldir ;чистим roots

        call initmem
        ld c,1
        call pokecurtime_curtrack_c ;set part 0 in the beginning

        ld hl,wasfrq
        ld de,tfrq
        ld b,96
refrq0
        ld a,(hl)
        ld (de),a
        inc hl
        inc d
        ld a,(hl)
        ld (de),a
        inc hl
        dec d
        inc e
        djnz refrq0
        ld a,e
        sub 3*12
        ld l,a
        ld h,d
refrq1
        ld a,(hl)
        add a,3
        rra
        rra
        rra
        and 0x1f
        ld (de),a
        inc l
        inc d
        xor a
        ld (de),a
        dec d
        inc e
        jp p,refrq1
        ld l,0
;notes -128..-1 equal to 0
refrq2
        ld a,(hl)
        ld (de),a
        inc d
        inc h
        ld a,(hl)
        ld (de),a
        dec h
        dec d
        inc e
        jr nz,refrq2

;for example: 0=bass/pad, 2=tone, 5=drum
        ld ix,emptychn
        ;ld (ix+chn.keepme_in),5
        ;ld (ix+chn.channel_in),0
        call initchnnote_pause ;делает smpcuraddr=smp_pause и nogliss
        call setpgsamples
        call playsample ;после этого канал можно микшировать
        call setpgroots

        ld hl,COMMANDLINE ;command line
;command line = "untr <file>"
        call skipword
        ld a,(hl)
        or a
        jr z,nofilename
        call skipspaces
        ld de,tfilename
        call getword
        call untr_load
nofilename

;;;;;;;;;;;;;;;;;;;;;
        ;call setneedredraw
        call prcurcur
mainloop
        xor a
        ld (tracksmode),a
mainloop_nokey
        YIELD
        call updatescr
        ;call prcurcur
        GET_KEY
        or a
        jr z,mainloop_nokey
        ;push af
        ;call prcurcur
        ;pop af
         cp key_tab
         jp z,tracksloop
        ld hl,mainloop
        push hl
        ld c,0
        cp key_F2
        jp z,untr_save
        cp key_F3
        jp z,untr_load
        cp ss0
        jp z,untr_step0
        cp ss1
        jp z,untr_step1
        cp ss2
        jp z,untr_step2
        cp ss3
        jp z,untr_step3
        cp ss4
        jp z,untr_step4
        cp ss5
        jp z,untr_step5
        cp ss6
        jp z,untr_step6
        cp ss7
        jp z,untr_step7
        cp ss8
        jp z,untr_step8
        cp 'Y'
        jp z,untr_copy
        cp 'Q'
        jp z,untr_setplayall
        cp 'W'
        jp z,untr_setplaybegin
        cp 'E'
        jp z,untr_setplayend
        cp 'R'
        jp z,untr_startplay
        cp 'T'
        jp z,untr_stopplay
        cp key_left
        jp z,untr_left
        cp key_right
        jp z,untr_right
        cp key_up
        jp z,untr_up
        cp key_down
        jp z,untr_down
        cp key_pgup
        jp z,untr_pgup
        cp key_pgdown
        jp z,untr_pgdown
        cp key_home
        jp z,untr_home
        cp key_end
        jp z,untr_end
        cp key_enter
        jp z,untr_play
        cp key_del
        jp z,untr_del
        cp key_ins
        jp z,untr_ins
        cp key_backspace
        jp z,untr_backspace
        cp ' '
        jp z,untr_space
        cp key_esc
        jp z,untr_quit

        push af
;смотрим тип текущего канала
        ld a,(curtrack)
        call gettracktype
        cp _t;CHNTYPE_NOTES
        jr z,enternote
        pop af
        call keytodigit
        jr c,untr_afternotekey_alltracksiforder
        push af
        ld a,(newdigit)
        ld (olddigit),a
        pop af
        ld (newdigit),a
        call pokecurtime_curtrack_c
untr_afternotekey_alltracksiforder
        call setneedredraw_alltracksiforder
        jp untr_afternotekey;untr_right

untr_copy
;fromdigit,todigit,csY
        ;ld hy,0 ;track
        ld a,(curtrack)
        ld hy,a
;untr_copy0
        ld a,(olddigit)
        ld ly,a ;part
;ly=part
        ld a,hy ;a=track
        call getendaddr ;de=end or 0
        ex de,hl
untr_copybytes0
;hl=index
olddigit=$+2
        ld ly,0 ;part
        ld a,hy ;a=track
        call peektrackpartindex
        ld c,a
newdigit=$+2
        ld ly,0 ;part
        ld a,hy ;a=track
        call poketrackpartindex_c
        ld a,h
        or l
        dec hl
        jr nz,untr_copybytes0
        ;inc hy
        ;ld a,(ntracks)
        ;cp hy
        ;jr nz,untr_copy0
        jp setneedpralltracks

keytodigit
;ввод цифры 0..9a..zA..Z -> 1..62 (пробел -> 0)
;out: CY=error
        sub ' '
        ld c,a;0
        jr z,enterdigok
        sub '0'-' '
        cp 10
        ld c,1
        jr c,enterdigok
        sub 'a'-'0'
        cp 26
        ld c,1+10
        jr c,enterdigok
        sub 'A'-'a'
        cp 26
        ld c,1+10+26
        ccf
        ret c ;wrong digit!
enterdigok
        add a,c
        ld c,a
        ret

enternote
        pop af
        cp 'a'
        jp z,untr_pause
        cp 'f'
        jp z,untr_keygliss

        ld hl,tnotekeys
        ld bc,3*12
        cpir
        ret nz
         inc c ;add c,NOTE_LOWEST
        call pokecurtime_curtrack_c

untr_afternotekey

        call setneedredraw_curtrack
        call updatescr

       ld a,(nowplaying)
        or a
        jr nz,untr_afternotekey_noplay

       ld hl,(curtime)
       ld (playtime),hl
        call inittracks ;в каналах с пустышкой включает паузу, форсирует ретриггер огибающей
        call initnote

playnote0
        halt
        call playnote
        call checknotekeys_pressed
        jr nz,playnote0

        call shutay
untr_afternotekey_noplay
        ;call setneedredraw
curstep=$+1
        ld b,0
        ld a,b
        or a
        ret z
step0
        push bc
        call untr_right
        pop bc
        djnz step0
        ret

untr_keygliss
        ld c,NOTE_GLISS
        jr untr_pauseq
untr_pause
        ld c,NOTE_PAUSE
untr_pauseq
        call pokecurtime_curtrack_c
        jp untr_afternotekey

untr_space
        ld c,NOTE_SPACE
        call pokecurtime_curtrack_c
        jp untr_afternotekey_alltracksiforder

untr_step8
        inc c
untr_step7
        inc c
untr_step6
        inc c
untr_step5
        inc c
untr_step4
        inc c
untr_step3
        inc c
untr_step2
        inc c
untr_step1
        inc c
untr_step0
        ld a,c
        ld (curstep),a
        ret

tracksloop
        ld a,1
        ld (tracksmode),a
tracksloop_nokey
        YIELD
        call updatescr
        ;call prtrackscur
        GET_KEY
        or a
        jr z,tracksloop_nokey
        ;push af
        ;call prtrackscur
        ;pop af
         cp key_tab
         jp z,mainloop
        ld hl,tracksloop
        push hl
        cp key_left
        jp z,tracks_left
        cp key_right
        jp z,tracks_right
        cp key_up
        jp z,untr_up
        cp key_down
        jp z,untr_down
        cp key_ins
        jp z,tracks_ins
        cp key_del
        jp z,tracks_del
        ;push af
        ld hl,(curtrack)
        ld h,0
        add hl,hl
        add hl,hl
        add hl,hl ;*8
tracks_curx=$+1
        ld bc,0
        add hl,bc
        ld bc,ttypes
        add hl,bc
        ;pop af
        call keytodigit ;out: CY=error, a=digit
        ret c
        ld (hl),a
        jp setneedprtypes

tracks_ins
        ld hl,ntracks
        ld a,(hl)
        cp MAXNTRACKS
        ret z
        inc (hl)
;вставить трек в tracks
;если мы на треке a=MAXNTRACKS-2, то надо сдвинуть 4 байта (1 строчку)
;если мы на треке a=MAXNTRACKS-3, то надо сдвинуть 4*2 байта (2 строчки)
;значит, надо сдвинуть MAXNTRACKS-a-1 строчек
        ld a,(curtrack)
        cpl
        add a,MAXNTRACKS
        call amulchnsstep_tohl
        ld b,h
        ld c,l
        ;add a,a
        ;add a,a
        ;ld c,a
        ;ld b,0
        ld hl,tracks_end-1-chnsstep;4
        ld de,tracks_end-1
        lddr
;вставить трек в ttypes
        ld hl,ttypes_end-1-8
        ld de,ttypes_end-1
        ld a,(curtrack)
        cpl
        add a,MAXNTRACKS
        add a,a
        add a,a
        add a,a
        ld c,a
        ;ld b,0
        rl b
        lddr
;сдвинуть roots треков, начиная с curtrack
        ld a,(curtrack)
        ld hl,0x4000+0x3eff
        ld de,0x4000+0x3fff
        cpl
        add a,64;MAXNTRACKS
        ld b,a
        ;ld c,0
        lddr
        inc hl
        ld d,h
        ld e,l
        inc de
        ld (hl),l;0
        dec c ;bc=0x00ff
        ldir

        jp setneedprtracks

tracks_del
        ld hl,ntracks
        ld a,(hl)
        dec a
        ret z
        dec (hl)
;очистить трек
        ld hl,0
        ld ly,0 ;part=0..63
tracks_del0
        ld a,(curtrack)
;ly=part
;a=track
        call getendaddr
        ex de,hl
tracks_del1
        ld a,(curtrack)
        ld c,0 ;c=data
;hl=index
;ly=part
;a=track
;c=data
        call poketrackpartindex_c
        ld a,h
        or l
        dec hl
        jr nz,tracks_del1
        inc ly
        ld a,ly
        cp 64
        jr nz,tracks_del0
       
;удалить трек в tracks
        ld a,(curtrack)
        or a
        ret z ;don't delete order
        ;add a,a
        ;add a,a
        ;ld e,a
        ;ld d,0
        call amulchnsstep_tohl
        ld de,tracks
        add hl,de
        ld d,h
        ld e,l
        ld bc,chnsstep
        add hl,bc
;если мы на треке a=MAXNTRACKS-2, то надо сдвинуть chnsstep байт (1 строчку)
;если мы на треке a=MAXNTRACKS-3, то надо сдвинуть chnsstep*2 байт (2 строчки)
;значит, надо сдвинуть MAXNTRACKS-a-1 строчек
        ld a,(curtrack)
        cpl
        add a,MAXNTRACKS
        ;add a,a
        ;add a,a
        ;ld c,a
        ;ld b,0
        push de
        push hl
        call amulchnsstep_tohl
        ld b,h
        ld c,l
        pop hl
        pop de
        ldir
;удалить трек в ttypes
        ld a,(curtrack)
        add a,a
        add a,a
        add a,a
        ld e,a
        ld d,b;0
        ld hl,ttypes
        add hl,de
        ld d,h
        ld e,l
        ld c,8
        add hl,bc
        ld a,(curtrack)
        cpl
        add a,MAXNTRACKS
        add a,a
        add a,a
        add a,a
        ld c,a
        ;ld b,0
        rl b
        ldir

;сдвинуть roots треков, начиная с curtrack
        ld a,(curtrack)
        add a,0x40
        ld d,a
        inc a
        ld h,a
        ld l,0
        ld e,l;0
        ld a,(curtrack)
        cpl
        add a,64;MAXNTRACKS
        ld b,a
        ;ld c,0
        ldir
       
        call cls
        jp setneedprtracks

tracks_left
        ld hl,tracks_curx
        ld a,(hl)
        or a
        ret z
        dec (hl)
        ret

tracks_right
        ld hl,tracks_curx
        ld a,(hl)
        cp 6;7
        ret z
        inc (hl)
        ret

untr_setplaybegin
        ld hl,(curtime)
        ld (playbegin),hl
        ret

untr_setplayend
        ld hl,(curtime)
        ld (playend),hl
        ret

untr_setplayall
        ld hl,0
        ld (playbegin),hl
        ld (playend),hl
        ret

untr_startplay
startplay
        ld a,1
        ld (nowplaying),a
         ld hl,(curtime)
         ld (playtime),hl
        call initplayer
        call inittracks ;в каналах с пустышкой включает паузу, форсирует ретриггер огибающей
player4000page=$+1
         ld a,0
         ld hl,player
         OS_SETMUSIC
        ret
       
untr_stopplay
stopplay
        xor a
        ld (nowplaying),a
         ld a,(player4000page)
         ld hl,play_reter
         OS_SETMUSIC

        call shutay
        ret

untr_play
        call startplay

        jr playenter0_go
        ;OS_GETTIMER ;out: dehl=timer
        ;ld (playenter_oldtimer),hl
playenter0
;        OS_GETTIMER ;out: dehl=timer
;playenter_oldtimer=$+1
;        ld de,0
;        ld (playenter_oldtimer),hl
       
        ;call untr_right ;TODO check end and loop
        halt
playenter_curxy=$+1
        ld bc,0
          ;call prcur
playenter0_go
        call updatescr
        call getcurplayx
        ld c,a
        call getcury
        ld b,a
        ld (playenter_curxy),bc
          ;call prcur
          ;jr playenter0
        call checknotekeys_pressed
        jr nz,playenter0
         ld hl,(playtime)
         call untr_pgdown_ok

        call stopplay

        jp untr_afternotekey

untr_del_popret
        pop hl
        ret

untr_backspace
        ld hl,(curtime)
        ld a,h
        or l
        ret z
        call untr_left
        ;jp untr_del
untr_del
        ld a,(curtrack)
        ld hl,(curtime)
        call tracktime_totrackpartindex
;hl=index
;ly=part
;a=track
        push hl ;hl=curaddr
        call getendaddr ;de=end or 0
        ex de,hl
        pop de ;de=curaddr
        push hl ;hl=endaddr
        xor a
        sbc hl,de ;endaddr-curaddr
        jr c,untr_del_popret
        ex de,hl
        inc de
;de=число нот до конца трека включительно
;0x0101 - 1 проход
;0x0102 - 2 прохода
;0x0100 - 256 проходов
;0x0201 - 257 проходов
;b=LSB
;hx=HSB = ((num-1)/256)+1
        ld b,e
        dec de
        inc d
        ld hx,d

        pop hl ;hl=endaddr

        ;ld de,-NTRACKS
        ld c,NOTE_SPACE
;hl=index
;ly=part
untr_del0
        push de
        ld a,(curtrack)
        call poketrackpartindex_c ;c<->mem(hl)
        pop de
         dec hl ;add hl,de
        djnz untr_del0
        dec hx
        jr nz,untr_del0

        jp setneedredraw_alltracksiforder

untr_ins
        ld a,(curtrack)
        ld hl,(curtime)
        call tracktime_totrackpartindex
;hl=index
;ly=part
;a=track
        push hl ;hl=curaddr
        push hl ;hl=curaddr
        call getendaddr ;de=end or 0
        ex de,hl
        pop de ;de=curaddr
        or a
        sbc hl,de ;endaddr-curaddr
        jr c,untr_del_popret
        ex de,hl
        inc de
        inc de
;de=число нот до конца трека включительно
;0x0101 - 1 проход
;0x0102 - 2 прохода
;0x0100 - 256 проходов
;0x0201 - 257 проходов
;b=LSB
;hx=HSB = ((num-1)/256)+1
        ld b,e
        dec de
        inc d
        ld hx,d

        pop hl ;hl=curaddr

        ;ld de,NTRACKS
        ld c,NOTE_SPACE
;hl=index
;ly=part
untr_ins0
        push de
        ld a,(curtrack)
        call poketrackpartindex_c ;c<->mem(hl)
        pop de
         inc hl ;add hl,de
        djnz untr_ins0
        dec hx
        jr nz,untr_ins0
        jp setneedredraw_alltracksiforder

untr_quit
        QUIT

checknotekeys_pressed
        ld a,0x81
        in a,(0xfe)
        cpl
        and 0x1f
        ret nz
        ld a,0x7f ;space..B
        in a,(0xfe)
        cpl
        and 0x1c ;BNM
        ret nz
        ld a,0xfe ;cs..V
        in a,(0xfe)
        cpl
        and 0x1e
        ret

untr_home
;переход на начало текущей части
        ld hl,(curtime)
        ld a,(curtrack)
        push hl
        call tracktime_totrackpartindex ;hl=index
        ex de,hl ;de=index
        pop hl
       ld a,d
       or e
       jr z,untr_home_left
untr_home_ok
        or a
        sbc hl,de ;beg=time-index (index=time-beg)
        jp untr_pgdown_ok
untr_home_left
;уже в начале текущей части, пытаемся найти предыдущую
        ld a,h
        or l
        ret z
        dec hl
        ld a,(curtrack)
        push hl
        call tracktime_totrackpartindex ;hl=index
        ex de,hl ;de=index
        pop hl
        jr untr_home_ok

untr_end
;переход на конец текущей части в текущем треке
        ld a,(curtrack)
        ld hl,(curtime)
       push hl ;curtime
        push hl
        call tracktime_totrackpartindex ;hl=index
        ex de,hl ;de=index
        pop hl
        or a
        sbc hl,de ;beg=time-index (index=time-beg)
        push hl ;beg
        call getendaddr ;de=end index
        pop hl ;beg
        add hl,de ;time=index+beg (beg=time-index)
       pop de ;curtime
        or a
        sbc hl,de ;time>curtime?
        add hl,de
        jr c,untr_end_findnext
        jp nz,untr_pgdown_ok
untr_end_findnext
        ex de,hl ;hl=curtime
;уже на конце текущей части в текущем треке
;пытаемся найти следующую часть
        ld a,(curtrack)
        inc hl
        push hl
        call gettrackorder ;номер ордера (0=нет)
        pop hl
        or a ;канал подписан на ордер?
        ret z ;не подписан
        ex de,hl
        xor a ;TODO номер канала ордера
        ld ly,0 ;у ордера всегда берём дефолтную часть (part=0), т.к. ордер не подчиняется ордерам
        call getroot
        call findright ;out: de=nonempty index (or 0xffff), a=data (1..62 or 0)
         ld a,d
         and e
         inc a
         ret z
        ex de,hl
        jp untr_pgdown_ok

untr_up
        ld hl,curtrack
        ld a,(hl)
        or a
        ret z
        dec (hl)
        ld a,(hl)
        ld hl,toptrack
        cp (hl)
        ret nc
        dec (hl)
        ret;jp setneedprtypes ;setneedredraw

setneedredraw_alltracksiforder
        ld a,(curtrack)
        or a
        call z,setneedpralltracks ;keep a!
setneedredraw_curtrack
        ;ld a,1
        ;ld (untr_needredraw),a ;forced redraw (even if lefttime has not changed)
        ld a,(curtrack)
        call amulchnsstep_tohl
        ld de,chns-2;tracks
        add hl,de
        set 7,(hl)
        ret
setneedpralltracks
;keep a!
        ld ix,chns;tracks
        ld a,(ntracks)
        ld b,a
        ld de,chnsstep
setneedpralltracks0
        set 7,(ix-2);(hl)
        add ix,de
        ;inc hl
        ;inc hl
        ;inc hl
        ;inc hl
        djnz setneedpralltracks0
        ;ld a,55 ;"scf"
        ;ld (needpralltracks),a
        ret

untr_down
        ld hl,curtrack
        ld a,(ntracks)
        dec a
        cp (hl)
        ret z
        inc (hl)
        ld c,(hl)
        ld hl,toptrack
        ld a,(hl)
        add a,SCRNTRACKS
        ld b,a
        ld a,c
        cp b
        ret c
        inc (hl)
        ret;jp setneedprtypes;setneedredraw

untr_pgdown
        ld hl,(curtime)
         ;inc hl
         ;inc hl
         ;inc hl
         ;inc hl
         ;inc hl
        ld a,l
        and 0xf8
        ld l,a
        ld bc,8
        add hl,bc
        ret c
        call checkeof
untr_pgdown_ok
        ld (curtime),hl
;установим курсор в центр, если это возможно
        ld bc,SCRTRACKWID/2
        xor a
        sbc hl,bc
        jr nc,$+4
         ld h,a
         ld l,a
        push hl
        add hl,bc
        pop hl
        jr nc,$+5
         ld hl,0x10000-(SCRTRACKWID/2)
        ld (lefttime),hl
        ret

untr_pgup
        ld hl,(curtime)
        ld a,h
        or l
        ret z
        dec hl
         ;dec hl
         ;dec hl
         ;dec hl
         ;dec hl
        ld a,l
        and 0xf8
        ld l,a
        jr untr_pgdown_ok

untr_left
        ld hl,(curtime)
        ld a,h
        or l
        ret z
        dec hl
        ld (curtime),hl
        ld de,(lefttime)
        or a
        sbc hl,de
        add hl,de
        ret nc
        dec de
        ld (lefttime),de
        ret

amulchnsstep_tohl
_=chnsstep
        ld e,a
        ld d,0
        if _&0x80
        ;ld h,d
        ;ld l,e
__=1
        else
        ;ld h,d
        ;ld l,d
__=0
        endif
_=_*2
        dup 7
        if __ != 0
        add hl,hl
__=__*2
        endif
        if _&0x80
        if __ != 0
        add hl,de
        else
        ld h,d
        ld l,e
        endif
__=__+1
        endif
_=_*2
        edup
        ret

getcurplayxonscreen
;out: a=0=offscreen
        call isplayxonscreen
        ld a,0
        ret c
        add hl,bc
        ld a,l
        add a,TRACKX
        ret

isplayxonscreen
;CY=offscreen
        ld hl,(playtime)
        ld bc,(lefttime)
        or a
        sbc hl,bc
        ret c
        ld bc,SCRTRACKWID
        ;or a
        sbc hl,bc
        ccf
        ret

getcurplayx
        push bc
        ld hl,(playtime)
        ld bc,(lefttime)
        or a
        sbc hl,bc
        ld a,l
        add a,TRACKX
        pop bc
;a=x
        ret

getcurx
        push bc
        ld hl,(curtime)
        ld bc,(lefttime)
        or a
        sbc hl,bc
        ld a,l
        add a,TRACKX
        pop bc
;a=x
        ret

getcury
        ld a,(curtrack)
        ld hl,toptrack
        sub (hl)
        inc a
;a=y
        ret

prcurcur
        call getcurx
        ld c,a
        call getcury
        ld b,a
        ld (oldcurxonscreen),bc
        jp prcur

        if 1==0
prtrackscur
        ld a,(tracks_curx)
        ld c,a
        call getcury
        ld b,a
        ld (oldcurxonscreen),bc
        jp prcur
        endif

findsamplelengthandloop
;find sample length and loop line
;hl=sample
;out: e=length, d=loopsize
        ld de,0 ;e=length, d=loopsize
        ld bc,7
findsamplelength0
        inc e ;length = 1..
        add hl,bc
        ld a,(hl)
        inc a
        jr nz,findsamplelength0
        inc hl
        ld c,(hl)
        inc hl
        ld b,(hl)
        add hl,bc
;hl=sampleloop
        ld bc,7
findsampleloop0
        inc d ;loopsize = 1..
        add hl,bc
        ld a,(hl)
        inc a
        jr nz,findsampleloop0
        ret

        include "view.asm"
        include "scroll.asm"
        include "save.asm"

getword
;hl=string
;de=wordbuf
;out: hl=terminator/space addr
getword0
        ld a,(hl)
        or a
        jr z,getwordq
        sub ' '
        jr z,getwordq
        ldi
        jp getword0
getwordq
        ;xor a
        ld (de),a
        ret

skipword
;hl=string
;out: hl=terminator/space addr
skipword0
        ld a,(hl)
        or a
        ret z
        sub ' '
        ret z
        inc hl
        jp skipword0

skipspaces
;hl=string
;out: hl=after last space
        ld a,(hl)
        cp ' '
        ret nz
        inc hl
        jr skipspaces


        macro tn msk,semi,vol,frq,noi
        db msk,semi,0,vol
        dw frq
        db noi
        endm

        macro tne msk,semi,envsemi,vol,frq,noi
        db msk,semi,envsemi,vol
        dw frq
        db noi
        endm

C4ADD=-3353

C8ADD=0x000f-0x0ef8

wassmp_drum
;-0187 01 TN- F (+3353 для орнамента -96)
;-0352 00 T-- E
;-0608 00 T-- D
            ;fsrohENT  ;s ;v ;f       ;n (o=outerenv)
        tn 0b11000011,-96,15,C4ADD+187,1
        tn 0b11000001,-96,15,C4ADD+352,0
        tn 0b11000001,-96,15,C4ADD+608,0
        tn 0b11001000,  0, 0,        0,0
        db -1
        dw -2-SMPLINE ;loop to line with hole
szsmp_drum=$-wassmp_drum

wassmp_hihat
;+0471 05 TN- F (+3353 для орнамента -96)
;+0471 04 TN- D
;+0471 04 -N- C
;+0471 03 -N- B
;+0471 03 -N- A
;+0471 02 -N- 9
;+0471 02 -N- 8
;+0471 01 -N- 7
;+0471 01 -N- 5
;+0471 01 -N- 5
;+0471 01 -N- 4
;+0471 01 -N- 4
;+0471 01 -N- 3
;+0471 01 -N- 3
;+0471 01 -N- 2
;+0471 01 -N- 2
;+0471 01 -N- 1
;+0471 01 -N- 1
            ;fsrohENT  ;s ;v ;f       ;n (o=outerenv)
        tn 0b11000011,-96,15,C4ADD-471,5
        tn 0b11000011,-96,13,C4ADD-471,4
        tn 0b11000010,-96,12,C4ADD-471,4
        tn 0b11000010,-96,11,C4ADD-471,3
        tn 0b11000010,-96,10,C4ADD-471,3
        tn 0b11000010,-96, 9,C4ADD-471,2
        tn 0b11000010,-96, 8,C4ADD-471,2
        tn 0b11000010,-96, 7,C4ADD-471,1
        tn 0b11000010,-96, 5,C4ADD-471,1
        tn 0b11000010,-96, 5,C4ADD-471,1
        tn 0b11000010,-96, 4,C4ADD-471,1
        tn 0b11000010,-96, 4,C4ADD-471,1
        tn 0b11000010,-96, 3,C4ADD-471,1
        tn 0b11000010,-96, 3,C4ADD-471,1
        tn 0b11000010,-96, 2,C4ADD-471,1
        tn 0b11000010,-96, 2,C4ADD-471,1
        tn 0b11000010,-96, 1,C4ADD-471,1
        tn 0b11000010,-96, 1,C4ADD-471,1
        tn 0b11001000,  0, 0,        0,0
        db -1
        dw -2-SMPLINE ;loop to line with hole
szsmp_hihat=$-wassmp_hihat

wassmp_crash ;B-8!!!
;-0000 07 TN- F
;-0000 10 -N- E
;-0000 10 TN- E
;-0000 14 -N- D
;-0000 14 -N- C
;-0000 14 -N- C
;-0000 14 -N- C
;-0000 14 -N- B
;-0000 14 -N- B
;-0000 14 -N- B etc
            ;fsrohENT  ;s ;v ;f       ;n (o=outerenv)
        tn 0b11000011,-96,15,C8ADD+0,7
        tn 0b11000010,-96,14,C8ADD+0,10
        tn 0b11000011,-96,14,C8ADD+0,10
        tn 0b11000010,-96,13,C8ADD+0,14
        tn 0b11000011,-96,12,C8ADD+0,14
        tn 0b11000011,-96,12,C8ADD+0,14
        tn 0b11000011,-96,12,C8ADD+0,14
        tn 0b11000011,-96,11,C8ADD+0,14
        tn 0b11000011,-96,11,C8ADD+0,14
        tn 0b11000011,-96,11,C8ADD+0,14
        tn 0b11000011,-96,10,C8ADD+0,14
        tn 0b11000011,-96,10,C8ADD+0,14
        tn 0b11000011,-96,10,C8ADD+0,14
        tn 0b11000011,-96, 9,C8ADD+0,14
        tn 0b11000011,-96, 9,C8ADD+0,14
        tn 0b11000011,-96, 9,C8ADD+0,14
        tn 0b11000011,-96, 8,C8ADD+0,14
        tn 0b11000011,-96, 8,C8ADD+0,14
        tn 0b11000011,-96, 8,C8ADD+0,14
        tn 0b11000011,-96, 7,C8ADD+0,14
        tn 0b11000011,-96, 7,C8ADD+0,14
        tn 0b11000011,-96, 7,C8ADD+0,14
        tn 0b11000011,-96, 6,C8ADD+0,14
        tn 0b11000011,-96, 6,C8ADD+0,14
        tn 0b11000011,-96, 6,C8ADD+0,14
        tn 0b11000011,-96, 5,C8ADD+0,14
        tn 0b11000011,-96, 5,C8ADD+0,14
        tn 0b11000011,-96, 5,C8ADD+0,14
        tn 0b11000011,-96, 4,C8ADD+0,14
        tn 0b11000011,-96, 4,C8ADD+0,14
        tn 0b11000011,-96, 4,C8ADD+0,14
        tn 0b11000011,-96, 3,C8ADD+0,14
        tn 0b11000011,-96, 3,C8ADD+0,14
        tn 0b11000011,-96, 3,C8ADD+0,14
        tn 0b11000011,-96, 2,C8ADD+0,14
        ;tn 0b11000011,-96, 2,C8ADD+0,14
        ;tn 0b11000011,-96, 2,C8ADD+0,14
        ;tn 0b11000011,-96, 1,C8ADD+0,14
        ;tn 0b11000011,-96, 1,C8ADD+0,14
        ;tn 0b11000011,-96, 1,C8ADD+0,14
        tn 0b11001000,  0, 0,        0,0
        db -1
        dw -2-SMPLINE ;loop to line with hole
szsmp_crash=$-wassmp_crash

wassmp_snare
;-0288 00 TN- F (+3353 для орнамента -96)
;+0202 06 TN- C
;-0512 06 TN- B
;-0970 06 TN- A
;      06 -N- 9
;      06 -N- 8
;      05 -N- 7
;      05 -N- 6
;      05 -N- 5
;      05 -N- 4
;      05 -N- 3
;      05 -N- 2
;      05 -N- 1
            ;fsrohENT  ;s ;v ;f       ;n (o=outerenv)
        tn 0b11000011,-96,15,C4ADD+288,0
        tn 0b11000011,-96,12,C4ADD-202,6
        tn 0b11000011,-96,11,C4ADD+512,6
        tn 0b11000011,-96,10,C4ADD+970,6
        tn 0b00000010,  0, 9,        0,6
        tn 0b00000010,  0, 8,        0,6
        tn 0b00000010,  0, 7,        0,5
        tn 0b00000010,  0, 6,        0,5
        tn 0b00000010,  0, 5,        0,5
        tn 0b00000010,  0, 4,        0,5
        tn 0b00000010,  0, 3,        0,5
        tn 0b00000010,  0, 2,        0,5
        tn 0b00000010,  0, 1,        0,5
wassmp_pause
        tn 0b11001000,  0, 0,        0,0
        db -1
        dw -2-SMPLINE ;loop to line with hole
szsmp_pause=$-wassmp_pause
szsmp_snare=$-wassmp_snare

wassmp_bass
        tne 0b11000100,0,+5*12,0x0e,    0,0
        db -1
        dw -2-SMPLINE ;loop to first line
szsmp_bass=$-wassmp_bass

wassmp_maj
        tn 0b11000001,2*12+0,11,     0,0
        tn 0b11000001,2*12+4,11,     0,0
        tn 0b11000001,2*12+7,11,     0,0
        db -1
        dw wassmp_maj-($+1) ;loop to first line
szsmp_maj=$-wassmp_maj

        macro t4 msk,vol
        db msk|0b11000000,2*12,0,vol,  0,0,0
        endm

wassmp_orn2of6
        tn 0b11001000,  0, 0,        0,0
        tn 0b11001000,  0, 0,        0,0
        tn 0b11001000,  0, 0,        0,0
        tn 0b11001000,  0, 0,        0,0
        tn 0b11000001,2*12+0,15,     0,0
        tn 0b11000001,2*12+0,15,     0,0
        db -1
        dw wassmp_orn2of6-($+1) ;loop to first line
szsmp_orn2of6=$-wassmp_orn2of6

wassmp_orn1of3
        tn 0b11001000,  0, 0,        0,0
        tn 0b11001000,  0, 0,        0,0
        tn 0b11000001,2*12+0,15,     0,0
        db -1
        dw wassmp_orn1of3-($+1) ;loop to first line
szsmp_orn1of3=$-wassmp_orn1of3

wassmp_tone
        t4 0b00000001,15
        t4 0b00000001,14
        t4 0b00000001,14
        t4 0b00000001,14
        t4 0b00000001,14
        t4 0b00000001,13
        t4 0b00000001,13
        t4 0b00000001,13
        t4 0b00000001,13
        t4 0b00000001,12
        t4 0b00000001,12
        t4 0b00000001,12
        t4 0b00000001,12
        t4 0b00000001,11
        t4 0b00000001,11
        t4 0b00000001,11
        t4 0b00000001,11
        t4 0b00000001,10
        t4 0b00000001,10
        t4 0b00000001,10
        t4 0b00000001,10
        t4 0b00000001,9
        t4 0b00000001,9
        t4 0b00000001,9
        t4 0b00000001,9
        t4 0b00000001,8
        t4 0b00000001,8
        t4 0b00000001,8
        t4 0b00000001,8
        t4 0b00000001,7
        t4 0b00000001,7
        t4 0b00000001,7
        t4 0b00000001,7
        t4 0b00001000,0
        db -1
        dw -2-SMPLINE ;loop to line with hole
szsmp_tone=$-wassmp_tone

;A0gO123

;bass, pad и tone имеют параметры:
;сэмпл
;громкость
;смещение в сэмпле
 ;канал [рабочая октава не нужна, она в сэмпле]
 ;приоритет

;drum имеет параметры:
;
;громкость
;[смещение в сэмпле не нужно?]
 ;канал [рабочая октава]
 ;приоритет

;фильтр имеет параметры:
;тип фильтра (d=drum channel, t=tone channel(bass/pad/tone), g=gain, Vv=vib/gliss up/down, Ee=env(vib/gliss up/down), n=noise down)
;для вибрато и глисса: скорость изменения
;для вибрато: глубина (0=бесконечность, т.е. gliss)
;для вибрато: период

;0,0,0,0,1,0,0,0,0,-1
;0,0,0,1,1,0,0,0,-1,-1

tnotekeys
        db "MJNHBGVCDXSZ"
        db "mjnhbgvcdxsz"
        db ssM,ssJ,ssN,ssH,ssB,ssG,ssV,ssC,ssD,ssX,ssS,ssZ
        align 256
wasfrq
        incbin "tb_st.bin"

        ds 0x8000-$
tfrq
        ds 512
        include "mem.asm"
        include "play.asm"
        include "mix.asm"

ttypes
        if OLDTTYPES
        db "ORDER ",13
        db "drum *",13
        db "tone *",13
        db "vib 1*",13
        db "pad  *",13
        db "vol   ",13
         ;db "vol   ",13
        db "drum *",13
        db "tone *",13
        db "vol   ",13
        db "bass *",13
        db "drum *",13
        db "tone *",13
        db "pad  *",13
        db "vol   "
        db 0

        else
;A0gOS2v*
        db  0, 0,_O, 0, 0, 0, 0, 0;"  O     "
        db _A,_5,_d,_O, 0, 0,_f, 0;"A5dO  f "
        db _A,_2,_t,_O,_t, 0,_f, 0;"A2tOt f "
        db  0, 0,_V,_O,_3,_1,_1, 0;"  VO311 "
        db _D,_0,_t,_O,_p, 0,_f, 0;"D0tOp1f "
        db  0, 0,_g, 0, 0, 0, 0, 0;"  g     "
        db _B,_5,_d,_O, 0, 0,_f, 0;"B5dO  f "
        db _B,_2,_t,_O,_t, 0,_f, 0;"B2tOt f "
        db  0, 0,_g, 0, 0, 0, 0, 0;"  g     "
        db _B,_0,_t,_O,_b, 0,_f, 0;"B0tOb f "
        db _C,_5,_d,_O, 0, 0,_f, 0;"C5dO  f "
        db _C,_5,_t,_O,_t, 0,_f, 0;"C2tOt f "
        db _C,_0,_t,_O,_p, 0,_f, 0;"C0tOp1f "
        db  0, 0,_g, 0, 0, 0, 0, 0;"  g     "
        ds ttypes+(MAXNTRACKS*8)-$
ttypes_end
        endif

;смотрим тип текущего канала
gettracktype
        push de
        ld l,a
        ld h,0
        add hl,hl
        add hl,hl
        add hl,hl
        ld de,ttypes+2
        add hl,de
        ld a,(hl)
        pop de
        ret

gettrackorder
        push de
        ld l,a
        ld h,0
        add hl,hl
        add hl,hl
        add hl,hl
        ld de,ttypes+3
        add hl,de
        ld a,(hl)
        pop de
        ret

tracks
chns=tracks+2
        CHNTYPE 0x80+CHNTYPE_ORDER  ,0;,0;-1
        CHNTYPE 0x80+CHNTYPE_SAMPLES,1;,0;Adrum
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Atone
        CHNTYPE 0x80+CHNTYPE_FILTER ,1;,0;Filter_Avib
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Apad
        CHNTYPE 0x80+CHNTYPE_FILTER ,0;,0;Filter_Avol
         ;CHNTYPE 0x80+CHNTYPE_FILTER ,0,0;Filter_Bvol
        CHNTYPE 0x80+CHNTYPE_SAMPLES,1;,0;Bdrum
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Btone
        CHNTYPE 0x80+CHNTYPE_FILTER ,0;,0;Filter_Bvol
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Bbass
        CHNTYPE 0x80+CHNTYPE_SAMPLES,1;,0;Cdrum
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Ctone
        CHNTYPE 0x80+CHNTYPE_NOTES  ,1;,0;Cpad
        CHNTYPE 0x80+CHNTYPE_FILTER ,0;,0;Filter_Cvol
         ;CHNTYPE 0x80+CHNTYPE_FILTER ,0;,0;Filter_Cvol
        ds tracks+(chnsstep*MAXNTRACKS)-$,-1
tracks_end
        ;db -1

emptychn
        chn

chip0
        chip
chip1
        chip


lefttime
        dw 0
playtime
        dw 0
curtime
        dw 0
curtrack
        db 0
toptrack
        db 0
ntracks
        db 14 ;числотреков N

        align 4
freemem_start
cmd_end


        display "Size ",/d,cmd_end-cmd_begin," bytes"

        savebin "untr.com",cmd_begin,cmd_end-cmd_begin

        LABELSLIST "../../us/user.l",1