;-------------------------------------------------------------------------------
; The NinjaTracker V1.0 - 10 rasterline musiceditor.
;
; Cadaver 10/2002
;-------------------------------------------------------------------------------

                processor 6502

ESCBYTE         = $BF

MAX_SONGS       = 16
MAX_PATT        = 128
MAX_PATTLEN     = 192
MAX_SONGLEN     = 256
MAX_TBL         = 255

VISIBLE_ROWS    = 9
VISIBLE_TBLROWS = 9

FAST_KEYREPEAT  = 10
FASTFWD_AMOUNT  = 10

        ;Zeropage

alo             = $02
ahi             = $03
textlo          = $04
texthi          = $05
destlo          = $06
desthi          = $07
editlo          = $08
edithi          = $09
var1            = $0a
var2            = $0b
var3            = $0c
var4            = $0d

songtblsizelo   = $0e
songtblsizehi   = $0f
patttblsizelo   = $10
patttblsizehi   = $11
wavetblsizelo   = $12
wavetblsizehi   = $13
pulsetblsizelo  = $14
pulsetblsizehi  = $15
filttblsizelo   = $16
filttblsizehi   = $17
trackssizelo    = $18
trackssizehi    = $19
pattsizelo      = $1a
pattsizehi      = $1b

songtblloadrlo  = $1c
songtblloadrhi  = $1d
songtblhiadrlo  = $1e
songtblhiadrhi  = $1f
patttblloadrlo  = $20
patttblloadrhi  = $21
patttblhiadrlo  = $22
patttblhiadrhi  = $23
wavetbladrlo    = $24
wavetbladrhi    = $25
pulsetbladrlo   = $26
pulsetbladrhi   = $27
filttbladrlo    = $28
filttbladrhi    = $29
tracksadrlo     = $2a
tracksadrhi     = $2b
pattadrlo       = $2c
pattadrhi       = $2d

numsongs        = $2e
numpatt         = $2f

endadrlo        = $30
endadrhi        = $31



temp1           = $fb
temp2           = $fc
temp3           = $fd
temp4           = $fe
temp5           = $ff


status          = $90
fa              = $ba

        ;Orderlist commands

LOOP            = $00
TRANS           = $80

        ;Pattern commands / note numbers

ENDPATT         = $00
C0              = $01
CIS0            = $02
D0              = $03
DIS0            = $04
E0              = $05
F0              = $06
FIS0            = $07
G0              = $08
GIS0            = $09
A0              = $0a
B0              = $0b
H0              = $0c
C1              = $0d
CIS1            = $0e
D1              = $0f
DIS1            = $10
E1              = $11
F1              = $12
FIS1            = $13
G1              = $14
GIS1            = $15
A1              = $16
B1              = $17
H1              = $18
C2              = $19
CIS2            = $1a
D2              = $1b
DIS2            = $1c
E2              = $1d
F2              = $1e
FIS2            = $1f
G2              = $20
GIS2            = $21
A2              = $22
B2              = $23
H2              = $24
C3              = $25
CIS3            = $26
D3              = $27
DIS3            = $28
E3              = $29
F3              = $2a
FIS3            = $2b
G3              = $2c
GIS3            = $2d
A3              = $2e
B3              = $2f
H3              = $30
C4              = $31
CIS4            = $32
D4              = $33
DIS4            = $34
E4              = $35
F4              = $36
FIS4            = $37
G4              = $38
GIS4            = $39
A4              = $3a
B4              = $3b
H4              = $3c
C5              = $3d
CIS5            = $3e
D5              = $3f
DIS5            = $40
E5              = $41
F5              = $42
FIS5            = $43
G5              = $44
GIS5            = $45
A5              = $46
B5              = $47
H5              = $48
C6              = $49
CIS6            = $4a
D6              = $4b
DIS6            = $4c
E6              = $4d
F6              = $4e
FIS6            = $4f
A6              = $50
B6              = $51
H6              = $52
C7              = $53
CIS7            = $54
D7              = $55
DIS7            = $56
E7              = $57
F7              = $58
FIS7            = $59
G7              = $5a
REST            = $5b
SETWAVE         = $5c
SETAD           = $5d
SETSR           = $5e
SETFILT         = $5f
SETSND          = $60
SND             = $60
DUR             = $101

        ;Kernal routines

scnkey          = $ff9f
getin           = $ffe4
setnam          = $ffbd
setlfs          = $ffba
load            = $ffd5
save            = $ffd8
chrin           = $ffcf
open            = $ffc0
close           = $ffc3
chkin           = $ffc6
chkout          = $ffc9
clrchn          = $ffcc
chrout          = $ffd2
plot            = $fff0

        ;Some keycodes

KEY_F1          = $85
KEY_F3          = $86
KEY_F5          = $87
KEY_F7          = $88
KEY_F8          = $8c
KEY_UP          = $91
KEY_DOWN        = $11
KEY_LEFT        = $9d
KEY_RIGHT       = $1d
KEY_INS         = $94
KEY_DEL         = $14
KEY_BREAK       = $03
KEY_LEFTARROW   = $5f

;-------------------------------------------------------------------------------
; The editor itself
;-------------------------------------------------------------------------------

                org $0800

                dc.b $ff,0,0            ;Cursor sprite
                dc.b $ff,0,0
                dc.b $ff,0,0
                dc.b $ff,0,0
                dc.b $ff,0,0
                dc.b $ff,0,0
                dc.b $ff,0,0
                dc.b $ff,0,0
                ds.b 39,0

                org $0840

                jmp start

;-------------------------------------------------------------------------------
; Music routine
;-------------------------------------------------------------------------------

music:          ldx #$00
initsongnum:    ldy #$00
                bmi chnloop
                txa
                ldx #21
clearloop:      sta chnsongpos-1,x
                dex
                bne clearloop
initloop:       lda songtbllo,y
                sta chnsonglo,x
                lda songtblhi,y
                sta chnsonghi,x
                iny
                dec chncounter,x
                lda chnnext,x
                tax
                bne initloop
                sta temp3
                sta $d417
                lda #$ff
                sta initsongnum+1
                rts

freqmod:        inc chnwavedelay,x
                bne fmnotover
                lda chnwavestored,x
                sta chnwavepos,x
fmnotover:      lda chnfreqlo,x
                clc
                adc chnfreqmodlo,x
                sta chnfreqlo,x
                sta $d400,x
                lda chnfreqhi,x
                adc chnfreqmodhi,x
                jmp setfreqhi

chnloop:        ldy chnwavepos,x
                beq freqmod
                lda wavetbl-1,y
                beq nowavechange
                cmp #$08
                beq hrnote
                bcc legatonote
                cmp #$90
                bcc wavechange
newfreqmod:     sta chnwavedelay,x
                lda nexttbl-1,y
                sta chnwavestored,x
                lda notetbl-1,y
                asl
                sta chnfreqmodlo,x
                lda #$00
                sta chnwavepos,x
                bcc freqmodpos
                lda #$ff
freqmodpos:     asl chnfreqmodlo,x
                rol
                sta chnfreqmodhi,x
                jmp wavedone

hrnote:         sta $d404,x
                lda notetbl-1,y
                sta $d405,x
                lda nexttbl-1,y
                sta $d406,x
                lda #$09
                sta $d404,x
legatonote:     lda wavetbl,y
                beq skippulse
                sta chnpulsepos,x
                lda #$00
                sta chnpulsetime,x
skippulse:      lda notetbl,y
                beq skipfilt
                sta temp3
                lda #$00
                sta temp4
skipfilt:       lda nexttbl,y
                sta chnwavepos,x
                jmp reloadcounter

wavechange:     sta $d404,x
nowavechange:   lda nexttbl-1,y
                sta chnwavepos,x
                lda notetbl-1,y
                asl
                bcs absnote
                adc chnnote,x
absnote:        tay
                lda freqtbl-2,y
                sta chnfreqlo,x
                sta $d400,x
                lda freqtbl-1,y
setfreqhi:      sta $d401,x
                sta chnfreqhi,x
wavedone:       inc chncounter,x
                bne nonewnote

getnewnote:     ldy chnpattnum,x
                lda patttbllo,y
                sta temp1
                lda patttblhi,y
                sta temp2
                ldy chnpattpos,x
                lda (temp1),y
                cmp #$c0                        ;Duration?
                bcc noduration
                sta chnduration,x
                iny
                lda (temp1),y
noduration:     cmp #$60
                bcs notewithwave
                cmp #$5b
                bcc notewithoutwave
                beq rest
command:        and #$07
                cmp #$07
                beq cmdflt
                sta cmdsta+1
                iny
                lda (temp1),y
cmdsta:         sta $d400,x
                bcc rest
cmdflt:         iny
                lda (temp1),y
                sta temp3
                lda #$00
                sta temp4
                bcs rest
notewithoutwave:
                adc chntrans,x
                asl
                sta chnnote,x
                lda chnwavepreset,x
                sta chnwavepos,x
                bne rest
notewithwave:   beq waveonly
                sbc #$61
                adc chntrans,x               ;Adds one too much (C=1)
                asl
                sta chnnote,x
waveonly:       iny
                lda (temp1),y
                sta chnwavepreset,x
                sta chnwavepos,x
rest:           iny
                lda (temp1),y
                beq endpatt
                tya
endpatt:        sta chnpattpos,x
                jmp nextchn

nonewnote:      bmi pulseexec
reloadcounter:
                lda chnpattpos,x
                bne nonewpatt
                lda chnsonglo,x
                sta temp1
                lda chnsonghi,x
                sta temp2
                ldy chnsongpos,x
                lda (temp1),y
                bpl notrans
                sta chntrans,x
                iny
                lda (temp1),y
notrans:        sta chnpattnum,x
                iny
                lda (temp1),y
                beq songloop
noloop:         tya
                jmp loopcommon
songloop:       iny
                lda (temp1),y
loopcommon:     sta chnsongpos,x

nonewpatt:      lda chnduration,x
                sta chncounter,x
                jmp nextchn

pulseexec:      txa
                bne skipfiltexec
                ldy temp3
                beq filttype
                dec temp4
                bmi firstfilt
                bne filtadd
nextfilt:       lda filtnexttbl-1,y
                sta temp3
                tay
firstfilt:      lda filttimetbl-1,y
                bmi setfilt
                sta temp4
                bpl filttype
setfilt:        and #$70
                sta filttype+1
                lda #$01
                sta temp4
                lda filttimetbl-1,y
resonance:      ora #$f0
                sta $d417
                lda filtaddtbl-1,y
                beq filttype
                bne storefilt
filtadd:        lda temp5
                clc
                adc filtaddtbl-1,y
storefilt:      sta temp5
                sta $d416
filttype:       lda #$00
volume:         ora #$0f
                sta $d418
skipfiltexec:   ldy chnpulsepos,x
                beq nextchn
                dec chnpulsetime,x
                bmi firstpulse
                bne pulseadd
nextpulse:      lda pulsenexttbl-1,y
                sta chnpulsepos,x
                tay
firstpulse:     lda pulsetimetbl-1,y
                bmi setpulse
                sta chnpulsetime,x
                jmp nextchn
setpulse:       lda #$01
                sta chnpulsetime,x
                lda pulseaddtbl-1,y
                bne storepulse
pulseadd:       clc
                lda pulseaddtbl-1,y
                adc chnpulse,x
                adc #$00
storepulse:     sta chnpulse,x
                sta $d402,x
                sta $d403,x
nextchn:        lda chnnext,x
                beq chndone
                tax
                jmp chnloop
chndone:        rts

freqtbl:        dc.w $0115,$0125,$0136,$0149,$015c,$0171,$0187,$019f,$01b7,$01d1,$01ed,$020a
                dc.w $022a,$024a,$026d,$0292,$02b9,$02e3,$030f,$033e,$036f,$03a3,$03db,$0415
                dc.w $0454,$0495,$04db,$0525,$0573,$05c7,$061e,$067c,$06de,$0747,$07b6,$082b
                dc.w $08a8,$092b,$09b7,$0a4b,$0ae7,$0b8e,$0c3d,$0cf8,$0dbd,$0e8e,$0f6c,$1057
                dc.w $1150,$1257,$136e,$1496,$15cf,$171c,$187b,$19f0,$1b7b,$1d1d,$1ed8,$20ae
                dc.w $22a0,$24af,$26dd,$292d,$2b9f,$2e38,$30f7,$33e0,$36f6,$3a3b,$3db1,$415d
                dc.w $4540,$495e,$4dbb,$525a,$573f,$5c70,$61ef,$67c1,$6ded,$7476,$7b63,$82ba
                dc.w $8a80,$92bc,$9b76,$a4b4,$ae7f,$b8e0,$c3de,$cf83,$dbda,$e8ed,$f6c7,$ffff

chnsongpos:     dc.b 0
chnpattnum:     dc.b 0
chnpattpos:     dc.b 0
chntrans:       dc.b 0
chncounter:     dc.b 0
chnwavepos:     dc.b 0
chnwavestored:  dc.b 0

                dc.b 0,0,0,0,0,0,0
                dc.b 0,0,0,0,0,0,0

chnwavepreset:  dc.b 1
chnwavedelay:   dc.b 0
chnsonglo:      dc.b 0
chnsonghi:      dc.b 0
chnpulse:       dc.b 0
chnpulsepos:    dc.b 0
chnpulsetime:   dc.b 0

                dc.b 1,0,0,0,0,0,0
                dc.b 1,0,0,0,0,0,0

chnnote:        dc.b 0
chnduration:    dc.b 0
chnfreqlo:      dc.b 0
chnfreqhi:      dc.b 0
chnfreqmodlo:   dc.b 0
chnfreqmodhi:   dc.b 0
chnnext:        dc.b 7

                dc.b 0,0,0,0,0,0,14
                dc.b 0,0,0,0,0,0,0

patttbllo:
N               set patterns
                repeat MAX_PATT
                dc.b <N
N               set N+MAX_PATTLEN
                repend

patttblhi:
N               set patterns
                repeat MAX_PATT
                dc.b >N
N               set N+MAX_PATTLEN
                repend

songtbllo:
N               set orderlists
                repeat MAX_SONGS*3
                dc.b <N
N               set N+MAX_SONGLEN
                repend

songtblhi:
N               set orderlists
                repeat MAX_SONGS*3
                dc.b >N
N               set N+MAX_SONGLEN
                repend

init:           sta inittemp+1
                asl
inittemp:       adc #$00
                sta initsongnum+1
                lda #$00
                sta maxraster
                sta timeframe
                sta timemin
                sta timesec
                sta fastfwd                             
                lda #$01
                sta playflag
                rts

stop:           jsr ep_silence2
                sta playflag
                sta fastfwd
                sta temp3
                sta $d417
                rts

;-------------------------------------------------------------------------------
; Editor
;-------------------------------------------------------------------------------

start:          cld
                lda fa                  ;Find out drive number
                cmp #$08
                bcs driveok
                lda #$08
driveok:        sta drivenumber
                lda #$36                ;Switch off BASIC-rom
                sta $01
                jsr stop
                jsr clearall
                jsr initraster
                jsr initscreen
                jsr drawall
mainloop:       jsr printraster
                jsr getkey
                lda editmode
                asl
                tax
                lda emjumptbl,x
                sta emjump+1
                lda emjumptbl+1,x
                sta emjump+2
emjump:         jsr $0000
                jsr generalkeys
                jmp mainloop

generalkeys:    lda key
                cmp #$21
                bcc gk_noem
                cmp #$28
                bcs gk_noem
                sec
                sbc #$21
                sta editmode
                rts
gk_noem:        cmp #"Z"+$80
                bcc gk_nofastup
                lda #FAST_KEYREPEAT
                sta fastup
                rts
gk_nofastup:    cmp #"X"+$80
                bcc gk_nofastdown
                lda #FAST_KEYREPEAT
                sta fastdown
                rts
gk_nofastdown:  cmp #KEY_F1
                bne gk_noplay
                lda songnum
                jmp init
gk_noplay:      cmp #KEY_F3
                bne gk_nostop
                jmp stop
gk_nostop:      cmp #KEY_F5
                bne gk_noplaypos
                lda songnum
                sei
                jsr init
                jsr music
                lda songstart
                sta chnsongpos
                lda songstart+1
                sta chnsongpos+7
                lda songstart+2
                sta chnsongpos+14
                cli
                rts
gk_noplaypos:   cmp #KEY_F7
                bne gk_nofastfwd
                lda fastfwd
                eor #$01
                sta fastfwd
gk_nofastfwd:   cmp #KEY_F8
                bne gk_nohelp
                jmp onlinehelp
gk_nohelp:      cmp #KEY_LEFTARROW
                bne gk_nodisk
                jmp diskmenu
gk_nodisk:      rts

diskmenu:       jsr stop
                jsr clearscreen
diskmenu2:      lda #$0f
                sta textcolor
                ldx #0
                stx rastercol+1
                ldy #0
                jsr setxy
                lda #<disktext
                sta textlo
                lda #>disktext
                sta texthi
dmloop1:        jsr printtextcont
                inc cursory
                lda cursory
                cmp #10
                bne dmloop1
                ldx #0
                ldy #24
                jsr setxy
                ldx #<devicetext
                ldy #>devicetext
                jsr printtext
                ldx #14
                ldy #24
                jsr setxy
                lda drivenumber
                jsr printhex8
dm_wait:        jsr getkey                
                beq dm_wait
                cmp #"C"
                bne dm_nodrivechg
                lda drivenumber
                clc
                adc #$01
                cmp #$20
                bcc dm_notover
                lda #$08
dm_notover:     sta drivenumber
                jmp diskmenu2
dm_nodrivechg:  cmp #"C"+$80
                bne dm_nodrivechg2
                lda drivenumber
                sec
                sbc #$01
                cmp #$08
                bcs dm_notover2
                lda #$1f
dm_notover2:    sta drivenumber
                jmp diskmenu2
dm_nodrivechg2: cmp #"N"
                beq dm_nuke
                cmp #"X"
                beq dm_exit
                cmp #"L"
                bne dm_noload
                jsr loadsong
                jmp dm_exitmenu
dm_noload:      cmp #"S"
                bne dm_nosave
                jsr savesong
                jmp dm_exitmenu
dm_nosave:      cmp #"E"
                bne dm_noerase
                jsr erasefile
                jmp diskmenu
dm_noerase:     cmp #"D"
                bne dm_nodir
                jsr directory
                jmp diskmenu
dm_nodir:       cmp #"P"
                bne dm_exitmenu
                jsr packrelocate
                jmp dm_exitmenu
dm_exitmenu:    jsr initscreen
                jmp drawall

dm_exit:        jsr confirm
                cmp #"Y"
                beq dm_exit2
                jmp diskmenu2
dm_exit2:       jmp 64738

dm_nuke:        jsr confirm
                cmp #"Y"
                beq dm_nuke2
                jmp diskmenu2
dm_nuke2:       jsr stop
                jsr clearall
                jmp dm_exitmenu


packrelocate:   jsr clearscreen
		lda #$00
                sta rastercol+1
		jsr stop
                lda #$0f
                sta textcolor
                ldx #$00
                ldy #$00
                jsr setxy
                lda #<packtext1
                sta textlo
                lda #>packtext1
                sta texthi
                jsr printtextcont
		ldy #$02
		sty cursory
		jsr printtextcont
dm_packloop:    ldx #14
                stx cursorx
                lda relocadrhi
		jsr printhex8
                ldx #16
		stx cursorx
                lda relocadrlo
		jsr printhex8
dm_packwait:    jsr getkey
                cmp #$00
                beq dm_packwait
                cmp #KEY_UP
                bne dm_pl2not1
                dec relocadrhi
dm_pl2not1:     cmp #KEY_DOWN
                bne dm_pl2not2
                inc relocadrhi
dm_pl2not2:     cmp #KEY_LEFT
                bne dm_pl2not3
                dec relocadrlo
                ldx relocadrlo
                cpx #$ff
                bne dm_pl2not3
                dec relocadrhi
dm_pl2not3:     cmp #KEY_RIGHT
                bne dm_pl2not4
                inc relocadrlo
                bne dm_pl2not4
                inc relocadrhi
dm_pl2not4:     cmp #KEY_BREAK
                beq dm_packabort
                cmp #13
                beq dm_packadrok
		bne dm_packloop
dm_packadrok:   ldx #$00
		ldy #$03
		jsr setxy
                ldx #<packtext3
                ldy #>packtext3
                jsr printtext
dm_packloop2:   ldx #14
		stx cursorx
                lda relocadrzp
		jsr printhex8
dm_packwait2:   jsr getkey
                cmp #$00
                beq dm_packwait2
                cmp #KEY_RIGHT
                bne dm_pl3not1
                dec relocadrzp
dm_pl3not1:     cmp #KEY_LEFT
                bne dm_pl3not2
                inc relocadrzp
dm_pl3not2:     cmp #KEY_BREAK
                beq dm_packabort
                cmp #13
                beq dm_packadrok2
		bne dm_packloop2
dm_packabort:	rts
dm_packadrok2:
                ldy #$80
dm_findoutpatterns:
                lda pattlen-1,y
                bne dm_lastpattfound
                dey
                bne dm_findoutpatterns
dm_lastpattfound:
                tya
                sta numpatt
                sta patttblsizelo
                lda #$00
                sta patttblsizehi
                ldy #15*3
dm_findoutsongs:lda orderlistlen,y
                ora orderlistlen+1,y
                ora orderlistlen+2,y
                bne dm_lastsongfound
                tya
                sec
                sbc #$03
                tay
                jmp dm_findoutsongs
dm_lastsongfound:
                iny
                iny
                iny
                sty numsongs
                tya
                sta songtblsizelo
                lda #$00
                sta songtblsizehi
                lda tablelen
                ldy #3
                jsr mulu
                lda alo
                sta wavetblsizelo
                lda ahi
                sta wavetblsizehi
                lda tablelen+1
                ldy #3
                jsr mulu
                lda alo
                sta pulsetblsizelo
                lda ahi
                sta pulsetblsizehi
                lda tablelen+2
                ldy #3
                jsr mulu
                lda alo
                sta filttblsizelo
                lda ahi
                sta filttblsizehi
                ldy #$00
                sty pattsizelo
                sty pattsizehi
dm_countpattsize:
                lda pattlen,y
                clc
                adc pattsizelo
                sta pattsizelo
                lda pattsizehi
                adc #$00
                sta pattsizehi
                iny
                bpl dm_countpattsize
                ldy #$00
                sty trackssizelo
                sty trackssizehi
dm_counttracksize:
                lda orderlistlen,y
                clc
                adc trackssizelo
                sta trackssizelo
                lda trackssizehi
                adc #$00
                sta trackssizehi
                iny
                cpy #MAX_SONGS*3
                bcc dm_counttracksize

                lda relocadrlo
                clc
                adc #<(vplayerend-vplayerstart)
                sta songtblloadrlo
                lda relocadrhi
                adc #>(vplayerend-vplayerstart)
                sta songtblloadrhi

                lda songtblloadrlo
                clc
                adc songtblsizelo
                sta songtblhiadrlo
                lda songtblloadrhi
                adc songtblsizehi
                sta songtblhiadrhi
                lda songtblhiadrlo
                clc
                adc songtblsizelo
                sta patttblloadrlo
                lda songtblhiadrhi
                adc songtblsizehi
                sta patttblloadrhi

                lda patttblloadrlo
                clc
                adc patttblsizelo
                sta patttblhiadrlo
                lda patttblloadrhi
                adc patttblsizehi
                sta patttblhiadrhi
                lda patttblhiadrlo
                clc
                adc patttblsizelo
                sta wavetbladrlo
                lda patttblhiadrhi
                adc patttblsizehi
                sta wavetbladrhi

                lda wavetbladrlo
                clc
                adc wavetblsizelo
                sta pulsetbladrlo
                lda wavetbladrhi
                adc wavetblsizehi
                sta pulsetbladrhi

                lda pulsetbladrlo
                clc
                adc pulsetblsizelo
                sta filttbladrlo
                lda pulsetbladrhi
                adc pulsetblsizehi
                sta filttbladrhi

                lda filttbladrlo
                clc
                adc filttblsizelo
                sta tracksadrlo
                lda filttbladrhi
                adc filttblsizehi
                sta tracksadrhi

                lda tracksadrlo
                clc
                adc trackssizelo
                sta pattadrlo
                lda tracksadrhi
                adc trackssizehi
                sta pattadrhi

                lda pattadrlo
                clc
                adc pattsizelo
                sta endadrlo
                lda pattadrhi
                adc pattsizehi
                sta endadrhi

                lda endadrlo
                sec
                sbc relocadrlo
                sta var1
                lda endadrhi
                sec
                sbc relocadrhi
                sta var2                        ;Total size

                ldx #$00
                ldy #$05
                jsr setxy
                ldx #<packres1
                ldy #>packres2
                jsr printtext
                inc cursory
                jsr printtextcont
                inc cursory
                jsr printtextcont

                ldx #$0e
                ldy #$05
                jsr setxy
                lda #>(vplayerend-vplayerstart)
                jsr printhex8
                ldx #$10
                stx cursorx
                lda #<(vplayerend-vplayerstart)
                jsr printhex8

                lda var1
                sec
                sbc #<(vplayerend-vplayerstart)
                sta var3
                lda var2
                sbc #>(vplayerend-vplayerstart)
                sta var4

                ldx #$0e
                ldy #$06
                jsr setxy
                lda var4
                jsr printhex8
                ldx #$10
                stx cursorx
                lda var3
                jsr printhex8

                ldx #$0e
                ldy #$07
                jsr setxy
                lda var2
                jsr printhex8
                ldx #$10
                stx cursorx
                lda var1
                jsr printhex8

                jsr askname
                lda namelength
                bne dm_packnameok
                rts
dm_packnameok:  lda $d011
                and #$0f
                sta $d011
dm_packwaitscreen:
                lda $d011
                bpl dm_packwaitscreen

                ldx #$00
dm_copyplayer:  lda vplayerstart,x
                sta $0400,x
                lda vplayerstart+$100,x
                sta $0500,x
                lda vplayerstart+$200,x
                sta $0600,x
                lda vplayerstart+$300,x
                sta $0700,x
                inx
                bne dm_copyplayer

                lda #$00                ;Now perform the relocation itself
                sta destlo
                lda #$04
                sta desthi
dm_relocate:    ldy #$00                ;Get the instruction
                lda (destlo),y
                bne dm_notrelocdone     ;Zero=done
                jmp dm_relocdone
dm_notrelocdone:sta dm_compare+1
                lda #<asmtable
                sta textlo
                lda #>asmtable
                sta texthi
dm_searchasm:   lda (textlo),y
                cmp #$ff                ;$ff=end of table, something went
                bne dm_compare          ;wrong!
dm_eternity:    inc $d020
                jmp dm_eternity
dm_compare:     cmp #$00
                beq dm_asmfound
                clc
                lda textlo
                adc #$02
                sta textlo
                lda texthi
                adc #$00
                sta texthi
                jmp dm_searchasm
dm_asmfound:    ldy #$01
                lda (textlo),y          ;Get size of instruction
                beq dm_zeropage
                cmp #$03                ;3-byte instructions must be relocated
                beq dm_absolute
dm_nextasm:     clc
                adc destlo
                sta destlo
                lda desthi              ;Else we go on
                adc #$00
                sta desthi
                jmp dm_relocate
dm_zeropage:    lda (destlo),y
                clc
                adc relocadrzp
                sta (destlo),y
                lda #$02
                bne dm_nextasm
dm_absdone:     lda #$03
                jmp dm_nextasm
dm_absolute:    ldy #$02                ;Get highbyte of the address
                lda (destlo),y          ;which determines the type of the
                cmp #$d4                ;relocation, but if it is a SID-chip
                beq dm_absdone          ;reference then skip it!
                asl
                tax
                lda dm_reljmptbl-2,x
                sta dm_reljmp+1
                lda dm_reljmptbl-1,x
                sta dm_reljmp+2
dm_reljmp:      jmp $0000
dm_relocdone:   jsr savecommon
                lda relocadrlo          ;Write startaddress first
                jsr save_sendbyte
                lda relocadrhi
                jsr save_sendbyte
                lda #$00
                sta destlo
                lda #$04
                sta desthi
dm_saveplr:     ldy #$00
                lda (destlo),y
                jsr save_sendbyte
                inc destlo
                bne dm_splok
                inc desthi
dm_splok:       lda destlo
                cmp #<($0400+vplayerend-vplayerstart)
                bne dm_saveplr
                lda desthi
                cmp #>($0400+vplayerend-vplayerstart)
                bne dm_saveplr
                ldy #$00
                lda tracksadrlo
                sta textlo
dm_savesongtbllo:
                lda textlo
                jsr save_sendbyte
                lda textlo
                clc
                adc orderlistlen,y
                sta textlo
                iny
                cpy numsongs
                bcc dm_savesongtbllo
                ldy #$00
                lda tracksadrlo
                sta textlo
                lda tracksadrhi
                sta texthi
dm_savesongtblhi:
                lda texthi
                jsr save_sendbyte
                lda textlo
                clc
                adc orderlistlen,y
                sta textlo
                lda texthi
                adc #$00
                sta texthi
                iny
                cpy numsongs
                bcc dm_savesongtblhi
                ldy #$00
                lda pattadrlo
                sta textlo
dm_savepatttbllo:
                lda textlo
                jsr save_sendbyte
                lda textlo
                clc
                adc pattlen,y
                sta textlo
                iny
                cpy numpatt
                bcc dm_savepatttbllo
                ldy #$00
                lda pattadrlo
                sta textlo
                lda pattadrhi
                sta texthi
dm_savepatttblhi:
                lda texthi
                jsr save_sendbyte
                lda textlo
                clc
                adc pattlen,y
                sta textlo
                lda texthi
                adc #$00
                sta texthi
                iny
                cpy numpatt
                bcc dm_savepatttblhi
                lda #<wavetbl
                ldx #>wavetbl
                ldy tablelen
                jsr dm_savetable
                lda #<notetbl
                ldx #>notetbl
                ldy tablelen
                jsr dm_savetable
                lda #<nexttbl
                ldx #>nexttbl
                ldy tablelen
                jsr dm_savetable
                lda #<pulsetimetbl
                ldx #>pulsetimetbl
                ldy tablelen+1
                jsr dm_savetable
                lda #<pulseaddtbl
                ldx #>pulseaddtbl
                ldy tablelen+1
                jsr dm_savetable
                lda #<pulsenexttbl
                ldx #>pulsenexttbl
                ldy tablelen+1
                jsr dm_savetable
                lda #<filttimetbl
                ldx #>filttimetbl
                ldy tablelen+2
                jsr dm_savetable
                lda #<filtaddtbl
                ldx #>filtaddtbl
                ldy tablelen+2
                jsr dm_savetable
                lda #<filtnexttbl
                ldx #>filtnexttbl
                ldy tablelen+2
                jsr dm_savetable
                lda #$00
                sta var1
dm_savetrackloop:
                ldy var1
                lda songtbllo,y
                sta textlo
                lda songtblhi,y
                sta texthi
                lda orderlistlen,y
                sta var2
                ldy #$00
dm_savetrackloop2:
                lda (textlo),y
                jsr save_sendbyte
                iny
                cpy var2
                bcc dm_savetrackloop2
                inc var1
                lda var1
                cmp numsongs
                bcc dm_savetrackloop
                lda #$00
                sta var1
dm_savepattloop:ldy var1
                lda patttbllo,y
                sta textlo
                lda patttblhi,y
                sta texthi
                lda pattlen,y
                sta var2
                ldy #$00
dm_savepattloop2:
                lda (textlo),y
                jsr save_sendbyte
                iny
                cpy var2
                bcc dm_savepattloop2
                inc var1
                lda var1
                cmp numpatt
                bcc dm_savepattloop
                jmp load_error

dm_savetable:   sta textlo
                stx texthi
                sty var2
                ldy #$00
dm_stloop:      lda (textlo),y
                jsr save_sendbyte
                iny
                cpy var2
                bcc dm_stloop
                rts

dm_reljmptbl:   dc.w relplayer
                dc.w relplayer
                dc.w relplayer
                dc.w relplayer
                dc.w relsongtbllo
                dc.w relsongtblhi
                dc.w relpatttbllo
                dc.w relpatttblhi
                dc.w relwavetimetbl
                dc.w relwavenotetbl
                dc.w relwavenexttbl
                dc.w relpulsetimetbl
                dc.w relpulseaddtbl
                dc.w relpulsenexttbl
                dc.w relfilttimetbl
                dc.w relfiltaddtbl
                dc.w relfiltnexttbl

subdest:        ldy #$01
                sta var1
                stx var2
                lda (destlo),y
                sec
                sbc var1
                sta (destlo),y
                iny
                lda (destlo),y
                sbc var2
                sta (destlo),y
                rts

adddest:        ldy #$01
                stx var1
                clc
                adc (destlo),y
                sta (destlo),y
                iny
                lda (destlo),y
                adc var1
                sta (destlo),y
                rts

relplayer:      lda #<$100
                ldx #>$100
                jsr subdest
                lda relocadrlo
                ldx relocadrhi
                jsr adddest
                jmp dm_absdone

relsongtbllo:   lda #<vsongtbllo
                ldx #>vsongtbllo
                jsr subdest
                lda songtblloadrlo
                ldx songtblloadrhi
                jsr adddest
                jmp dm_absdone

relsongtblhi:   lda #<vsongtblhi
                ldx #>vsongtblhi
                jsr subdest
                lda songtblhiadrlo
                ldx songtblhiadrhi
                jsr adddest
                jmp dm_absdone

relpatttbllo:   lda #<vpatttbllo
                ldx #>vpatttbllo
                jsr subdest
                lda patttblloadrlo
                ldx patttblloadrhi
                jsr adddest
                jmp dm_absdone

relpatttblhi:   lda #<vpatttblhi
                ldx #>vpatttblhi
                jsr subdest
                lda patttblhiadrlo
                ldx patttblhiadrhi
                jsr adddest
                jmp dm_absdone

relwavetimetbl: lda #<(vwavetbl)
                ldx #>(vwavetbl)
                jsr subdest
                lda wavetbladrlo
                ldx wavetbladrhi
                jsr adddest
                jmp dm_absdone

relwavenotetbl: lda #<(vnotetbl)
                ldx #>(vnotetbl)
                jsr subdest
                lda wavetbladrlo
                ldx wavetbladrhi
                jsr adddest
                lda tablelen
                ldx #$00
                jsr adddest
                jmp dm_absdone

relwavenexttbl: lda #<(vnexttbl)
                ldx #>(vnexttbl)
                jsr subdest
                lda wavetbladrlo
                ldx wavetbladrhi
                jsr adddest
                lda tablelen
                ldx #$00
                jsr adddest
                lda tablelen
                jsr adddest
                jmp dm_absdone

relpulsetimetbl:lda #<(vpulsetimetbl)
                ldx #>(vpulsetimetbl)
                jsr subdest
                lda pulsetbladrlo
                ldx pulsetbladrhi
                jsr adddest
                jmp dm_absdone

relpulseaddtbl: lda #<(vpulseaddtbl)
                ldx #>(vpulseaddtbl)
                jsr subdest
                lda pulsetbladrlo
                ldx pulsetbladrhi
                jsr adddest
                lda tablelen+1
                ldx #$00
                jsr adddest
                jmp dm_absdone

relpulsenexttbl:lda #<(vpulsenexttbl)
                ldx #>(vpulsenexttbl)
                jsr subdest
                lda pulsetbladrlo
                ldx pulsetbladrhi
                jsr adddest
                lda tablelen+1
                ldx #$00
                jsr adddest
                lda tablelen+1
                jsr adddest
                jmp dm_absdone

relfilttimetbl:
                lda #<(vfilttimetbl)
                ldx #>(vfilttimetbl)
                jsr subdest
                lda filttbladrlo
                ldx filttbladrhi
                jsr adddest
                jmp dm_absdone

relfiltaddtbl:  lda #<(vfiltaddtbl)
                ldx #>(vfiltaddtbl)
                jsr subdest
                lda filttbladrlo
                ldx filttbladrhi
                jsr adddest
                lda tablelen+2
                ldx #$00
                jsr adddest
                jmp dm_absdone

relfiltnexttbl:
                lda #<(vfiltnexttbl)
                ldx #>(vfiltnexttbl)
                jsr subdest
                lda filttbladrlo
                ldx filttbladrhi
                jsr adddest
                lda tablelen+2
                ldx #$00
                jsr adddest
                lda tablelen+2
                jsr adddest
                jmp dm_absdone

confirm:        ldx #0
                ldy #24
                jsr setxy
                ldx #<confirmtext
                ldy #>confirmtext
                jsr printtext
confirm_getkey: jsr getkey
                cmp #$00
                beq confirm_getkey
                pha
                lda #$20
                ldx #39
confirm2:       sta $400+24*40,x
                dex
                bpl confirm2
                pla
                rts

onlinehelp:     lda #$00
                sta rastercol+1
                jsr clearscreen
                lda #<onlinehelptext
                sta textlo
                lda #>onlinehelptext
                sta texthi
                ldx #$00
                lda #$0f
ohr_setcolors:  sta $d800,x
                sta $d900,x
                sta $da00,x
                sta $db00,x
                inx
                bne ohr_setcolors
oh_redraw:      sei
                lda #$34
                sta $01
                ldy #$00
ohr_loop1:      lda (textlo),y
                cmp #96
                bcc ohr_nolower1
                sbc #96
ohr_nolower1:   sta $0400,y
                iny
                bne ohr_loop1
                inc texthi
ohr_loop2:      lda (textlo),y
                cmp #96
                bcc ohr_nolower2
                sbc #96
ohr_nolower2:   sta $0500,y
                iny
                bne ohr_loop2
                inc texthi
ohr_loop3:      lda (textlo),y
                cmp #96
                bcc ohr_nolower3
                sbc #96
ohr_nolower3:   sta $0600,y
                iny
                bne ohr_loop3
                inc texthi
ohr_loop4:      lda (textlo),y
                cmp #96
                bcc ohr_nolower4
                sbc #96
ohr_nolower4:   sta $0700,y
                iny
                bne ohr_loop4
                lda texthi
                sec
                sbc #$03
                sta texthi
                lda #$36
                sta $01
                cli
oh_keyloop:     jsr getkey             
                cmp #KEY_UP
                bne oh_notup
                lda textlo
                cmp #<onlinehelptext
                bne oh_upok
                lda texthi
                cmp #>onlinehelptext
                bne oh_upok
                jmp oh_keyloop
oh_upok:        lda textlo
                sec
                sbc #40
                sta textlo
                lda texthi
                sbc #$00
                sta texthi
                jmp oh_redraw
oh_notup:       cmp #KEY_DOWN
                bne oh_notdown
                lda textlo
                cmp #<onlinehelpend
                bne oh_downok
                lda texthi
                cmp #>onlinehelpend
                bne oh_downok
                jmp oh_keyloop
oh_downok:      lda textlo
                clc
                adc #40
                sta textlo
                lda texthi
                adc #$00
                sta texthi
                jmp oh_redraw
oh_notdown:     cmp #$20
                beq oh_quit
                cmp #13
                beq oh_quit
                cmp #KEY_F8
                beq oh_quit
                bne oh_keyloop
oh_quit:        jsr initscreen
                jmp drawall


editpattern:    jsr patttowork
                lda pattrow
                sec
                sbc pattview
                clc
                adc #$03
                tay
                ldx pattcol
                lda pattcoltbl,x
                tax
                lda #$00
                cpx #30
                bne ep_nobigcursor
                lda #$ff
ep_nobigcursor: jsr cursorpos
                ldx pattrow
                lda key
                cmp #KEY_LEFT
                bne ep_notleft
                dec pattcol
                bpl ep_done
                lda #$04
                sta pattcol
                jmp ep_up
ep_done:        jsr worktopatt
                jmp drawpattern
ep_notleft:     cmp #KEY_RIGHT
                bne ep_notright
ep_right:       inc pattcol
                lda pattcol
                cmp #$05
                bcc ep_done
                lda #$00
                sta pattcol
                jmp ep_down
ep_notright:    cmp #KEY_UP
                bne ep_notup
ep_up:          lda pattrow
                beq ep_done
                dec pattrow
                lda pattrow
                cmp pattview
                bcs ep_done
                dec pattview
                jmp ep_done
ep_notup:       cmp #KEY_DOWN
                bne ep_notdown
ep_down:        lda pattrow
                cmp workpattlen
                bcc ep_downok
                jmp ep_done
ep_downok:      inc pattrow
                lda pattrow
                sec
                sbc pattview
                cmp #VISIBLE_ROWS
                bcc ep_done
                inc pattview
                jmp ep_done
ep_notdown:     ldy pattcol
                bne ep_nonote
                ldy #19
ep_checknote:   cmp notekeytbl,y
                beq ep_notefound
                dey
                bpl ep_checknote
                bmi ep_nonote
ep_notefound:   tya
                cmp #16
                bcs ep_cmd
                adc #$01
                sta workpattnote,x
                lda octave
                ldy #12
                jsr mulu
                lda alo
                clc
                adc workpattnote,x
                cmp #$5a
                bcc ep_noteok
                lda #$5a
ep_noteok:      sta workpattnote,x
                jsr ep_checklength
                jmp ep_testnote
ep_nonote:      cmp #$20
                bne ep_nospace
                jsr ep_silence
                ldy pattcol
                beq ep_rest
                cpy #3
                bcs ep_cleardur
ep_clearwave:   lda #$00
                sta workpattwave,x
                jmp ep_done
ep_cleardur:    lda #$00
                sta workpattdur,x
                jmp ep_done
ep_rest:        lda #$5b
                sta workpattnote,x
                jsr ep_checklength
                jmp ep_done
ep_cmd:         clc
                adc #$4c
                sta workpattnote,x
                jsr ep_checklength
                jmp ep_done
ep_nospace:     cmp #":"
                beq ep_prevpatt
                cmp #";"
                beq ep_nextpatt
                bne ep_nopattchg
ep_prevpatt:    dec pattnum
ep_pattchgcommon:
                lda pattnum
                and #$7f
                sta pattnum
                lda #$00
                sta pattrow
                sta pattview
                jsr patttowork
                jsr ep_checktestwav
                jsr worktopatt
                jmp drawpattern
ep_nextpatt:    inc pattnum
                jmp ep_pattchgcommon
ep_nopattchg:   cmp #KEY_INS
                bne ep_noinsert
                lda pattrow
                sta var3
                cmp #MAX_PATTLEN-2
                bcs ep_insdone
                ldy #MAX_PATTLEN-2
ep_insloop:     lda workpattnote,y
                sta workpattnote+1,y
                lda workpattwave,y
                sta workpattwave+1,y
                lda workpattdur,y
                sta workpattdur+1,y
                cpy #$00
                beq ep_insdone2
                dey
                cpy var3
                bcs ep_insloop
ep_insdone2:    ldy pattrow
                lda workpattnote,y
                bne ep_insdone
                sta workpattwave,y
                sta workpattdur,y
                lda #REST
                sta workpattnote,y
ep_insdone:     jmp ep_done
ep_noinsert:    cmp #KEY_DEL
                bne ep_nodelete
                lda pattrow
                cmp workpattlen
                bcs ep_deldone
                tay
ep_delloop:     lda workpattnote+1,y
                sta workpattnote,y
                lda workpattwave+1,y
                sta workpattwave,y
                lda workpattdur+1,y
                sta workpattdur,y
                iny
                cpy #MAX_PATTLEN-1
                bcc ep_delloop
ep_deldone:     jmp ep_done
ep_nodelete:    cmp #"N"+$80
                bne ep_notransdown
                ldy #$00
ep_transdown:   lda workpattnote,y
                beq ep_transdowndone
                cmp #$01
                beq ep_transdownskip
                cmp #$5b
                bcs ep_transdownskip
                sec
                sbc #$01
                sta workpattnote,y
ep_transdownskip:
                iny
                bne ep_transdown
ep_transdowndone:
                jmp ep_done
ep_notransdown: cmp #"M"+$80
                bne ep_notransup
                ldy #$00
ep_transup:     lda workpattnote,y
                beq ep_transupdone
                cmp #$5a
                bcs ep_transupskip
                adc #$01
                sta workpattnote,y
ep_transupskip: iny
                bne ep_transup
ep_transupdone  jmp ep_done
ep_notransup:   cmp #13
                bne ep_noenter
                jsr ep_silence
                lda pattcol
                cmp #1
                bcc ep_noenter2
                cmp #3
                bcs ep_noenter2
                ldy pattrow
                lda workpattnote,y
                cmp #$5f
                beq ep_enterfilt
                cmp #$5c
                bcs ep_noenter2
                lda workpattwave,y
                beq ep_noenter2
                sec
                sbc #$01
                cmp tablelen
                bcs ep_noenter2
                sta tablerow
                sta tableview
                lda #$04
                sta editmode
                lda #$00
                jmp drawtable
ep_enterfilt: lda workpattwave,y
                beq ep_noenter2
                sec
                sbc #$01
                cmp tablelen+2
                bcs ep_noenter2
                sta tablerow+2
                sta tableview+2
                lda #$06
                sta editmode
                lda #$02
                jmp drawtable
ep_noenter2:    rts
ep_noenter:     cmp #"C"+$80
                bne ep_nocopy
                lda pattnum
                beq ep_noenter2
                jsr getpattadr
                ldy #$00
ep_pattloop:    lda (editlo),y
                sta copybuffer,y
                iny
                cpy #MAX_PATTLEN
                bcc ep_pattloop
                rts
ep_nocopy:      cmp #"V"+$80
                bne ep_nopaste
                lda pattnum
                beq ep_noenter2
                jsr getpattadr
                ldy #$00
ep_pattloop2:   lda copybuffer,y
                sta (editlo),y
                iny
                cpy #MAX_PATTLEN
                bcc ep_pattloop2
                jsr patttowork
                jsr ep_checktestwav
                jsr worktopatt
                jmp drawpattern
ep_nopaste:     jsr gethex
                bmi ep_nohex
                jmp ep_hex
ep_nohex:       rts

ep_setoctave:   cmp #$08
                bcs ep_hexquit
                sta octave
                lda workpattnote,x
                cmp #$5b
                bcs ep_nohex
                sec
                sbc #$01
                ldy #$0c
                jsr divu
                sta var1
                lda #$0c
                ldy octave
                jsr mulu
                lda alo
                clc
                adc var1
                adc #$01
                cmp #$5a
                bcc ep_octaveok
                lda #$5a
ep_octaveok:    sta workpattnote,x
                jmp ep_testnote

ep_hex:         ldx pattrow
                cpx workpattlen
                bcc ep_hexok
ep_hexquit:     rts
ep_hexok:       ldy pattcol
                beq ep_setoctave
                cpy #3
                bcs ep_setdur
ep_setwave:     cpy #1
                beq ep_waveleft
                lda workpattwave,x
                and #$f0
                ora hexdigit
                sta workpattwave,x
                jmp ep_right
ep_waveleft:    asl hexdigit
                asl hexdigit
                asl hexdigit
                asl hexdigit
                lda workpattwave,x
                and #$0f
                ora hexdigit
                sta workpattwave,x
                jmp ep_right
ep_setdur:      lda hexdigit
                cmp #$0a
                bcc ep_sdok
                jmp ep_done
ep_sdok:        cpy #4
                bne ep_durleft
                lda workpattdur,x
                and #$f0
                ora hexdigit
                sta workpattdur,x
                jmp ep_durcommon
ep_durleft:     asl hexdigit
                asl hexdigit
                asl hexdigit
                asl hexdigit
                lda workpattdur,x
                and #$0f
                ora hexdigit
                sta workpattdur,x
ep_durcommon:   lda workpattdur,x
                cmp #$65
                bcc ep_durok1
                lda #$65
ep_durok1:      cmp #$02
                bcs ep_durok2
                lda #$02
ep_durok2:      sta workpattdur,x
                jmp ep_right

ep_checktestwav:lda workpattnote
                cmp #$5b
                bcs ep_ctwdone
                lda workpattwave
                beq ep_ctwdone
                sta lasttestwav
ep_ctwdone:     rts

ep_checklength: cpx workpattlen
                bne ep_notlast
                lda #$00
                sta workpattnote+1,x
                sta workpattwave+1,x
                sta workpattdur+1,x
ep_notlast:     rts

ep_testnote:    lda playflag
                bne ep_notestnote
                sei
                ldy testchn
                lda workpattwave,x
                beq ep_nonewwave
                sta lasttestwav
ep_nonewwave:   lda lasttestwav
                sta chnwavepos,y
                lda workpattnote,x
                asl
                sta chnnote,y
                lda #$00
                sta chntrans,y
                cli
ep_notestnote:  jmp ep_done

ep_silence:     lda playflag
                bne ep_nosilence
ep_silence2:    sei
                lda #$80
                sta chncounter
                sta chncounter+7
                sta chncounter+14
                lda #$00
                sta $d404
                sta $d404+7
                sta $d404+14
                sta chnwavepos
                sta chnwavepos+7
                sta chnwavepos+14
                sta chnwavestored
                sta chnwavestored+7
                sta chnwavestored+14
                cli
ep_nosilence:   rts

edittable:      lda editmode
                sec
                sbc #$04
                sta var1
                tax
                jsr gettableadr
                lda editlo
                sta textlo
                lda edithi
                sta texthi
                lda tablebyte,x
                clc
                adc edithi
                sta edithi
                lda tablerow,x
                sec
                sbc tableview,x
                adc #13
                pha
                txa
                ldy #14
                jsr mulu
                lda tablebyte,x
                asl
                adc tablebyte,x
                adc tablecol
                adc alo
                adc #$03
                tax
                pla
                tay
                lda #$00
                jsr cursorpos
                ldx var1
                jsr gethex
                bmi eta_nohex
                lda tablecol
                ldy editmode                    ;Nybbles reversed in pulse
                cpy #$05                        ;table
                bne eta_noreverse
                ldy tablebyte,x
                cpy #$01
                bne eta_noreverse
                eor #$01
eta_noreverse:  cmp #$00
                beq eta_leftdigit
                ldy tablerow,x
                lda (editlo),y
                and #$f0
                ora hexdigit
                sta (editlo),y
                jmp eta_digitcommon
eta_leftdigit:  ldy tablerow,x
                asl hexdigit
                asl hexdigit
                asl hexdigit
                asl hexdigit
                lda (editlo),y
                and #$0f
                ora hexdigit
                sta (editlo),y
eta_digitcommon:lda tablerow,x
                cmp tablelen,x
                bne eta_digitdone
                inc tablelen,x
                lda var1
                jsr gettableadr
                lda tablerow,x
                tay
                clc
                adc #$02
                inc edithi
                inc edithi
                sta (editlo),y
eta_digitdone:  jmp eta_right
eta_done:       lda editmode
                sec
                sbc #$04
                jmp drawtable
eta_nohex:      lda key
                cmp #KEY_LEFT
                bne eta_notleft
                lda tablecol
                eor #$01
                sta tablecol
                beq eta_done
                dec tablebyte,x
                bpl eta_done
                lda #$02
                sta tablebyte,x
                jmp eta_up
eta_notleft:    cmp #KEY_RIGHT
                bne eta_notright
eta_right:      lda tablecol
                eor #$01
                sta tablecol
                bne eta_done
                inc tablebyte,x
                lda tablebyte,x
                cmp #$03
                bcc eta_done
                lda #$00
                sta tablebyte,x
                beq eta_down
eta_notright:   cmp #KEY_DOWN
                bne eta_notdown
eta_down:       lda tablerow,x
                cmp tablelen,x
                bcc eta_downok
                jmp eta_done
eta_downok:     inc tablerow,x
                lda tablerow,x
                sec
                sbc tableview,x
                cmp #VISIBLE_TBLROWS
                bcc eta_done
                inc tableview,x
                jmp eta_done
eta_notdown:    cmp #KEY_UP
                bne eta_notup
eta_up:         lda tablerow,x
                bne eta_upok
                rts
eta_upok:       dec tablerow,x
                lda tablerow,x
                cmp tableview,x
                bcs eta_done
                dec tableview,x
                jmp eta_done
eta_notup:      cmp #KEY_DEL
                beq eta_delete
                jmp eta_nodelete
eta_delete:     txa
                jsr gettableadr
                lda tablerow,x
                cmp tablelen,x
                bcc eta_delok
                jmp eta_done
eta_delok:      dec tablelen,x
                tay
eta_delloop:    iny
                beq eta_deldone
                lda (editlo),y
                dey
                sta (editlo),y
                iny
                inc edithi
                lda (editlo),y
                dey
                sta (editlo),y
                iny
                inc edithi
                lda (editlo),y
                dey
                sta (editlo),y
                dec edithi
                dec edithi
                iny
                bne eta_delloop
eta_deldone:    lda #$00
                ldy #$ff
                sta (editlo),y
                inc edithi
                sta (editlo),y
                inc edithi
                sta (editlo),y
                lda #$ff
                jsr eta_adjustjumps
                jmp eta_done

eta_nodelete:   cmp #KEY_INS
                bne eta_noinsert
                txa
                jsr gettableadr
                lda tablerow,x
                sta var3
                cmp #$fe
                bcs eta_insdone
                inc tablelen,x
                ldy #$fe
eta_insloop:    lda (editlo),y
                iny
                sta (editlo),y
                dey
                inc edithi
                lda (editlo),y
                iny
                sta (editlo),y
                dey
                inc edithi
                lda (editlo),y
                iny
                sta (editlo),y
                dec edithi
                dec edithi
                dey
                cpy var3
                beq eta_insdone
                dey
                jmp eta_insloop
eta_insdone:    ldy var3
                lda #$00
                sta (editlo),y
                inc edithi
                inc edithi
                lda #$01
                jsr eta_adjustjumps
                lda editmode
                sec
                sbc #$04
                tax
                jsr gettableadr
                ldy tablerow,x
                lda #$00
                sta (editlo),y
                inc edithi
                sta (editlo),y
                inc edithi
                tya
                clc
                adc #$02
                sta (editlo),y
                jmp eta_done
eta_noinsert:   rts

eta_adjustjumps:sta var2
                lda tablerow,x
                clc
                adc #$01
                sta var3
                ldy #$00
eta_ajloop:     lda editmode                    ;When in the wave table,
                cmp #$04
                bne eta_ajcheck
                lda (textlo),y                  ;watch out for noteinit cmd.
                beq eta_ajcheck
                cmp #$09
                bcc eta_ajskip
eta_ajcheck:    lda (editlo),y
                cmp var3
                beq eta_ajnot
                bcc eta_ajnot
                clc
                adc var2
                sta (editlo),y
eta_ajnot:      iny
                bne eta_ajloop
                lda editmode
                cmp #$04                        ;Wavetable?
                bne eta_ajdone
                lda #$01                        ;Must "relocate" wave
                sta var4                        ;references in all patterns!
eta_ajpattloop: ldy var4
                lda patttbllo,y
                sta destlo
                lda patttblhi,y
                sta desthi
                ldy #$00
eta_ajpattloop2:lda (destlo),y
                beq eta_ajpattdone
                cmp #$c0
                bcc eta_ajpattnodur
                iny
                lda (destlo),y
eta_ajpattnodur:cmp #$60
                bcc eta_ajpattnowave
                iny
                lda (destlo),y
                cmp var3
                beq eta_ajpattskip
                bcc eta_ajpattskip
                clc
                adc var2
                sta (destlo),y
eta_ajpattnowave:
eta_ajpattskip: iny
                bne eta_ajpattloop2
eta_ajpattdone: inc var4
                bpl eta_ajpattloop
                jsr patttowork
                jmp drawpattern
eta_ajdone:     rts
eta_ajskip:     iny
                beq eta_ajdone
                jmp eta_ajcheck

edittrack:      lda editmode
                ldy #7
                jsr mulu
                lda alo
                sta testchn
                ldx editmode
                lda trackrow,x
                sec
                sbc trackview,x
                clc
                adc #$03
                tay
                lda editmode
                asl
                asl
                asl
                adc editmode
                adc #$04
                adc trackcol
                tax
                lda #$00
                jsr cursorpos
                lda editmode
                jsr gettrackadr
                ldx editmode
                jsr gethex
                bmi et_nohex
                ldy trackrow,x
                lda trackcol
                beq et_leftdigit
et_rightdigit:  lda (editlo),y
                and #$f0
                ora hexdigit
                sta (editlo),y
                jmp et_digitcommon
et_leftdigit:   asl hexdigit
                asl hexdigit
                asl hexdigit
                asl hexdigit
                lda (editlo),y
                and #$0f
                ora hexdigit
                sta (editlo),y
et_digitcommon: jsr gettracknum
                tay
                lda trackrow,x
                cmp orderlistlen,y
                bne et_digitdone
                lda orderlistlen,y
                clc
                adc #$01
                sta orderlistlen,y
et_digitdone:   jmp et_right
et_done:        ldx editmode
                jmp drawtrack
et_nohex:       lda key
                cmp #KEY_LEFT
                bne et_notleft
                lda trackcol
                eor #$01
                sta trackcol
                beq et_done
                bne et_up
et_notleft:     cmp #KEY_RIGHT
                bne et_notright
et_right:       lda trackcol
                eor #$01
                sta trackcol
                bne et_done
                beq et_down
et_notright:    cmp #KEY_DOWN
                bne et_notdown
et_down:        jsr gettracknum
                tay
                lda trackrow,x
                cmp orderlistlen,y
                bcc et_downok
                jmp et_done
et_downok:      inc trackrow,x
                lda trackrow,x
                sec
                sbc trackview,x
                cmp #VISIBLE_ROWS
                bcc et_done
                inc trackview,x
                jmp et_done
et_notdown:     cmp #KEY_UP
                bne et_notup
et_up:          lda trackrow,x
                bne et_upok
                rts
et_upok:        dec trackrow,x
                lda trackrow,x
                cmp trackview,x
                bcs et_done
                dec trackview,x
                jmp et_done
et_notup:       cmp #KEY_DEL
                bne et_nodelete
                jsr gettracknum
                tax
                ldy editmode
                lda trackrow,y
                sta var1
                cmp orderlistlen,x
                bcs et_ajdone
                dec orderlistlen,x
                tay
et_delloop:     iny
                beq et_deldone
                lda (editlo),y
                dey
                sta (editlo),y
                iny
                bne et_delloop
et_deldone:     lda #$00
                ldy #$ff
                sta (editlo),y
                lda #$ff
                sta var2
et_adjustjumps: ldy #$00
et_ajloop:      lda (editlo),y
                beq et_ajfound
                iny
                bne et_ajloop
                beq et_ajdone
et_ajfound:     iny
                lda (editlo),y
                cmp var1
                beq et_ajdone
                bcc et_ajdone
                clc
                adc var2
                sta (editlo),y
et_ajdone:      jmp et_done
et_nodelete:    cmp #KEY_INS
                bne et_noinsert
                lda trackrow,x
                cmp #$ff
                bcs et_insdone
                sta var1
                jsr gettracknum
                tax
                inc orderlistlen,x
                ldy #$fe
et_insloop:     lda (editlo),y
                iny
                sta (editlo),y
                dey
                cpy var1
                beq et_insdone
                dey
                jmp et_insloop
et_insdone:     lda #$01
                sta var2
                jmp et_adjustjumps
et_noinsert:    cmp #$20
                bne et_nospace
                lda trackrow,x
                sta songstart,x
                jmp et_done
et_nospace:     cmp #13
                bne et_noreturn
                ldy trackrow,x
                lda (editlo),y
                beq et_noentry
                bmi et_noentry
                sta pattnum
                lda #$00
                sta pattrow
                sta pattview
                lda #$03
                sta editmode
                jsr patttowork
                jsr ep_checktestwav
                jsr worktopatt
                jmp drawpattern
et_noentry:     rts
et_noreturn:    cmp #":"
                beq et_prevsong
                cmp #";"
                beq et_nextsong
                rts
et_prevsong:    dec songnum
et_songcommon:  lda songnum
                and #$0f
                sta songnum
                jsr stop
                jsr resettrack
                jmp drawall
et_nextsong:    inc songnum
                jmp et_songcommon

gettracknum:    lda songnum
                asl
                adc songnum
                adc editmode
                rts

        ;Position sprite cursor

cursorpos:
N               set 0
                repeat 8
                sta $0801+N*3
                sta $0802+N*3
N               set N+1
                repend
                lda #$01
                sta $d015
                lda #$00
                sta $d01c
                sta $d017
                sta $d019
                lda #$ff
                sta $d01b
                tya
                asl
                asl
                asl
                adc #50
                sta $d001
                txa
                asl
                asl
                adc #12
                asl
                sta $d000
                lda #$00
                adc #$00
                sta $d010
                rts

        ;Draw everything on screen

drawall:        jsr patttowork
                jsr worktopatt
                jsr drawtracks
                jsr drawpattern
                jsr drawtables
                lda #$0f
                sta rastercol+1
                rts

        ;Pattern to work

patttowork:     lda pattnum
                jsr getpattadr
                ldx #$00
                ldy #$00
ptw_loop:       lda #$00
                sta workpattdur,x
                sta workpattwave,x
                lda (editlo),y
                beq ptw_end
                cmp #$c0
                bcc ptw_nodur
                eor #$ff
                adc #$01                ;Negate bits & add 2
                sta var2
                sty var1
                lda #$00
                sta var3
                ldy #$08
                sed
ptw_decloop:    asl var2
                lda var3
                adc var3
                sta var3
                dey
                bne ptw_decloop
                cld
                ldy var1
                sta workpattdur,x
                iny
                lda (editlo),y
ptw_nodur:      cmp #$60
                bcc ptw_nowave
                sbc #$60
                bne ptw_norest
                lda #$5b                ;Use always $5b for rest
ptw_norest:     sta workpattnote,x
                iny
                lda (editlo),y
                sta workpattwave,x
                jmp ptw_notedone
ptw_nowave:     sta workpattnote,x
                cmp #$5c
                bcc ptw_notedone
                iny
                lda (editlo),y
                sta workpattwave,x      ;Waveform/AD/SR Command
ptw_notedone:   iny
                inx
                jmp ptw_loop
ptw_end:        lda #$00
                sta workpattnote,x
                sta workpattwave,x
                sta workpattdur,x
                stx workpattlen
wtp_cancel:     rts

        ;Work to pattern

worktopatt:     lda #$00
                sta totaldurlo
                sta totaldurhi
                lda pattnum
                beq wtp_cancel
                jsr getpattadr
                ldx #$00
                stx var1                ;Duration
                ldy #$00
wtp_loop:       lda workpattnote,x
                beq wtp_end
                cpy #189                ;Check for too long pattern
                bcs wtp_end
                lda workpattdur,x
                beq wtp_nodur
                sta var1
                pha
                and #$0f
                sta var3
                sty var2
                pla
                lsr
                lsr
                lsr
                lsr
                ldy #10
                jsr mulu
                lda alo
                adc var3
                ldy var2
                sec
                sbc #$02
                eor #$ff                ;Subtract 2 & negate
                sta (editlo),y
                iny
wtp_nodur:      lda workpattnote,x
                cmp #$5c
                bcs wtp_command
wtp_note:       lda workpattwave,x
                beq wtp_noteonly
wtp_notewave:   lda workpattnote,x
                cmp #$5b
                bne wtp_notewaveok
                lda #$00
wtp_notewaveok: clc
                adc #$60
                jmp wtp_command
wtp_noteonly:   lda workpattnote,x
                jmp wtp_stepcommon
wtp_command:    sta (editlo),y
                iny
                lda workpattwave,x
wtp_stepcommon: sta (editlo),y
                iny
                sed
                lda totaldurlo
                clc
                adc var1
                sta totaldurlo
                lda totaldurhi
                adc #$00
                sta totaldurhi
                cld
                inx
                jmp wtp_loop
wtp_end:        sta (editlo),y
                stx workpattlen
                iny
                cpy #$01
                bne wtp_lengthok
                ldy #$00
wtp_lengthok:   tya
                ldx pattnum
                sta pattlen,x
                rts

        ;Draw pattern

dp_emptyrow:    ldx #<pattemptytext
                ldy #>pattemptytext
                jsr printtext
                jmp dp_nextrow

drawpattern:    lda fastup
                ora fastdown
                beq dp_ok
                rts
dp_ok:          ldx #31
                ldy #2
                jsr setxy
                lda #1
                sta textcolor
                lda pattnum
                jsr printhex8
                ldx #35
                stx cursorx
                lda totaldurhi
                jsr printhex8
                ldx #37
                stx cursorx
                lda totaldurlo
                jsr printhex8
                lda pattview
                sta var2
                lda #3
                sta cursory
dp_loop:        lda #1
                sta textcolor
                lda #27
                sta cursorx
                lda var2
                jsr printhex8
                lda #15
                sta textcolor
                lda #30
                sta cursorx
                ldx var2
                cpx workpattlen
                beq dp_rowok
                bcs dp_emptyrow
dp_rowok:       lda workpattnote,x
                beq dp_end
                cmp #$5b
                bcs dp_cmd
dp_note:        sec
                sbc #$01
                ldy #12                         ;Separate into note/octave
                jsr divu
                asl                             ;Remainder = note
                tax
                lda notenames,x
                sta notetext
                lda notenames+1,x
                sta notetext+1
                lda alo
                clc
                adc #$30
                sta notetext+2
                ldx #<notetext
                ldy #>notetext
                jsr printtext
                jmp dp_notedone
dp_end:         ldx #<endtext
                ldy #>endtext
                jsr printtext
                jmp dp_notedone
dp_cmd:         sbc #$5b
                asl
                asl
                adc #<cmdtext0
                tax
                lda #>cmdtext0
                adc #$00
                tay
                jsr printtext
dp_notedone:    lda #34
                sta cursorx
                ldx var2
                lda workpattnote,x
                cmp #$5c
                bcs dp_displaywave
                lda workpattwave,x
                beq dp_emptywave
dp_displaywave: lda workpattwave,x
                jsr printhex8
                jmp dp_wavedone
dp_emptywave:   jsr printemptyslot
dp_wavedone:    lda #37
                sta cursorx
                ldx var2
                lda workpattdur,x
                beq dp_emptydur
                jsr printhex8
                jmp dp_nextrow
dp_emptydur:    jsr printemptyslot
dp_nextrow:     inc var2
                inc cursory
                lda cursory
                cmp #3+VISIBLE_ROWS
                bcs dp_done
                jmp dp_loop
dp_done:        rts

        ;Draw orderlists (tracks)

drawtracks:     ldx #0
                jsr drawtrack
                ldx #1
                jsr drawtrack
                ldx #2
drawtrack:      lda fastup
                ora fastdown
                beq dt_ok
                rts
dt_ok:          stx var1
                txa
                jsr gettrackadr
                lda #3
                sta cursory
                txa
                ldy #9
                jsr mulu
                lda alo
                sta cursorx
                inc cursorx
                lda #1
                sta textcolor
                ldx var1
                lda trackview,x
                sta var2
drawtrackloop1: lda var2
                jsr printhex8
                inc cursory
                inc var2
                lda cursory
                cmp #3+VISIBLE_ROWS
                bcc drawtrackloop1
                lda cursorx
                adc #$02
                sta cursorx
                lda #3
                sta cursory
                ldx var1
                lda trackview,x
                sta var2
                lda songstart,x
                sta var4
drawtrackloop2: ldx var3
                lda #15
                sta textcolor
                lda var2
                cmp var4
                bne dt_colorskip
                ldy #1
                sty textcolor
dt_colorskip:   cmp orderlistlen,x
                bcs drawtrackend
                tay
                lda (editlo),y
                jsr printhex8
drawtrackback:  inc cursory
                inc var2
                lda cursory
                cmp #3+VISIBLE_ROWS
                bcc drawtrackloop2
                rts
drawtrackend:   jsr printemptyslot
                jmp drawtrackback

        ;Draw tables

drawtables:     lda #$00
                jsr drawtable
                lda #$01
                jsr drawtable
                lda #$02
drawtable:      jsr gettableadr
                lda fastup
                ora fastdown
                beq dta_ok
                rts
dta_ok:         lda var3
                ldy #14
                jsr mulu
                lda alo
                sta cursorx
                lda #14
                sta cursory
                lda #1
                sta textcolor
                ldx var3
                lda tableview,x
                sta var2
                inc var2
drawtableloop1: lda var2
                jsr printhex8
                inc cursory
                inc var2
                lda cursory
                cmp #14+VISIBLE_TBLROWS
                bcc drawtableloop1
                lda #15
                sta textcolor
                lda cursorx
                clc
                adc #$03
                sta cursorx
                jsr drawdatatable
                inc edithi
                lda cursorx
                clc
                adc #$03
                sta cursorx
                jsr drawdatatable
                inc edithi
                lda cursorx
                clc
                adc #$03
                sta cursorx
drawdatatable:  lda #14
                sta cursory
                ldx var3
                lda tableview,x
                sta var2
drawtableloop2: ldx var3
                lda var2
                cmp tablelen,x
                bcs drawtableend
                tay
                cpx #$01
                bne dt_nonybblerev
                lda cursorx
                cmp #20
                beq dt_nybblerev
dt_nonybblerev: lda (editlo),y
dt_nybblerevback:jsr printhex8
drawtableback:  inc cursory
                inc var2
                lda cursory
                cmp #14+VISIBLE_TBLROWS
                bcc drawtableloop2
                rts
drawtableend:   jsr printemptyslot
                jmp drawtableback
dt_nybblerev:   lda (editlo),y
                asl
                adc #$00
                asl
                adc #$00
                asl
                adc #$00
                asl
                adc #$00
                jmp dt_nybblerevback

getpattadr:     tax
                lda patttbllo,x
                sta editlo
                lda patttblhi,x
                sta edithi
                rts

gettrackadr:    sta alo
                lda songnum
                asl
                adc songnum
                adc alo
                sta var3
                adc #>orderlists
                sta edithi
                lda #<orderlists
                sta editlo
                rts

gettableadr:    sta var3
                asl
                adc var3
                adc #>wavetbl
                sta edithi
                lda #<wavetbl
                sta editlo
                rts

printemptyslot: ldx #<emptyslottext
                ldy #>emptyslottext
                jmp printtext

        ;Clear musicdata

clearall:       ldx #$00
                lda #<patterns
                sta destlo
                lda #>patterns
                sta desthi
clearpatt:      ldy #$00
                tya
                sta pattlen,x
clearpattloop:  sta (destlo),y
                iny
                cpy #MAX_PATTLEN
                bcc clearpattloop
                tya
                jsr incdest
                inx
                cpx #MAX_PATT
                bcc clearpatt
                lda #<orderlists
                sta destlo
                lda #>orderlists
                sta desthi
                lda #MAX_SONGS*3
                ldx #$00
clearsongs:     lda #$00
                tay
                sta orderlistlen,x
clearsongloop:  sta (destlo),y
                iny
                bne clearsongloop
                inc desthi
                inx
                cpx #MAX_SONGS*3
                bcc clearsongs
                lda #DUR-3
                sta patterns
                lda #SETWAVE
                sta patterns+1
                lda #$00
                sta patterns+2
                sta patterns+3
                lda #DUR-40
                sta patterns+192
                lda #REST
                sta patterns+193
                lda #DUR-40
                sta patterns+384
                lda #REST
                sta patterns+385
                lda #DUR-40
                sta patterns+576
                lda #REST
                sta patterns+577
                lda #4
                sta pattlen
                lda #3
                sta pattlen+1
                sta pattlen+2
                sta pattlen+3
                lda #3
                sta orderlistlen
                sta orderlistlen+1
                sta orderlistlen+2
                lda #1
                sta orderlists
                lda #2
                sta orderlists+$100
                lda #3
                sta orderlists+$200
                lda #$00
                sta orderlists+$1
                sta orderlists+$2
                sta orderlists+$101
                sta orderlists+$102
                sta orderlists+$201
                sta orderlists+$202
                ldx #$00
cleartables:    sta wavetbl,x
                sta notetbl,x
                sta nexttbl,x
                sta pulsetimetbl,x
                sta pulseaddtbl,x
                sta pulsenexttbl,x
                sta filttimetbl,x
                sta filtaddtbl,x
                sta filtnexttbl,x
                inx
                cpx #MAX_TBL
                bcc cleartables
                lda #$04
                sta tablelen
                lda #$01
                sta tablelen+1
                sta tablelen+2
                lda #$08
                sta wavetbl
                lda #$09
                sta notetbl
                lda #$00
                sta nexttbl
                lda #$01
                sta wavetbl+1
                lda #$00
                sta notetbl+1
                lda #$03
                sta nexttbl+1
                lda #$41
                sta wavetbl+2
                lda #$00
                sta notetbl+2
                lda #$04
                sta nexttbl+2
                sta nexttbl+3
                sta pulseaddtbl
                lda #$80
                sta pulsetimetbl
                lda #$90
                sta wavetbl+3
resetpatttrack: lda #$01
                sta pattnum
                lda #$00
                sta pattrow
                sta pattview
resettrack:     lda #$00
                sta trackrow
                sta trackrow+1
                sta trackrow+2
                sta trackview
                sta trackview+1
                sta trackview+2
                sta songstart
                sta songstart+1
                sta songstart+2
                rts

        ;Inc destination pointer

incdest:        clc
                adc destlo
                sta destlo
                lda desthi
                adc #$00
                sta desthi
                rts

        ;Gethex - converts keypress to hex

gethex:         lda key
                cmp #"0"
                bcc gh_hnotnum
                cmp #"9"+1
                bcs gh_hnotnum
                sbc #"0"-1
                jmp gh_h2
gh_hnotalpha:   lda #$ff
                sta hexdigit
                rts
gh_hnotnum:     cmp #"A"
                bcc gh_hnotalpha
                cmp #"F"+1
                bcs gh_hnotalpha
                sbc #"A"-11
gh_h2:          sta hexdigit
                rts

        ;Disk operations

loadsong:       jsr askname
                lda namelength
                bne loadok
                rts
loadok:         lda #$02
                ldy #$00
                ldx drivenumber
                jsr setlfs
                lda namelength
                ldx #<name
                ldy #>name
                jsr setnam
                jsr open
                ldx #$02
                jsr chkin
                jsr chrin
                ldx status
                bne load_error
                cmp #"C"
                bne load_error
                jsr chrin
                cmp #"N"
                bne load_error
                lda #<savesongstart
                sta destlo
                lda #>savesongstart
                sta desthi
load_loop:      jsr load_getbyte
                cmp #ESCBYTE
                beq load_block
                jsr load_storebyte
                jmp load_loop
load_block:     jsr load_getbyte
                sta var1
                jsr load_getbyte
                tax
                lda var1
load_blockloop: jsr load_storebyte
                dex
                bne load_blockloop
                jmp load_loop

load_getbyte:   ldx status
                bne load_fileend
                jsr chrin
                sta $d020
                stx $d020
                rts
load_fileend:   pla
                pla
load_error:     lda #$02
                jsr close
                jsr clrchn
                rts

load_storebyte: ldy #$00
                sta (destlo),y
                inc destlo
                bne load_storebyte2
                inc desthi
load_storebyte2:rts

savesong:       jsr askname
                lda namelength
                bne saveok
                rts
saveok:         jsr stop
                jsr savecommon
                lda #"C"                ;Identification
                jsr save_sendbyte
                lda #"N"
                jsr save_sendbyte
                lda #<savesongstart
                sta destlo
                lda #>savesongstart
                sta desthi
save_loop:      ldy #$00
                lda (destlo),y
                ldy #$01
                cmp (destlo),y
                beq save_block
                cmp #ESCBYTE
                beq save_literal
                jsr save_sendbyte
save_next:      inc destlo
                bne save_nothigh
                inc desthi
save_nothigh:   lda destlo
                cmp #<savesongend
                bne save_loop
                lda desthi
                cmp #>savesongend
                bne save_loop
                jmp save_done
save_literal:   lda #ESCBYTE
                jsr save_sendbyte
                jsr save_sendbyte
                lda #$01
                jsr save_sendbyte
                jmp save_next
save_block:     lda #ESCBYTE
                jsr save_sendbyte
                ldy #$00
                lda (destlo),y
                sta var1
                jsr save_sendbyte
                ldy #$00
save_blocklen:  iny
                cpy #$ff
                beq save_blockready
                lda (destlo),y
                cmp var1
                beq save_blocklen
save_blockready:tya
                jsr save_sendbyte
                clc
                adc destlo
                sta destlo
                lda desthi
                adc #$00
                sta desthi
                jmp save_nothigh

save_sendbyte:  jsr chrout
                ldx status
                bne save_senderror
                sta $d020
                stx $d020
                rts
save_senderror: pla
                pla
save_done:      jmp load_error

savecommon:     lda #15
                ldx drivenumber
                ldy #15
                jsr setlfs
                clc
                lda namelength
                adc #$03
                ldx #<scratch
                ldy #>scratch
                jsr setnam
                jsr open
                lda #15
                jsr close
                lda #$02
                ldy #$01
                ldx drivenumber
                jsr setlfs
                lda namelength
                ldx #<name
                ldy #>name
                jsr setnam
                lda namelength
                jsr open
                ldx #$02
                jmp chkout

erasefile:      jsr askname
                lda namelength
                bne erase_ok
                rts
erase_ok:       jsr music+6
                lda #15
                ldx drivenumber
                ldy #15
                jsr setlfs
                clc
                lda namelength
                adc #$03
                ldx #<scratch
                ldy #>scratch
                jsr setnam
                jsr open
                lda #15
                jmp close

dir_end:        lda #$02
                jsr close
                jsr clrchn
dir_wait:       jsr getkey
                cmp #$00
                beq dir_wait
                rts
directory:      jsr clearscreen
                jsr music+6
                lda #$02
                ldy #$00
                ldx drivenumber
                jsr setlfs
                lda #$01
                ldx #<dirname
                ldy #>dirname
                jsr setnam
                jsr open
                ldx #$02
                jsr chkin
                lda #27
                sta $d011
                clc
                ldx #$00
                ldy #$00
                jsr plot
                lda #$0c
                sta 646
                jsr chrin
                jsr chrin
dir_loop:       lda status
                bne dir_end
                jsr chrin
                cmp #$01
                bne dir_loop
                jsr chrin
                lda status
                bne dir_end
                jsr chrin
                sta textlo
                jsr chrin
                sta texthi
                lda #$00
                sta dirprintnum
                tay
dir_100loop:    lda texthi
                cmp #>100
                beq dir_100cl
                bcs dir_100ok
                bcc dir_100quit
dir_100cl:      lda textlo
                cmp #<100
                bcs dir_100ok
                bcc dir_100quit
dir_100ok:      iny
                sec
                lda textlo
                sbc #<100
                sta textlo
                lda texthi
                sbc #>100
                sta texthi
                jmp dir_100loop
dir_100quit:    tya
                clc
                adc #"0"
                cmp #"0"
                beq dir_10
                jsr chrout
                inc dirprintnum
dir_10:         ldy #$00
dir_10loop:     lda texthi
                cmp #>10
                beq dir_10cl
                bcs dir_10ok
                bcc dir_10quit
dir_10cl:       lda textlo
                cmp #<10
                bcs dir_10ok
                bcc dir_10quit
dir_10ok:       iny
                sec
                lda textlo
                sbc #<10
                sta textlo
                lda texthi
                sbc #>10
                sta texthi
                jmp dir_10loop
dir_10quit:     tya
                clc
                adc #"0"
                ldy dirprintnum
                bne dir_10pr
                cmp #"0"
                beq dir_10np
dir_10pr:       jsr chrout
dir_10np:       lda textlo
                clc
                adc #"0"
                jsr chrout
                lda #$20
                jsr chrout
dir_loop3:      lda status
                bne dir_end2
                jsr chrin
                cmp #$00
                bne dir_noline
                lda #13
                jsr chrout
                jmp dir_loop
dir_noline:     jsr chrout
                jmp dir_loop3
dir_end2:       jmp dir_end

dirname:        dc.b "$"
filebuffer:     ds.b 32,0
dirprintnum:    dc.b 0


        ;Ask for song filename

askname:        lda #$00
                sta namelength
                ldx #$0f
                lda #$20
askname1:       sta name,x
                dex
                bpl askname1
                ldx #0
                ldy #24
                jsr setxy
                ldx #<asknametext
                ldy #>asknametext
                jsr printtext
asknameloop:    ldx #9
                ldy #24
                jsr setxy
                ldx #<name
                ldy #>name
                jsr printtext
                lda #$20
                sta $400+24*40+16+9
                ldx namelength
                lda $400+24*40+9,x
                ora #$80
                sta $400+24*40+9,x
askname_getkey: jsr getkey
                cmp #$00
                beq askname_getkey
                cmp #13
                beq askname_end
                cmp #KEY_DEL
                bne askname_nodel
                lda namelength
                beq asknameloop
                dec namelength
                ldx namelength
                lda #$20
                sta name,x
                jmp asknameloop
askname_nodel:  cmp #$20
                bcc asknameloop
                and #$3f
                ldx namelength
                cpx #$10
                bcs asknameloop
                sta name,x
                inc namelength
                jmp asknameloop
askname_end:    ldx #$0f
askname_final:  lda name,x
                cmp #$20
                bcs askname_final2
                ora #$40
                sta name,x
askname_final2: dex
                bpl askname_final
                lda #24
                sta cursory
                jmp printemptyrow

getkey:         lda fastup
                bne gk_fastup
                lda fastdown
                bne gk_fastdown
                jsr getkey_delay
                jsr scnkey
                jsr getin
gk_ok:          sta key
                pha
                jsr gethex
                pla
                rts

getkey_delay:   ldy #6
gkd1:           ldx #$ff
gkd2:           dex
                bne gkd2
                dey
                bne gkd1
                rts

gk_fastup:      dec fastup
                lda #KEY_UP
                bne gk_ok
gk_fastdown:    dec fastdown
                lda #KEY_DOWN
                bne gk_ok

printraster:    lda #1
                sta textcolor
                ldx curraster
                lda hexcodes,x
                sta $0400+24*40+35
                ldx maxraster
                lda hexcodes,x
                sta $0400+24*40+37
                ldx #13
                ldy #24
                jsr setxy
                lda timemin
                jsr printhex8
                ldx #16
                stx cursorx
                lda timesec
                jsr printhex8
                ldx octave
                lda hexcodes,x
                sta $0400+24*40+26
                ldx songnum
                lda hexcodes,x
                sta $0400+24*40+6
                rts

initscreen:     lda #$00
                sta $d020
                sta $d021
                sta maxraster
                lda #$0b
                sta $d022
                lda #$0c
                sta $d023
                lda #$03
                sta $dd00
                lda #$08
                sta $d016
                lda #$1b
                sta $d011
                lda #22
                sta $d018
                lda #$80
                sta $291
                jsr clearscreen
                lda #1
                sta textcolor
                lda #0
                sta cursorx
                sta cursory
                ldx #<titletext
                ldy #>titletext
                jsr printtext
                lda #2
                sta cursory
                ldx #<tracktext
                ldy #>tracktext
                jsr printtext
                lda #13
                sta cursory
                ldx #<tabletext
                ldy #>tabletext
                jsr printtext
                lda #24
                sta cursory
                ldx #<statustext
                ldy #>statustext
                jsr printtext
                rts

clearscreen:    lda #$20
                ldx #$00
cs_loop:        sta $0400,x
                sta $0500,x
                sta $0600,x
                sta $0700,x
                inx
                bne cs_loop
                stx $d015
                lda $d011
                ora #$10
                sta $d011
                rts

        ;X=xposition, Y=yposition

setxy:          stx cursorx
                sty cursory
                rts

printemptyrow:  ldx #$00
                stx cursorx
                ldx #<emptyrow
                ldy #>emptyrow

        ;X=text address lo, Y=text address hi

printtext:      stx textlo
                sty texthi
printtextcont:  ldx cursory
                clc
                lda rowtbllo,x
                adc cursorx
                sta destlo
                lda rowtblhi,x
                adc #$00
                sta desthi
                ldy #$00
pt_loop:        lda (textlo),y
                beq pt_done
                cmp #96
                bcc pt_nolowercase
                sbc #96
pt_nolowercase: sta (destlo),y
                clc
                lda desthi
                adc #$d4
                sta desthi
                lda textcolor
                sta (destlo),y
                sec
                lda desthi
                sbc #$d4
                sta desthi
                iny
                jmp pt_loop
pt_done:        iny
                tya
                clc
                adc textlo
                sta textlo
                lda texthi
                adc #$00
                sta texthi
                rts

        ;A=hex value

printhex8:      jsr converthex8
                ldx cursory
                clc
                lda rowtbllo,x
                adc cursorx
                sta destlo
                lda rowtblhi,x
                adc #$d4
                sta desthi
                lda textcolor
                ldy #$00
                sta (destlo),y
                iny
                sta (destlo),y
                dey
                lda desthi
                sec
                sbc #$d4
                sta desthi
                lda hexstring
                ldy #$00
                sta (destlo),y
                lda hexstring+1
                iny
                sta (destlo),y
                rts

        ;A=number to be converted

converthex8:    sta hexvalue
                lsr
                lsr
                lsr
                lsr
                tax
                lda hexcodes,x
                sta hexstring
                lda hexvalue
                and #$0f
                tax
                lda hexcodes,x
                sta hexstring+1
                rts

        ;A,Y=values to be multiplied
        ;alo,ahi=16bit result

mulu:           sta alo
                tya
                beq mulu_zero
                dey
                sty ahi
                ldy #$07
                lda #$00
                lsr alo
                bcc mulu_shift1
                adc ahi
mulu_shift1:    ror
                ror alo
                bcc mulu_shift2
                adc ahi
mulu_shift2:    dey
                bne mulu_shift1
mulu_shift8:    ror
                sta ahi
                ror alo
                rts
mulu_zero:      sta alo
                sta ahi
                rts

        ;A=value to be divided
        ;Y=divisor
        ;alo=result
        ;A=remainder

divu:           sta alo
                tya
                sta ahi
                lda #$00
                asl alo
                ldy #$07
divu_loop:      rol
                cmp ahi
                bcc divu_skip
                sbc ahi
divu_skip:      rol alo
                dey
                bpl divu_loop
                rts

initraster:     sei
                lda #$7f
                sta $dc0d
                lda #$01
                sta $d01a
                lda #<raster
                sta $0314
                lda #>raster
                sta $0315
                lda $dc0d
                cli
                rts

raster:         dec $d019
                cld
                nop
                nop
                nop
                nop
                nop
rastercol:      lda #$00
                sta $d020
                jsr music
                lda $d012
                ldx #$00
                stx $d020
                sec
                sbc #$34
                sta curraster
                lda curraster
                cmp maxraster
                bcc ras_notmax
                sta maxraster
ras_notmax:     lda maxraster                   ;Raster-meter bugs sometimes..
                cmp #$10                        ;(loading/saving etc.)
                bcc ras_meterok
                lda #$00
                sta curraster
                sta maxraster
ras_meterok:    lda playflag
                bne ras_ok
                lda #$80
                sta chncounter
                sta chncounter+7
                sta chncounter+14
                lda #$00
                sta timeframe
ras_ok:         inc timeframe
                lda fastfwd
                beq ras_nofast
                jsr music
                jsr music
                jsr music
                lda timeframe
                clc
                adc #$03
                sta timeframe
ras_nofast:     lda timeframe
                cmp #50
                bcc ras_nosec
                sbc #50
                sta timeframe
                sed
                lda timesec
                clc
                adc #$01
                cmp #$60
                bcc ras_nomin
                lda #$00
                pha
                lda timemin
                adc #$00
                sta timemin
                pla
ras_nomin:      sta timesec
                cld
ras_nosec:      inc cursorcol
                lda cursorcol
                lsr
                lsr
                and #$07
                tax
                lda cursorcoltbl,x
                sta $d027
                lda $d011
                and #$7f
                sta $d011
                lda #$34
                sta $d012
                jmp $ea81

;-----------------------------------------------------------------------------
;The virtual playroutine (for relocation)
;-----------------------------------------------------------------------------

        ;A table for all C64 instructions. 3 byte long instructions contain an
        ;absolute address and must be relocated. 0 denotes zeropage relocation.

asmtable:       dc.b $69,2 ;ADC immediate
                dc.b $65,0 ;ADC zeropage
                dc.b $75,0 ;ADC zeropage,X
                dc.b $6d,3 ;ADC absolute
                dc.b $7d,3 ;ADC absolute,X
                dc.b $79,3 ;ADC absolute,Y
                dc.b $61,0 ;ADC indirect,X
                dc.b $71,0 ;ADC indirect,Y

                dc.b $29,2 ;AND immediate
                dc.b $25,0 ;AND zeropage
                dc.b $35,0 ;AND zeropage,X
                dc.b $2d,3 ;AND absolute
                dc.b $3d,3 ;AND absolute,X
                dc.b $39,3 ;AND absolute,Y
                dc.b $21,0 ;AND indirect,X
                dc.b $31,0 ;AND indirect,Y

                dc.b $0a,1 ;ASL accumulator
                dc.b $06,0 ;ASL zeropage
                dc.b $16,0 ;ASL zeropage,X
                dc.b $0e,3 ;ASL absolute
                dc.b $1e,3 ;ASL absolute,X
                dc.b $90,2 ;BCC
                dc.b $b0,2 ;BCS
                dc.b $f0,2 ;BEQ

                dc.b $24,0 ;BIT zeropage
                dc.b $2c,3 ;BIT absolute
                dc.b $30,2 ;BMI
                dc.b $d0,2 ;BNE
                dc.b $10,2 ;BPL
                dc.b $00,1 ;BRK
                dc.b $50,2 ;BVC
                dc.b $70,2 ;BVS

                dc.b $18,1 ;CLC
                dc.b $d8,1 ;CLD
                dc.b $58,1 ;CLI
                dc.b $b8,1 ;CLV
                dc.b $c9,2 ;CMP immediate
                dc.b $c5,0 ;CMP zeropage
                dc.b $d5,0 ;CMP zeropage,X
                dc.b $cd,3 ;CMP absolute

                dc.b $dd,3 ;CMP absolute,X
                dc.b $d9,3 ;CMP absolute,Y
                dc.b $c1,0 ;CMP indirect,X
                dc.b $d1,0 ;CMP indirect,Y
                dc.b $e0,2 ;CPX immediate
                dc.b $e4,0 ;CPX zeropage
                dc.b $ec,3 ;CPX absolute
                dc.b $c0,2 ;CPY immediate

                dc.b $c4,0 ;CPY zeropage
                dc.b $cc,3 ;CPY absolute
                dc.b $c6,0 ;DEC zeropage
                dc.b $d6,0 ;DEC zeropage,X
                dc.b $ce,3 ;DEC absolute
                dc.b $de,3 ;DEC absolute,X
                dc.b $ca,1 ;DEX
                dc.b $88,1 ;DEY

                dc.b $49,2 ;EOR immediate
                dc.b $45,0 ;EOR zeropage
                dc.b $55,0 ;EOR zeropage,X
                dc.b $4d,3 ;EOR absolute
                dc.b $5d,3 ;EOR absolute,X
                dc.b $59,3 ;EOR absolute,Y
                dc.b $41,0 ;EOR indirect,X
                dc.b $51,0 ;EOR indirect,Y

                dc.b $e6,0 ;INC zeropage
                dc.b $f6,0 ;INC zeropage,X
                dc.b $ee,3 ;INC absolute
                dc.b $fe,3 ;INC absolute,X
                dc.b $e8,1 ;INX
                dc.b $c8,1 ;INY
                dc.b $4c,3 ;JMP absolute
                dc.b $6c,3 ;JMP indirect

                dc.b $20,3 ;JSR absolute
                dc.b $a9,2 ;LDA immediate
                dc.b $a5,0 ;LDA zeropage
                dc.b $b5,0 ;LDA zeropage,X
                dc.b $ad,3 ;LDA absolute
                dc.b $bd,3 ;LDA absolute,X
                dc.b $b9,3 ;LDA absolute,Y
                dc.b $a1,0 ;LDA indirect,X

                dc.b $b1,0 ;LDA indirect,Y
                dc.b $a2,2 ;LDX immediate
                dc.b $a6,0 ;LDX zeropage
                dc.b $b6,0 ;LDX zeropage,Y
                dc.b $ae,3 ;LDX absolute
                dc.b $be,3 ;LDX absolute,Y
                dc.b $a0,2 ;LDY immediate
                dc.b $a4,0 ;LDY zeropage

                dc.b $b4,0 ;LDY zeropage,Y
                dc.b $ac,3 ;LDY absolute
                dc.b $bc,3 ;LDY absolute,Y
                dc.b $4a,1 ;LSR accumulator
                dc.b $46,0 ;LSR zeropage
                dc.b $56,0 ;LSR zeropage,X
                dc.b $4e,3 ;LSR absolute
                dc.b $5e,3 ;LSR absolute,X

                dc.b $ea,1 ;NOP
                dc.b $09,2 ;ORA immediate
                dc.b $05,2 ;ORA zeropage
                dc.b $15,2 ;ORA zeropage,X
                dc.b $0d,3 ;ORA absolute
                dc.b $1d,3 ;ORA absolute,X
                dc.b $19,3 ;ORA absolute,Y
                dc.b $01,0 ;ORA indirect,X

                dc.b $11,0 ;ORA indirect,Y
                dc.b $48,1 ;PHA
                dc.b $08,1 ;PHP
                dc.b $68,1 ;PLA
                dc.b $28,1 ;PLP
                dc.b $2a,1 ;ROL accumulator
                dc.b $26,0 ;ROL zeropage

                dc.b $36,2 ;ROL zeropage,X
                dc.b $2e,3 ;ROL absolute
                dc.b $3e,3 ;ROL absolute,X
                dc.b $6a,1 ;ROR accumulator
                dc.b $66,0 ;ROR zeropage
                dc.b $76,0 ;ROR zeropage,X
                dc.b $6e,3 ;ROR absolute
                dc.b $7e,3 ;ROR absolute,X

                dc.b $40,1 ;RTI
                dc.b $60,1 ;RTS
                dc.b $e9,2 ;SBC immediate
                dc.b $e5,0 ;SBC zeropage
                dc.b $f5,0 ;SBC zeropage,X
                dc.b $ed,3 ;SBC absolute
                dc.b $fd,3 ;SBC absolute,X
                dc.b $f9,3 ;SBC absolute,Y

                dc.b $e1,0 ;SBC indirect,X
                dc.b $f1,0 ;SBC indirect,Y
                dc.b $38,1 ;SEC
                dc.b $f8,1 ;SED
                dc.b $78,1 ;SEI
                dc.b $85,0 ;STA zeropage
                dc.b $95,0 ;STA zeropage,X
                dc.b $8d,3 ;STA absolute

                dc.b $9d,3 ;STA absolute,X
                dc.b $99,3 ;STA absolute,Y
                dc.b $81,0 ;STA indirect,X
                dc.b $91,0 ;STA indirect,Y
                dc.b $86,0 ;STX zeropage
                dc.b $96,0 ;STX zeropage,Y
                dc.b $8e,3 ;STX absolute
                dc.b $84,2 ;STY zeropage

                dc.b $94,0 ;STY zeropage,X
                dc.b $8c,3 ;STY absolute
                dc.b $aa,1 ;TAX
                dc.b $a8,1 ;TAY
                dc.b $ba,1 ;TSX
                dc.b $8a,1 ;TXA
                dc.b $9a,1 ;TXS
                dc.b $98,1 ;TYA
                dc.b $ff,0 ;End of table


vplayerstart:
                rorg $0100

vtemp1          = $00
vtemp2          = $01
vtemp3          = $02
vtemp4          = $03
vtemp5          = $04


vsongtbllo      = $500
vsongtblhi      = $600
vpatttbllo      = $700
vpatttblhi      = $800
vwavetbl        = $901
vnotetbl        = $a01
vnexttbl        = $b01
vpulsetimetbl   = $c01
vpulseaddtbl    = $d01
vpulsenexttbl   = $e01
vfilttimetbl    = $f01
vfiltaddtbl     = $1001
vfiltnexttbl    = $1101


                jmp vinit

vmusic:         ldx #$00
vinitsongnum:   ldy #$00
                bmi vchnloop
                txa
                ldx #21
vclearloop:     sta vchnsongpos-1,x
                dex
                bne vclearloop
vinitloop:      lda vsongtbllo,y
                sta vchnsonglo,x
                lda vsongtblhi,y
                sta vchnsonghi,x
                iny
                dec vchncounter,x
                lda vchnnext,x
                tax
                bne vinitloop
                sta vtemp3
                sta $d417
                lda #$ff
                sta vinitsongnum+1
                rts

vfreqmod:       inc vchnwavedelay,x
                bne vfmnotover
                lda vchnwavestored,x
                sta vchnwavepos,x
vfmnotover:     lda vchnfreqlo,x
                clc
                adc vchnfreqmodlo,x
                sta vchnfreqlo,x
                sta $d400,x
                lda vchnfreqhi,x
                adc vchnfreqmodhi,x
                jmp vsetfreqhi

vchnloop:       ldy vchnwavepos,x
                beq vfreqmod
                lda vwavetbl-1,y
                beq vnowavechange
                cmp #$08
                beq vhrnote
                bcc vlegatonote
                cmp #$90
                bcc vwavechange
vnewfreqmod:    sta vchnwavedelay,x
                lda vnexttbl-1,y
                sta vchnwavestored,x
                lda vnotetbl-1,y
                asl
                sta vchnfreqmodlo,x
                lda #$00
                sta vchnwavepos,x
                bcc vfreqmodpos
                lda #$ff
vfreqmodpos:    asl vchnfreqmodlo,x
                rol
                sta vchnfreqmodhi,x
                jmp vwavedone

vhrnote:        sta $d404,x
                lda vnotetbl-1,y
                sta $d405,x
                lda vnexttbl-1,y
                sta $d406,x
                lda #$09
                sta $d404,x
vlegatonote:    lda vwavetbl,y
                beq vskippulse
                sta vchnpulsepos,x
                lda #$00
                sta vchnpulsetime,x
vskippulse:     lda vnotetbl,y
                beq vskipfilt
                sta vtemp3
                lda #$00
                sta vtemp4
vskipfilt:      lda vnexttbl,y
                sta vchnwavepos,x
                jmp vreloadcounter

vwavechange:    sta $d404,x
vnowavechange:  lda vnexttbl-1,y
                sta vchnwavepos,x
                lda vnotetbl-1,y
                asl
                bcs vabsnote
                adc vchnnote,x
vabsnote:       tay
                lda vfreqtbl-2,y
                sta vchnfreqlo,x
                sta $d400,x
                lda vfreqtbl-1,y
vsetfreqhi:     sta $d401,x
                sta vchnfreqhi,x
vwavedone:      inc vchncounter,x
                bne vnonewnote

vgetnewnote:    ldy vchnpattnum,x
                lda vpatttbllo,y
                sta vtemp1
                lda vpatttblhi,y
                sta vtemp2
                ldy vchnpattpos,x
                lda (vtemp1),y
                cmp #$c0                        ;Duration?
                bcc vnoduration
                sta vchnduration,x
                iny
                lda (vtemp1),y
vnoduration:    cmp #$60
                bcs vnotewithwave
                cmp #$5b
                bcc vnotewithoutwave
                beq vrest
vcommand:       and #$07
                cmp #$07
                beq vcmdflt
                sta vcmdsta+1
                iny
                lda (vtemp1),y
vcmdsta:        sta $d400,x
                bcc vrest
vcmdflt:        iny
                lda (vtemp1),y
                sta vtemp3
                lda #$00
                sta vtemp4
                bcs vrest
vnotewithoutwave:
                adc vchntrans,x
                asl
                sta vchnnote,x
                lda vchnwavepreset,x
                sta vchnwavepos,x
                bne vrest
vnotewithwave:  beq vwaveonly
                sbc #$61
                adc vchntrans,x               ;Adds one too much (C=1)
                asl
                sta vchnnote,x
vwaveonly:      iny
                lda (vtemp1),y
                sta vchnwavepreset,x
                sta vchnwavepos,x
vrest:          iny
                lda (vtemp1),y
                beq vendpatt
                tya
vendpatt:       sta vchnpattpos,x
                jmp vnextchn

vnonewnote:      bmi vpulseexec
vreloadcounter:
                lda vchnpattpos,x
                bne vnonewpatt
                lda vchnsonglo,x
                sta vtemp1
                lda vchnsonghi,x
                sta vtemp2
                ldy vchnsongpos,x
                lda (vtemp1),y
                bpl vnotrans
                sta vchntrans,x
                iny
                lda (vtemp1),y
vnotrans:       sta vchnpattnum,x
                iny
                lda (vtemp1),y
                beq vsongloop
vnoloop:        tya
                jmp vloopcommon
vsongloop:      iny
                lda (vtemp1),y
vloopcommon:    sta vchnsongpos,x

vnonewpatt:     lda vchnduration,x
                sta vchncounter,x
                jmp vnextchn

vpulseexec:     txa
                bne vskipfiltexec
                ldy vtemp3
                beq vfilttype
                dec vtemp4
                bmi vfirstfilt
                bne vfiltadd
vnextfilt:      lda vfiltnexttbl-1,y
                sta vtemp3
                tay
vfirstfilt:     lda vfilttimetbl-1,y
                bmi vsetfilt
                sta vtemp4
                bpl vfilttype
vsetfilt:       and #$70
                sta vfilttype+1
                lda #$01
                sta vtemp4
                lda vfilttimetbl-1,y
vresonance:     ora #$f0
                sta $d417
                lda vfiltaddtbl-1,y
                beq vfilttype
                bne vstorefilt
vfiltadd:       lda vtemp5
                clc
                adc vfiltaddtbl-1,y
vstorefilt:     sta vtemp5
                sta $d416
vfilttype:      lda #$00
vvolume:        ora #$0f
                sta $d418
vskipfiltexec:  ldy vchnpulsepos,x
                beq vnextchn
                dec vchnpulsetime,x
                bmi vfirstpulse
                bne vpulseadd
vnextpulse:     lda vpulsenexttbl-1,y
                sta vchnpulsepos,x
                tay
vfirstpulse:    lda vpulsetimetbl-1,y
                bmi vsetpulse
                sta vchnpulsetime,x
                jmp vnextchn
vsetpulse:      lda #$01
                sta vchnpulsetime,x
                lda vpulseaddtbl-1,y
                bne vstorepulse
vpulseadd:      clc
                lda vpulseaddtbl-1,y
                adc vchnpulse,x
                adc #$00
vstorepulse:    sta vchnpulse,x
                sta $d402,x
                sta $d403,x
vnextchn:       lda vchnnext,x
                beq vchndone
                tax
                jmp vchnloop
vchndone:       rts

vinit:          sta vinittemp+1
                asl
vinittemp:      adc #$00
                sta vinitsongnum+1
                rts

vchnsongpos:    dc.b 0
vchnpattnum:    dc.b 0
vchnpattpos:    dc.b 0
vchntrans:      dc.b 0
vchncounter:    dc.b 0
vchnwavepos:    dc.b 0
vchnwavestored: dc.b 0

                dc.b 0,0,0,0,0,0,0
                dc.b 0,0,0,0,0,0,0

vchnwavepreset: dc.b 1
vchnwavedelay:  dc.b 0
vchnsonglo:     dc.b 0
vchnsonghi:     dc.b 0
vchnpulse:      dc.b 0
vchnpulsepos:   dc.b 0
vchnpulsetime:  dc.b 0

                dc.b 1,0,0,0,0,0,0
                dc.b 1,0,0,0,0,0,0

vchnnote:       dc.b 0
vchnduration:   dc.b 0
vchnfreqlo:     dc.b 0
vchnfreqhi:     dc.b 0
vchnfreqmodlo:  dc.b 0
vchnfreqmodhi:  dc.b 0
vchnnext:       dc.b 7

                dc.b 0,0,0,0,0,0,14
                dc.b 0,0,0,0,0,0,0

vfreqtbl:       dc.w $0115,$0125,$0136,$0149,$015c,$0171,$0187,$019f,$01b7,$01d1,$01ed,$020a
                dc.w $022a,$024a,$026d,$0292,$02b9,$02e3,$030f,$033e,$036f,$03a3,$03db,$0415
                dc.w $0454,$0495,$04db,$0525,$0573,$05c7,$061e,$067c,$06de,$0747,$07b6,$082b
                dc.w $08a8,$092b,$09b7,$0a4b,$0ae7,$0b8e,$0c3d,$0cf8,$0dbd,$0e8e,$0f6c,$1057
                dc.w $1150,$1257,$136e,$1496,$15cf,$171c,$187b,$19f0,$1b7b,$1d1d,$1ed8,$20ae
                dc.w $22a0,$24af,$26dd,$292d,$2b9f,$2e38,$30f7,$33e0,$36f6,$3a3b,$3db1,$415d
                dc.w $4540,$495e,$4dbb,$525a,$573f,$5c70,$61ef,$67c1,$6ded,$7476,$7b63,$82ba
                dc.w $8a80,$92bc,$9b76,$a4b4,$ae7f,$b8e0,$c3de,$cf83,$dbda,$e8ed,$f6c7,$ffff

                rend
;-------------------------------------------------------------------------------

vplayerend:

savesongstart:

wavetbl:        ds.b MAX_TBL+1,0
notetbl:        ds.b MAX_TBL+1,0
nexttbl:        ds.b MAX_TBL+1,0

pulsetimetbl:   ds.b MAX_TBL+1,0
pulseaddtbl:    ds.b MAX_TBL+1,0
pulsenexttbl:   ds.b MAX_TBL+1,0

filttimetbl:    ds.b MAX_TBL+1,0
filtaddtbl:     ds.b MAX_TBL+1,0
filtnexttbl:    ds.b MAX_TBL+1,0

patterns:       ds.b MAX_PATT*MAX_PATTLEN,0

orderlists:     ds.b MAX_SONGS*MAX_SONGLEN*3,0

pattlen:        ds.b MAX_PATT,0
orderlistlen:   ds.b MAX_SONGS*3,0
tablelen:       dc.b 0,0,0

savesongend:


;-------------------------------------------------------------------------------
; Other data
;-------------------------------------------------------------------------------

rowtbllo:
n               set 0
                repeat 25
                dc.b <($400+40*n)
n               set n+1
                repend

rowtblhi:
n               set 0
                repeat 25
                dc.b >($400+40*n)
n               set n+1
                repend

emjumptbl:      dc.w edittrack
                dc.w edittrack
                dc.w edittrack
                dc.w editpattern
                dc.w edittable
                dc.w edittable
                dc.w edittable

pattcoltbl:     dc.b 30,34,35,37,38

cursorcoltbl:   dc.b 0,9,8,7,1,7,8,9

notekeytbl:     dc.b "A"
                dc.b "W"
                dc.b "S"
                dc.b "E"
                dc.b "D"
                dc.b "F"
                dc.b "T"
                dc.b "G"
                dc.b "Y"
                dc.b "H"
                dc.b "U"
                dc.b "J"
                dc.b "K"
                dc.b "O"
                dc.b "L"
                dc.b "P"
                dc.b "W"+$80
                dc.b "D"+$80
                dc.b "S"+$80
                dc.b "F"+$80


notenames:      dc.b "C-"
                dc.b "C#"
                dc.b "D-"
                dc.b "D#"
                dc.b "E-"
                dc.b "F-"
                dc.b "F#"
                dc.b "G-"
                dc.b "G#"
                dc.b "A-"
                dc.b "A#"
                dc.b "B-"

notetext:       dc.b "C-0",0
cmdtext0:       dc.b "Rst",0
cmdtext1:       dc.b "Wav",0
cmdtext2:       dc.b "AD ",0
cmdtext3:       dc.b "SR ",0
cmdtext4:       dc.b "Flt",0
endtext:        dc.b "End",0

pattemptytext:  dc.b "--- -- --",0
emptyslottext:  dc.b "--",0
emptyrow:       dc.b "                                       ",0

titletext:      dc.b "CovertBitops NinjaTracker V1.0  F8=Help",0
statustext:        dc.b " Song   Time   :   Octave   Raster  /  ",0
tracktext:      dc.b "Track 1  Track 2  Track 3  Sct    D    ",0
tabletext:      dc.b " Wavetable    Pulse-table   Filtertable",0

asknametext:    dc.b "Filename:",0

confirmtext:    dc.b "Are you sure (Y/N)?",0

disktext:       dc.b "Disk Menu",0
                dc.b " ",0
                dc.b "C Change Device",0
                dc.b "D Directory",0
                dc.b "L Load Song",0
                dc.b "S Save Song",0
                dc.b "E Erase File",0
                dc.b "P Pack & Relocate",0
                dc.b "N Nuke Songdata",0
                dc.b "X Exit NinjaTracker",0
devicetext:     dc.b "Device number:",0

packtext1:      dc.b "Pack & relocate song",0
packtext2:      dc.b "Start address:",0
packtext3:      dc.b "Zeropage base:",0

packres1:       dc.b "Playroutine:",0
packres2:       dc.b "Musicdata:",0
packres3:       dc.b "Total size:",0


hexstring:      dc.b "00",0
hexcodes:       dc.b "0123456789ABCDEF",0

scratch:        dc.b "S0:"
name:           dc.b "                ",0
namelength:     dc.b 0

textcolor:      dc.b 0
hexdigit:       dc.b 0
hexvalue:       dc.b 0
cursorx:        dc.b 0
cursory:        dc.b 0
drivenumber:    dc.b 0
fastfwd:        dc.b 0

curraster:      dc.b 0
maxraster:      dc.b 0
timeframe:      dc.b 0
timesec:        dc.b 0
timemin:        dc.b 0
playflag:       dc.b 0
fastup:         dc.b 0
fastdown:       dc.b 0
key:            dc.b 0
cursorcol:      dc.b 0
octave:         dc.b 0

relocadrlo:	dc.b 0
relocadrhi:	dc.b $10
relocadrzp:	dc.b $fb

songnum:        dc.b 0
pattnum:        dc.b 0

editmode:       dc.b 0

testchn:        dc.b 0
lasttestwav:    dc.b 1

trackcol:       dc.b 0
trackview:      dc.b 0,0,0
trackrow:       dc.b 0,0,0

tablecol:       dc.b 0
tablebyte:      dc.b 0,0,0
tableview:      dc.b 0,0,0
tablerow:       dc.b 0,0,0

pattview:       dc.b 0
pattrow:        dc.b 0
pattcol:        dc.b 0

songstart:      dc.b 0,0,0

workpattnote:   ds.b MAX_PATTLEN,0
workpattwave:   ds.b MAX_PATTLEN,0
workpattdur:    ds.b MAX_PATTLEN,0

workpattlen:    dc.b 0
totaldurlo:     dc.b 0
totaldurhi:     dc.b 0

copybuffer:     dc.b MAX_PATTLEN,0

                org $cc80


onlinehelptext: dc.b "CovertBitops NinjaTracker online help   "
                dc.b "                                        "
                dc.b "Press arrows up/down to scroll, and     "
                dc.b "F8, SPACE or RETURN to return to editor."
                dc.b "                                        "
                dc.b "1. Introduction                         "
                dc.b "                                        "
                dc.b "NinjaTracker is a 10-rasterline max (in "
                dc.b "most cases) music editor, with simple   "
                dc.b "but flexible musicdata and small play-  "
                dc.b "routine (about 512 bytes without tables,"
                dc.b "variables & musicdata).                 "
                dc.b "                                        "
                dc.b "If you're looking for an easy music-    "
                dc.b "editor, please look elsewhere. But if   "
                dc.b "you know what you're doing, and have low" 
                dc.b "rastertime & memory use requirements,   "
                dc.b "NinjaTracker might be useful to you.    "
                dc.b "                                        "
                dc.b "One last thing. GoatTracker strayed     "
                dc.b "quite far from my original plan because "
                dc.b "of feature-requests. This was not bad   "
                dc.b "(it became easy & powerful) but I'm not "
                dc.b "going to repeat that with this program. "
                dc.b "Therefore, please, no feature-requests  "
                dc.b "for Ninjatracker!                       "
                dc.b "                                        "
                dc.b "This program is freeware; modifying it  "
                dc.b "(full sourcecode included) is allowed   "
                dc.b "and in fact recommended!                "
                dc.b "                                        "
                dc.b "WWW: http://covertbitops.c64.org        "
                dc.b "Email: loorni`student.oulu.fi           "
                dc.b "                                        "
                dc.b "2. How to use                           "
                dc.b "                                        "
                dc.b "NinjaTracker is operated on keyboard;   "
                dc.b "here are the general keys:              "
                dc.b "                                        "
                dc.b "  Cursors     Move around               "
                dc.b "  Ins/Del     Delete rows               "
                dc.b "  Shift+Ins   Insert rows               "
                dc.b "  0-9, A-F    Edit hexadecimal data     "
                dc.b "  Shift+1,2,3 Enter tracks 1,2,3        "
                dc.b "  Shift+4     Enter sector (pattern)    "
                dc.b "  Shift+5,6,7 Enter wave/pulse/filttbl. "
                dc.b "  Shift+Z     Fast scroll up            "
                dc.b "  Shift+X     Fast scroll down          "
                dc.b "  F1          Play from song beginning  "
                dc.b "  F3          Stop playing              "
                dc.b "  F5          Play from selected pos.   "
                dc.b "  F7          Toggle fastforward mode   "
                dc.b "  F8          Enter help screen         "
                dc.b "             Enter disk menu           "
                dc.b "                                        "
                dc.b "2.1 Track editor special keys           "
                dc.b "                                        "
                dc.b "  ;:          Select song to work on    "
                dc.b "  SPACE       Mark playing position     "
                dc.b "  RETURN      Go to sector under cursor "
                dc.b "                                        "
                dc.b "2.2 Sector editor special keys          "
                dc.b "                                        "
                dc.b "  ;:          Select sector to work on  "
                dc.b "  0-7         Select octave             "
                dc.b "  AWSEDFTGY.. Enter notes like on piano "
                dc.b "  Shift+W     Wave command              "
                dc.b "  Shift+D     AD command                "
                dc.b "  Shift+S     SR command                "
                dc.b "  Shift+F     Filter command            "
                dc.b "  Shift+C     Copy pattern              "
                dc.b "  Shift+V     Paste pattern             "
                dc.b "  Shift+N     Transpose halfstep down   "
                dc.b "  Shift+M     Transpose halfstep up     "
                dc.b "  SPACE       Rest / empty (zero) column"
                dc.b "  RETURN      Go to wavetable entry     "
                dc.b "              under cursor (when in wave"
                dc.b "              column)                   "
                dc.b "                                        "
                dc.b "SPACE or RETURN also silences test note."
                dc.b "                                        "
                dc.b "3. The musicdata                        "
                dc.b "                                        "
                dc.b "3.1 Track data                          "
                dc.b "                                        "
                dc.b "There can be a maximum of 16 different  "
                dc.b "songs (subtunes), each with 3 tracks.   "
                dc.b "All songs share the same tables & 127   "
                dc.b "sectors.                                "
                dc.b "                                        "
                dc.b "Values in the track data:               "
                dc.b "                                        "
                dc.b "  00    Loop (followed by loop position)"
                dc.b "  01-7F Sector to play                  "
                dc.b "  80-BF Transpose upwards               "
                dc.b "  C0-FF Transpose downwards             "
                dc.b "                                        "
                dc.b "- Sector 00 has been reserved for song  "
                dc.b "  initialization and therefore can't be "
                dc.b "  referenced in the track data.         "
                dc.b "- A transpose command must be always    "
                dc.b "  followed by a sector number.          "
                dc.b "- Imagine the transpose being added to  "
                dc.b "  note number and then ANDed with 7F;   "
                dc.b "  therefore transpose FF is one halfstep"
                dc.b "  down and 81 is one halfstep up.       "
                dc.b "- A song that plays only once can be    "
                dc.b "  realized by creating one empty sector "
                dc.b "  (with just one rest note) and looping "
                dc.b "  to it indefinitely.                   "
                dc.b "                                        "
                dc.b "3.2 Sector data                         "
                dc.b "                                        "
                dc.b "A sector (pattern) consists of three    "
                dc.b "columns; from left to right they are:   "
                dc.b "                                        "
                dc.b "- Note/Command                          "
                dc.b "- Wavetable pointer/Command parameter   "
                dc.b "- Duration (using decimal notation)     "
                dc.b "                                        "
                dc.b "A note can range from C-0 to F-7 (use   "
                dc.b "transpose to reach the highest notes).  "
                dc.b "When a note is encountered, it will use "
                dc.b "the last wavetable pointer remembered,  "
                dc.b "or a new wavetable pointer if one exists"
                dc.b "on the wave column at same position.    "
                dc.b "                                        "
                dc.b "If duration column is empty then the    "
                dc.b "last remembered duration will be used.  "
                dc.b "Duration minimum is 2 and maximum is 65."
                dc.b "For longer notes, use the rest command. "
                dc.b "                                        "
                dc.b "Note 1: the packer isn't 'smart': to    "
                dc.b "save memory, you must make sure yourself"
                dc.b "there are no unnecessary duplicate      "
                dc.b "values.                                 "
                dc.b "                                        "
                dc.b "The commands:                           "
                dc.b "                                        "
                dc.b "  Rst - Rest, do nothing (except change "
                dc.b "        wavetable pointer, if exists)   "
                dc.b "  Wav - Change channel waveform (useless"
                dc.b "        if wavetable is also controlling"
                dc.b "        the waveform)                   "
                dc.b "  AD  - Change channel's Attack/Decay   "
                dc.b "  SR  - Change channel's Sustain/Release"
                dc.b "  Flt - Change filtertable pointer      "
                dc.b "        (global for all channels)       "
                dc.b "                                        "
                dc.b "Note 2: there are no zero-duration      "
                dc.b "commands; Wav,AD,SR,Flt imply a 'rest'  "
                dc.b "in addition to the action they perform. "
                dc.b "                                        "
                dc.b "An example. Let's assume that wavetable "
                dc.b "pointer 01 contains an instrument and 0A"
                dc.b "contains a vibrato loop (more of these  "
                dc.b "later)                                  "
                dc.b "                                        "
                dc.b "  C-3 01 12 Play note, dur. 16 frames   "
                dc.b "  Rst 0A -- Begin vibrato program + rest"
                dc.b "  SR  6A -- Set sustain & release + rest"
                dc.b "  Wav 40 36 Set waveform + rest         "
                dc.b "  D-3 01 12 Waveptr. 01 needed again now"
                dc.b "  E-3 -- -- but not for subsequent notes"
                dc.b "  F-3 -- -- with same instrument        "
                dc.b "                                        "
                dc.b "3.3 Wavetable data                      "
                dc.b "                                        "
                dc.b "The wavetable controls note/instrument  "
                dc.b "initialization fully (no separate instr."
                dc.b "data.) It consists of 3 columns, from   "
                dc.b "left to right:                          "
                dc.b "                                        "
                dc.b "- Waveform/command column               "
                dc.b "- Note/slidespeed column                "
                dc.b "- Pointer to next step-column           "
                dc.b "                                        "
                dc.b "The waveform column values are:         "
                dc.b "                                        "
                dc.b "  00    Note with waveform unchanged    "
                dc.b "  01-07 Legato note init (no hard-      "
                dc.b "        restart/ADSR setting)           "
                dc.b "  08    Hardrestart note init           "
                dc.b "  09-8F Waveform & note change          "
                dc.b "  90-FF Pitch slide (duration as        "
                dc.b "        negative value)                 "
                dc.b "                                        "
                dc.b "A note init occupies also the step      "
                dc.b "directly below it, the parameters are:  "
                dc.b "(an example)                            "
                dc.b "                                        "
                dc.b "  Note init command (here with HR)      "
                dc.b "  ]                                     "
                dc.b "  ]  Attack/Decay                       "
                dc.b "  ]  ]                                  "
                dc.b "  ]  ]  Sustain/Release                 "
                dc.b "  ]  ]  ]                               "
                dc.b "  08 08 8A                              "
                dc.b "  01 00 03                              "
                dc.b "  ]  ]  ]                               "
                dc.b "  ]  ]  Ptr to next wavetable step      "
                dc.b "  ]  ]                                  "
                dc.b "  ]  Filtertable ptr (00=unchanged)     "
                dc.b "  ]                                     "
                dc.b "  Pulsetable ptr (00=unchanged)         "
                dc.b "                                        "
                dc.b "An example of pitch slides (a vibrato   "
                dc.b "program, starting from step 01):        "
                dc.b "                                        "
                dc.b "  F8 00 02 Freq. unchanged for 8 frames "
                dc.b "  FD 02 03 Speed 2 slide up    3 frames "
                dc.b "  FD FC 04 Speed 4 slide down  3 frames "
                dc.b "  FD 04 03 Speed 4 slide up    3 frames,"
                dc.b "           loop back to previous step   "
                dc.b "                                        "
                dc.b "Notes 00-5F are relative notes and 80-DF"
                dc.b "are absolute (independent of note base  "
                dc.b "pitch). Examples of wave/note changes,  "
                dc.b "each example starting at step 01:       "
                dc.b "                                        "
                dc.b "  21 00 02 Sawtooth, note's base pitch  "
                dc.b "                                        "
                dc.b "  81 C8 02 High absolute noise          "
                dc.b "  41 00 03 Pulse, note's base pitch     "
                dc.b "                                        "
                dc.b "  00 00 02 A looping major arpeggio with"
                dc.b "  00 04 03 no waveform changes (now you "
                dc.b "  00 07 04 can use Wav-command in the   "
                dc.b "  00 0C 01 sector data for gate-off)    "
                dc.b "                                        "
                dc.b "Note: step 00 is reserved for pitch     "
                dc.b "slide, using it in the next step column "
                dc.b "causes unpredictable results (likely,   "
                dc.b "a previous pitch slide continues).      "
                dc.b "                                        "
                dc.b "To terminate a waveform program, it's   "
                dc.b "preferable to jump into a long, zero    "
                dc.b "speed pitch slide, that loops itself    "
                dc.b "indefinitely (step 01 in this example): "
                dc.b "                                        "
                dc.b "  90 00 01                              "
                dc.b "                                        "
                dc.b "3.4 Pulsetable data                     "
                dc.b "                                        "
                dc.b "The pulsetable consists of 3 columns,   "
                dc.b "from left to right:                     "
                dc.b "                                        "
                dc.b "- Duration column                       "
                dc.b "- Speed column                          "
                dc.b "- Pointer to next step-column           "
                dc.b "                                        "
                dc.b "A negative (80-FF) duration sets the    "
                dc.b "pulse to the value indicated in the     "
                dc.b "speed column.                           "
                dc.b "                                        "
                dc.b "Because of the peculiar nybble-reversed "
                dc.b "arithmetic used with pulse, you must    "
                dc.b "subtract one from all negative speeds   "
                dc.b "(speed FF is the same as 00!)           "
                dc.b "                                        "
                dc.b "An example of a pulse program:          "
                dc.b "                                        "
                dc.b "  80 20 02 Set pulse to value 20        "
                dc.b "  40 01 03 Pulse up (speed 1, 64 frames)"
                dc.b "  40 FE 02 Pulse down (speed 1, 64 fr.) "
                dc.b "                                        "
                dc.b "Unlike with wavetable, you can use step "
                dc.b "00 in the next step-column to end pulse-"
                dc.b "table execution.                        "
                dc.b "                                        "
                dc.b "3.5 Filtertable data                    "
                dc.b "                                        "
                dc.b "The filtertable consists of the same    "
                dc.b "columns and operates almost in the same "
                dc.b "way as the pulsetable.                  "
                dc.b "                                        "
                dc.b "Negative duration values are used to set"
                dc.b "filter passband, channels to be filtered"
                dc.b "and initial cutoff value.               "
                dc.b "                                        "
                dc.b "The high nybble of the duration value   "
                dc.b "(highest bit is ignored) is the pass-   "
                dc.b "band and low nybble is the bitmask of   "
                dc.b "channels to be filtered. Resonance is   "
                dc.b "hard-coded to F (highest value).        "
                dc.b "                                        "
                dc.b "If the initial cutoff value is zero, it "
                dc.b "will be left unchanged.                 "
                dc.b "                                        "
                dc.b "Examples of filter programs:            "
                dc.b "                                        "
                dc.b "  91 40 02 Lowpass on Chn1, cutoff 40   "
                dc.b "  7F 01 03 Up with speed 1, 127 frames  "
                dc.b "  7F FF 02 Down with speed 1, repeat    "
                dc.b "                                        "
                dc.b "  97 00 00 Lowpass on all channels,     "
                dc.b "           cutoff unchanged, stop filter"
                dc.b "           execution                    "
                dc.b "                                        "
                dc.b "4. Playroutine considerations           "
                dc.b "                                        "
                dc.b "The playroutine never skips wavetable   "
                dc.b "execution, but at the end of a sector   "
onlinehelpend:  dc.b "step, pulse execution is skipped for 2  "
                dc.b "frames. Also, filter exec is skipped    "
                dc.b "for 2 frames when channel 1 step ends.  "
                dc.b "                                        "
                dc.b "Wavetable programs shouldn't contain    "
                dc.b "note inits anywhere else than in the    "
                dc.b "very beginning. Otherwise note duration "
                dc.b "will be incorrect.                      "
                dc.b "                                        "
                dc.b "Like John Player, NinjaTracker does hard"
                dc.b "restart by setting test-bit for 1 frame."
                dc.b "This doesn't allow for the sharpest/most"
                dc.b "hifi attacks possible. Be cautious of   "
                dc.b "high sustain levels, the ADSR might bug!"
                dc.b "                                        "
                dc.b "5. The filemenu                         "
                dc.b "                                        "
                dc.b "Everything in here should be self-      "
                dc.b "explanatory. When packing/relocating,   "
                dc.b "you have to choose baseaddress and zero-"
                dc.b "page baseaddress, 5 zeropage bytes are  "
                dc.b "used.                                   "
                dc.b "                                        "
                dc.b "Init music: LDA #<song>; JSR <baseadr>  "
                dc.b "Play music: JSR <baseadr+3>             "
