.386

; . 2 . M . D . L .    * sound to mdl converter *
;
;                                    
; (c)oded 1995,1996 by                   
;   __                             ĿĳĿ
;  /_/_ _ _/_ _/ _ _ _               ĳٳ
; /  / ////// / / ////   of          
; \    - - -- \   - /

;v1.0 start of coding:  20.07.1995
;v1.0 release date:     22.10.1995
;v1.1 release date:     29.03.1996

;==== S T R U K T U R E N ===================================================

smpinf struc    ;SAMPLE-STRUCTUR
smpnam db 32 dup("-") ;name
smpfle db 08 dup("-") ;filename
smpfre dd 8363  ;frequenc
smplen dd 0     ;len
smprep dd 0     ;repeat-start
smprln dd 0     ;repeat-len
smpvol db 255   ;volume
smptyp db 0     ;bit 0=8/16b, 1=uni/bi, 2+3=packtyp, 4-7=0(unused)
smpinf ends

smpiln = 58

envinf struc	;ENVELOPE-STRUCTUR
envpos db 15 dup(0,0)	;15 * xdif/ypos
envsus db 0		;sustain, bit4=sustain on, bit5=loop on
envlop db 0		;bit0-3=start, bit4-7=end
envinf ends

enviln = 32

insinf struc	;INSTRUMENT-STRUCTUR (for 1 sample)
inssmp db 0	;sample-number
insrng db 0	;playrange-end (1-120)
insvol db 0	;sample-vol
insenv db 0	;sample-volenv,bit6=vol used,bit7=volenv used
inspan db 0	;sample-pan
insenp db 0	;sample-panenv,bit6=pan used,bit7=panenv used
insfad dw 0	;fadeout-speed
insvsp db 0	;vibrator-speed
insvde db 0	;vibrator-depth
insvsw db 0	;vibrator-sweep
insvfo db 0	;vibrator-form
insres db 0	;** reserved **
insenf db 0	;sample-frqenv,              bit7=frqenv used
insinf ends

insiln = 14

;==== M A C R O S ===========================================================

save    macro laenge,adresse
	mov cx,laenge
	mov dx,offset adresse
	mov ah,40h
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	cmp ax,cx
	jc mdlsv0
	endm

load    macro laenge,adresse
	mov cx,laenge
	mov dx,offset adresse
	mov ah,3fh
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	cmp ax,cx
	jc mdlsv0
	endm

chknul  macro reg
	local chknu1
	cmp dl,reg
	jnc chknu1
	mov ds:[bp],reg
	inc bp
chknu1: rcr dh,1
	endm

preenv	macro
db 01h,37h,04h,3Fh,05h,29h,07h,0Ch,05h,13h,09h,09h,38h
db 03h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,12h,63h,01h,25h,04h,3Ah,04h,2Ah,06h,08h,0Ah,16h,08h,08h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,32h,53h,01h,25h,04h,3Ah,04h,2Ah,06h,08h,0Ah,16h,08h,08h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,02h,53h,01h,36h,04h,3Dh,07h,3Dh,06h,36h,0Ch,2Ch,13h,1Ch,36h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,13h,64h,01h,3Fh,08h,14h,06h,0Ah,0Bh,07h,0Fh,06h,44h,02h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,10h,53h,01h,39h,05h,3Fh,0Ah,38h,08h,24h,0Eh,0Bh,19h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,03h,53h
endm

preenp	macro
db 01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,10h
db 13h,0Dh,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,21h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,1Ch
db 19h,2Ah,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,01h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,10h
db 13h,0Dh,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,21h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,1Ch
db 19h,2Ah,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,01h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,10h
db 13h,0Dh,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,21h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,1Ch
db 19h,2Ah,1Fh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,01h,70h
endm

preenf	macro
db 01h,1Fh,0Bh,34h,16h,3Fh,15h,3Bh,10h,31h,0Eh,23h,0Ch,15h,0Ch,06h,15h,00h,1Ah,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,12h,90h,01h,00h,1Ch,3Eh,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,21h,10h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,10h,13h,0Dh,1Fh,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,21h,70h,01h,20h,0Bh,2Ah,0Fh,2Fh,11h,2Ah,17h,13h,10h,0Fh,1Ch,19h,2Ah,1Fh,00h,00h,00h,00h,00h,00h
db 00h,00h,00h,00h,00h,00h,00h,00h,01h,70h,01h,1Fh,0Fh,26h,07h,18h,0Dh,2Ah,09h,10h,0Bh,2Fh,0Ah,09h,0Bh,34h,0Ah,05h,0Ch,38h,0Ah,00h
db 0Ch,3Fh,21h,1Ch,32h,11h,34h,1Fh,10h,0E0h,01h,3Fh,16h,3Fh,01h,00h,0Fh,00h,01h,13h,12h,13h,01h,06h,13h,06h,01h,31h,11h,31h,01h,1Eh
db 11h,1Eh,01h,32h,13h,31h,01h,06h,00h,10h
endm

;stacksegment
STCK    segment para stack use16 'stack'
	dw 128 dup(0)
STCK    ends

;datensegment fuer kaum gebrauchte datenmassen
DATA1   segment para use16 'data'

;==== D A T A S =============================================================

filmax = 1000		;maximale fileanzahl
dirlen = 12001          ;len catalog buffer
catalg db dirlen dup (0)
flgtab db 384 dup(0)

DATA1	ends

;main-datensegment
DATA    segment para use16 'data'

sndfil  db 13 dup(0)

;==== V A R I A B L E N =====================================================

envpre: preenv
enppre: preenp
enfpre: preenf
emstxt db "EMMXXXX0"

clrfuu db 0
edipt2 db 0
mespos db 0
mescrx db 0
mescry db 0
msmzgr dw 0
insmod db 0

noemtx db "No EMS 4.0 Driver found!",13,10,"$"
normtx db "Not enough conventional Ram.",13,10,"$"
no38tx db "No 386-CPU present!",13,10,"$"
nofitx db "No files found!",13,10,"$"

titltx:
db 10
db "DIGITRAKKER's 2MDL v1.1 -- written and (C) 1996 by prodatron/n-Factor --",13,10
db "  converts any soundmodule to a Digitrakker MDL-file",13,10
db 10,"$"                                        
helptx:
db "Syntax:   2MDL <filename>",13,10
db "Example:  2MDL *.mod",13,10
db "          ...converts all existing MOD-files to MDLs",13,10,10
db "Supported soundmodule-formats:",13,10
db "*.MDL -> Digitrakker, old and new MoDuLes",13,10
db "*.MOD -> Noisetracker, Protracker, Fasttracker, Taketracker...",13,10
db "*.S3M -> Screamtracker 3",13,10
db "*.XM  -> Fasttracker 2, Digitrakker",13,10
db "*.DMF -> X-Tracker",13,10
db "*.PTM -> Polytracker",13,10
db "*.MTM -> Multitracker",13,10
db "*.669 -> Composer 669",13,10
db "*.ULT -> Ultratracker",13,10
db "*.FAR -> Farandole Composer",13,10
db "*.DSM -> Dynamic Studio",13,10,"$"

redytx:
db 10,"Mission executed!",13,10,"$"

analysetxt db "____________: $"
readingtxt db "! reading... $"
writingtxt db "writing to ____________... $"
okwritetxt db "ok!",13,10,"$"
unknowntxt db "Unknown soundmodule-format! Skipping file...",13,10,"$"
readerrtxt db 13,10,"*** Error while reading file! ***",13,10,"$"
writerrtxt db 13,10,"*** Error while writing file! ***",13,10,"$"

typtab dw mdltxt,modtxt,s3mtxt,mtmtxt,ulttxt,c69txt,fartxt,xmtxt,ptmtxt,dsmtxt,dmftxt

mdltxt db "Digitrakker$"
modtxt db "Protracker$"
s3mtxt db "Screamtracker 3$"
mtmtxt db "Multitracker$"
ulttxt db "Ultratracker$"
c69txt db "Composer 669$"
fartxt db "Farandole Composer$"
xmtxt  db "Fasttracker 2$"
ptmtxt db "Polytracker$"
dsmtxt db "Dynamic Studio$"
dmftxt db "X-Tracker$"

;Disc-Variablen
ediold db 0
firsmp db 0
lassmp db 0
firins db 0
lasins db 0
dirpbf db 32 dup(0)
filnam db "--------.---",0
filanz dw 0     ;anzahl files im directory
dtabuf db 43 dup (0) ;vorruebergehende dta
dtaol1 dw 0     ;dta-adr
dtaol2 dw 0
tsmnot db 0
tsmnum db -1
tsmfil db 12 dup(0)
smdold db 0     ;alter sndmod
patrng dd 0

olddrv db "x:\"         ;start-drive
oldvrz db 64 dup (0)    ;start-verzeichnis

filnm2 db 13 dup(0)
dscjmp dw 0,code1	;adr der sound-lade-routine

xmh db "Extended Module: "
xmhnam db 20 dup(0),1ah
xmhcom db 20 dup(0),4,1,14h,1,0,0
xmhlen db 0,0
xmhrep db 0,0
xmhcan db 0,0
xmhpan db 0,0
xmhian db 0,0,0,0
xmhspd db 0,0
xmhbpm db 0,0
xmhlst db 256 dup(0)
xmpnot db 0
xmpins db 0
xmpvol db 0
xmpcmd db 0
xmpdat db 0
xmstab db 16*4 dup(0)
xmsanz db 0
xmpat  dw 0
xmpate dw 0
xmchnp dw 0
xmchn5 db 32 dup(0)
xmchng db 32 dup(0)
xmchnh db 32 dup(0)

notfrq: ;perioden-tabelle fuer alle 9 octaven
dw 54730,51658,48759,46022,43439,41001,38700,36528,34477,32542,30716,28992 ;0
dw 27365,25829,24379,23011,21719,20500,19350,18264,17239,16271,15358,14496 ;1
dw 13682,12914,12190,11505,10860,10250,09675,09132,08619,08136,07679,07248 ;2
dw 06841,06457,06095,05753,05430,05125,04837,04566,04310,04068,03839,03624 ;3
dw 03421,03229,03047,02876,02715,02563,02419,02283,02155,02034,01920,01812 ;4
dw 01710,01614,01524,01438,01357,01281,01209,01141,01077,01017,00960,00906 ;5
dw 00855,00807,00762,00719,00679,00641,00605,00571,00539,00508,00480,00453 ;6
dw 00428,00404,00381,00360,00339,00320,00302,00285,00269,00254,00240,00226 ;7
dw 00214,00202,00190,00180,00170,00160,00151,00143,00135,00127,00120,00113 ;8
dw 00107,00101,00095,00090,00085,00080,00076,00071,00067,00064,00060,00057 ;9

;==== S O N G - V A R I A B L E N ===========================================

;**************************************************************
;alle folgenden variablen werden von der sound-routine benutzt!
;**************************************************************

;sound-module variablen

sngnam db 32 dup("-")           ;songname
sngcom db 20 dup("-")           ;composer-name
snglen db 1,0                   ;songlaenge
sngrep db 0,0                   ;songrepeat
sngvol db 255                   ;main-volume
sngspd db 6                     ;songspeed
sngbpm db 125                   ;beats per minute
sngchn db 8 dup(0,127),8 dup(128,255) ;kanal-status
snglst db 255 dup(0)            ;song-liste
chnnam db 32*8 dup("-")		;channel-namen

sngmes db 64*76 dup(" ")        ;song-message
patnam db 255*16 dup("-")
patlen db 255 dup(63)

envdat envinf 64 dup(<>)	;vol-envelope-daten
enpdat envinf 64 dup(<>)	;pan-envelope-daten
enfdat envinf 64 dup(<>)	;frq-envelope-daten
smpdat smpinf 256 dup(<>)       ;sampledaten
smpofs dd 256 dup(0)            ;sampleadr im memory (256er auch!)

sngfil db "--------",0 ;filename
sngpos db 0     ;aktuelle songposition
trkpos db 0,0   ;kanal-position (0-28)
edipat db 0     ;nummer des gerade bearbeiteten pattern
insnum db 0	;nummer des aktuellen instruments (1-255)
smpins db 0	;position des instrumenten-samples
smpnum db 0     ;nummer des aktuellen sample (1-255)
octave db 4     ;octave (0-8)
sndmod db 0     ;0=aus, 1=song, 2=patternplay
sndtim db 0,0,0
patanz db 0     ;anz.belegter pattern

pmmold dd 0
patofs dd 255 dup(0)	;patadr ab 0

lodbuf db 8192 dup(0)   ;buffer fuer discoperationen
mssaln dd 0
mssaps dd 0
cnvcom db "*Converted ????File*"

extpos dw 0

DATA    ends

;codesegment
CODE    segment para use16 'code'
	assume cs:code, ds:data, ss:stck

usechn db 0
trkmax db 28    ;maximale trakpos
trkaol db 1     ;alte trk-displ-anz
otmcnt dw 0     ;counter, nachdem alter irq0 aufgerufen wird
otmadr dd 0     ;adr der alten irq0-routine
bpmser dd 0     ;servo-register fuers bpm-timing
bpmadd dd 0     ;ueberlauf-reg fuers bpm-timing
inscnt dw 0     ;counter fuer vol-ramps
chnuse db 0     ;anzahl benutzter kanaele

notpos db 0     ;position im pattern (0-63)
edipln db 0	;laenge des gerade bearbeiteten pattern -1
edipl1 dw 0
notps1 db 0     ;naechste pos im pattern (fuer patbreak)

;==== C S - V A R I A B L E N ===============================================

datseg dw data
dt1seg dw data1
codseg dw code
cd1seg dw code1
emsseg dw 0     ;segment der page-frame
patseg dw 0     ;pattern-segment
patse1 dw 0
patse3 dw 0     ;editor-patter/track-buffer (48k)
sbfseg dw 0     ;sample-buffer(64k)gebraucht von:csmlen,lodsmp,smpfil,mdlsv
insseg dw 0	;instrument-segment
envseg dw 0	;segment des environment-blocks
pspseg dw 0	;segment des psp
emspag dw 0	;nummer der ersten eingeblendeten ems-page

patmem dd 0	;laenge des gesamten pattern-speichers
pathnd dw 0     ;speicher handle fuer pattern
loganz db 0,0	;anzahl allokierter logischer ems-pages fuer pattern

sblmem dd 0	;fuer sb-sample-mem
sblhnd dw 0
sblanz db 0,0

memtyp db 0     ;0=ems

;laden/speichern
sndjmp dw f_mdlld,f_modld,f_s3mld,f_mtmld,f_ultld,f_c69ld,f_farld,f_xmld,f_ptmld,f_dsmld,f_dmfld
fhandl dw 0     ;handle-nr.
kennbt db "M.K.FLT46CHN6CHNOCTA8CHN"
numchn db 0
ftfreq dw 8363,8413,8463,8529,8581,8651,8723,8757,7895,7941,7985,8046,8107,8169,8232,8280
panmod db 16,111,111,16,16,111,111,16,16,111,111,16,16,111,111,16,16,111,111,16,16,111,111,16,16,111,111,16,16,111,111,16
cvmjmp dw cvmd0,cvmd1,cvmd2,cvmd3,cvmd4,cvmd5,cvmd6,cvmd7
       dw cvmd8,cvmd9,cvmda,cvmdb,cvmdc,cvmdd,cvmde,cvmdf
cvmejp dw cvme0,cvme1,cvme2,cvme3,cvme4,cvme5,cvme6,cvme7
       dw cvme8,cvme9,cvmea,cvmeb,cvmec,cvmed,cvmee,cvmef
sgnmsk db 0
sgnjmp dw 0,code
sgntyp dw 0
clslen dd 0
crnlen dd 0
dcblen dw 0
dcziel dd 0
cvmchn db 0
cvmovl db 32 dup(0)
ldslen dd 0
ldajmp dw lodsm0
mtmexl dw 0
mtmsnm db 0
s3msln db 0
s3mcmx db 0
s3mpan db 0
ultvs  db 0	;format-version
ultchn db 0	;anzahl channels
ultcps db 0	;akt.channel
ultpa  db 0
cnvbuf db 0,0,0,0
c69snm db 0
xmchns db 0
xmlast dw 0
xmvcmd dw 0
xmfine db 0
xmins  db 0
xmsmp  db 0
xmpre  dd 0
xmakt  db 0
notxmf dd 65536,69432,73561,77935,82570,87480,92681,98193,104031,110217,116771,123715
finxmf dd 65536,65565,65595,65624,65654,65684,65713,65743,65773,65802,65832,65862,65891,65921,65951,65981,66010,66040,66070,66100,66130,66160,66189,66219,66249,66279,66309,66339,66369,66399,66429,66459,66489,66519,66549,66579,66609,66639,66669,66699,66729
dd 66759,66789,66820,66850,66880,66910,66940,66971,67001,67031,67061,67092,67122,67152,67182,67213,67243,67273,67304,67334,67365,67395,67425,67456,67486,67517,67547,67578,67608,67639,67669,67700,67730,67761,67792,67822,67853,67883,67914,67945,67975
dd 68006,68037,68067,68098,68129,68160,68190,68221,68252,68283,68314,68344,68375,68406,68437,68468,68499,68530,68561,68592,68623,68654,68685,68716,68747,68778,68809,68840,68871,68902,68933,68964,68995,69026,69057,69089,69120,69151,69182,69213,69245
dd 69276,69307,69339,69370,69401

dmflnd db 0	;last node (sample-depacking)
dmfcnd db 0	;node count
dmfglo dw 0	;dmf global effect-buffer -> low=data,high=num
dmfbet db 0	;dmf beat (notenzeilen pro beat)
dmfbpm db 125	;dmf bpm ([t/s]=dmfbpm*dmfbet/60)
dmftik db 33	;dmf ticks ([t/s]=dmftik/4+1)
dmfspd db 0 	;flag, ob speed neu setzen => bpm=[t/s]*speed*125/50, speed=4
dmftyp db 0	;flag, ob ticks oder bpm

smpsjp dw 0
csslen dd 0
cssadr dd 0
csspos dd 0
crn16b db 0 ;1x=8bit,00=16bit low,01=16 bit high
sasaln dd 0
idamdl = 11
idaist = 6
idtmdl db "INPATRISSAMEPNIIVEPEFE"
idtist db "IIVEPEISSAFE"
idanz db 0
idadr dd idamdl dup(0)
idcnt db 0
idnow dd 0
mdlver	db 0	;format-version
mstrmx  dw 0
mstrad  dw 0
mstrnm  dw 0    ;anzahl tracks
mstrfp  dd 0    ;pos der trackinfos im file
mstrln  dd 0    ;gesamtlen der tracks

;==== P R O G R A M M =======================================================

start:	mov ax,ds:[2ch]
	mov cs:envseg,ax
	mov cs:pspseg,ds
	call setfree
	cld
	mov ds,cs:datseg
        mov dx,offset titltx    ;titel
        call prttxt
        call cmdget
        mov dx,offset helptx    ;help
        jc enderr
        call konfig             ;386
        jc enderr
        call extmem             ;EMS
        mov dx,offset noemtx
        jc enderr
        mov ah,48h              ;RAM
	mov bx,((48+64+64)*1024)/16
	int 21h
        mov dx,offset normtx
        jc enderr
        mov cs:patse3,ax
	add ax,48*1024/16
	mov cs:sbfseg,ax
	add ax,64*1024/16
	mov cs:insseg,ax
        call musini

        call getdir
        cmp filanz,0
        mov dx,offset nofitx
        jz ender1
        mov si,offset catalg
tomdl:  mov ds,cs:dt1seg
        mov es,cs:datseg
        mov di,offset filnam
        mov cx,12/2
        rep movsw
        mov ds,cs:datseg
        push si

        mov di,offset filnam
        mov cx,9
tomdl1: cmp [di],byte ptr "."
        jz tomdl2
        inc di
        loop tomdl1
        mov di,offset filnam+9
tomdl2: mov extpos,di

        call ldsnd
        jc tomdl3

        mov di,extpos
        mov dword ptr [di],"LDM."

	mov bx,offset sngchn+31
	mov cx,31
setvo1: test [bx],byte ptr 128
	jz setvo2
	dec bx
	loop setvo1
setvo2: inc cl
	mov cs:usechn,cl

        call makcrn
        call clrem0
        call svsnd
tomdl3: pop si
        dec filanz
        jnz tomdl
        mov dx,offset redytx
        call prttxt
msdos0: call smpres
        mov ah,49h      ;pattern-buffer freigeben
	mov es,cs:patse3
	int 21h
        call deapat     ;pattern-mem freigeben
msdos:  mov ax,4c00h    ;zurueck ins dos
	int 21h

ender1: call prttxt
        jmp msdos0

enderr: call prttxt
        jmp msdos

prttxt: mov ah,9        ;text-ausgabe
	int 21h
        ret

;==== S U B - R O U T I N E N ===============================================

; SUENV => bp=vol-/pan-ofs (dh=maske) => nach unbenutzer env/enp/smp suchen
;	=> al=num (255=nix)
suenv	proc near
	mov dh,63
	call suenv0
	jmp suenv5
;bp=ofs,dh=mask(63/255) => flgtab setzen => si=flgtab
suenv0: mov cl,255
	sub si,si
;si=inst,cl=anz
suen00:	mov es,cs:dt1seg	;flag-tab loeschen
	mov di,offset flgtab
	sub ax,ax
	push cx
	mov cx,256/2
	rep stosw
	pop cx
	mov fs,cs:insseg	;benutzte env/enp/smp eintragen
suenv1:	mov ch,16
	add si,32
suenv2:	movzx bx,fs:[si.bp]
	and bl,dh
	mov es:[bx.flgtab],1
	add si,14
	dec ch
	jnz suenv2
	loop suenv1
	mov si,offset flgtab
	ret
;si=flgtab,ah=anz => flgtab durchsuchen
suenv5:	mov ah,64		;unbenutzte suchen
suenv6:	sub al,al
suenv3:	cmp es:[si],byte ptr 0
	jz suenv4
	inc si
	inc al
	dec ah
	jnz suenv3
	mov al,-1
suenv4:	ret
suenv	endp

; CLREMP => alle unbenutzten, leeren pattern loeschen
clrem0: sub ah,ah		;testen, ob unbenutzte pattern vorhanden
	mov si,offset snglst
	movzx cx,snglen
clrem1:	lodsb
	cmp ah,al
	jnc clrem2
	mov ah,al
clrem2:	loop clrem1
	inc ah		;ah=anz.benutzter pattern
	cmp ah,patanz
	jc clrem3
	ret
clrem3:	mov clrfuu,ah
	mov al,edipat
	mov edipt2,al
	mov al,patanz
	dec al
	mov edipat,al
clrem4:	call setpat
	mov es,cs:patseg
	sub di,di
	mov ax,32*6/4
	mul cs:edipl1
	mov cx,ax
	sub eax,eax
	repz scasd
	jnz clrem5
	dec edipat
	mov al,clrfuu
	cmp edipat,al
	jnc clrem4
clrem5: movzx cx,patanz
	sub cl,edipat
	mov edipat,0
	dec cl
	jz clrem7
clrem6:	push cx
	call delpat
	pop cx
	loop clrem6
clrem7: mov al,edipt2
	cmp al,patanz
	jc clrem8
	sub al,al
clrem8:	mov edipat,al
	call setpat
        ret

; INCLR => al=num(ab 0) => instrument loeschen
inclr	proc near
	mov ah,al
	mov al,32+15*insiln+inssmp
	mov di,ax
	mov cx,16
	mov es,cs:insseg
inclr1: sub al,al		;samples loeschen
	xchg al,es:[di]
	sub di,insiln
	cmp al,1
	jc inclr2
	sub si,si		;sample in anderen ins suchen
	mov dl,255
inclr3:	add si,32
	mov dh,16
inclr4:	cmp al,es:[si.inssmp]
	jz inclr2
	add si,insiln
	dec dh
	jnz inclr4
	dec dl
	jnz inclr3
	dec al
	mov smpnum,al		;sample loeschen
	push cx
	push di
	push es
	call smclr1
	pop es
	pop di
	pop cx
inclr2:	loop inclr1
	add di,insiln-inssmp-32	;instrument resetten
	jmp iniin0
inclr	endp

clrsm0:	mov bx,offset smpdat+smplen
	mov di,offset smpofs
	mov cx,255
	sub eax,eax
clrsm3:	mov [bx],eax
	mov [di],eax
	add bx,smpiln
	add di,4
	loop clrsm3
	call smpres
	mov firsmp,1
	mov lassmp,255

clrsm1: mov al,smpnum
	push ax
	mov al,lassmp
	mov smpnum,al
clrsm2: dec smpnum
	call smclr1
	mov al,firsmp
	cmp smpnum,al
	jnc clrsm2
	pop ax
	mov smpnum,al
        ret

smclr1:	sub ecx,ecx
	call csmlen
smclr2:	call smpadr
	mov si,bx
	mov di,si
	add di,smpnam
	mov eax,"----"
	sub ebx,ebx
	mov cx,32/4
	mov es,cs:datseg
	rep stosd
	mov di,si
	add di,smpfle
	stosd
	stosd
	mov [si.smpfre],8363
	mov [si.smprep],ebx
	mov [si.smprln],ebx
	mov [si.smptyp],bl
	ret

; SMPADR => datenoffset von aktuellem sample => bx=datenoffset
smpadr  proc near
	mov bx,ax
	mov al,smpnum
	mov ah,smpiln
	mul ah
	add ax,offset smpdat
	xchg bx,ax
	ret
smpadr  endp

; GETLEN => samplelaenge holen => ecx=len
getlen  proc near
	call smpadr
	mov ecx,[bx.smplen]
	or ecx,ecx
	ret
getlen  endp

; SETFREE => uebrigen speicherplatz freimachen
setfree proc near
	mov ax,offset prgend
	add ax,15
	shr ax,4
	mov bx,cs:cd1seg
	add bx,ax       ;bx=segadr hinter codeseg
	mov ax,es       ;ax=seg von psp
	sub bx,ax       ;bx=prglen in paras
	mov ah,4ah      ;nur diesen Speicher weiterhin reservieren
	int 21h
	ret
setfree endp

; GETDIR => gewuenschte filenamen nach [catalg] (filmax*12) => filanz=anz
getdir  proc near
	mov di,offset catalg
	mov gs,cs:dt1seg
	mov ah,2fh
	int 21h
	mov dtaol1,es
	mov dtaol2,bx
	mov dx,offset dtabuf
	mov ah,1ah
	int 21h
	mov es,cs:datseg
	sub bx,bx       ;bx=counter
        mov dx,offset sndfil
	mov ah,4eh
srcfi1: int 21h
	jc scrfi2
        mov si,offset dtabuf+30
        and [si-9],byte ptr 16
        jnz srcfi3
	inc bx          ;file gefunden -> zaehler+1
        push di
srcfi4: lodsb
	mov gs:[di],al
	inc di
	or al,al
        jnz srcfi4
        pop di
        add di,12
srcfi3: cmp bx,filmax
        mov ah,4fh
        jnz srcfi1
scrfi2: mov ds,dtaol1
	mov dx,dtaol2
	mov ah,1ah
	int 21h
	mov ds,cs:datseg
        mov filanz,bx
	ret
getdir  endp

ldiff6:	push cx
	push si
	shr cx,1
ldiff8:	lodsw
	xchg al,ah
	mov [si-2],ax
	loop ldiff8
	pop si
	pop cx
	jmp smpsto

; LDSND => sound-mod laden
ldsnd:  mov si,offset filnam
        mov di,offset analysetxt
        mov cx,12
        mov ax,cs:datseg
        mov es,ax
        mov ds,ax
        rep movsb
        mov dx,offset analysetxt
        call prttxt

        mov gs,cs:codseg
	call far ptr autdet
	cmp bl,254
        mov dx,offset unknowntxt
        jz ldsnd0
        mov dx,offset readerrtxt
        jnc ldsnd0
        add bl,bl               ;module-routine auswaehlen
	sub bh,bh

        push bx
        mov dx,[bx.typtab]
        call prttxt
        mov dx,offset readingtxt
        call prttxt
        pop bx

	mov dx,cs:[bx.sndjmp]
	mov dscjmp,dx
	call iniins
	mov msmzgr,offset sngmes
	mov gs,cs:codseg
	call dword ptr dscjmp	;sound aus geoeffneter datei laden
        mov dx,offset readerrtxt
        jc svsnd0
        mov es,cs:datseg        ;sng-pars resetten
	mov si,offset filnam
	mov di,offset sngfil
	mov cx,4
	rep movsw
        mov bx,cs:fhandl        ;datei schliessen
	mov ah,3eh
	int 21h
        mov dx,offset readerrtxt
        jc ldsnd0
        ret

ldsnd0: call prttxt
        stc
        ret

; SVSND => sound-modul speichern (mdl)
svsnd:  mov si,offset filnam
        mov di,offset writingtxt+11
        mov cx,12
        mov ax,cs:datseg
        mov es,ax
        mov ds,ax
        rep movsb
        mov dx,offset writingtxt
        call prttxt

        mov ah,3ch              ;datei erstellen
	sub cx,cx
	mov dx,offset filnam
	int 21h
        mov dx,offset writerrtxt
        jc ldsnd0
        mov cs:fhandl,ax
	mov gs,cs:codseg
	call far ptr f_mdlsv	;mdl-file speichern
        mov dx,offset writerrtxt
        jc svsnd0
        mov dx,offset okwritetxt
        call prttxt
        mov bx,cs:fhandl        ;datei schliessen
	mov ah,3eh
	int 21h
        clc
        ret

svsnd0: push dx
        mov bx,cs:fhandl        ;datei schliessen
	mov ah,3eh
	int 21h
        pop dx
        call prttxt
        stc
        ret

;==== S U B - R O U T I N E N ===============================================

; CMDGET => holt [sndfil] aus der commando-zeile => cf=0 ok
cmdget	proc near
	mov es,cs:pspseg
	cmp es:[80h],byte ptr 0
	jz cmdge0
	mov bx,81h
	cmp es:[bx],byte ptr 0
	jz cmdge0
cmdge1: mov al,es:[bx]          ;loop
	inc bx
	cmp al,0dh
	jz cmdge0
	cmp al," "
	jz cmdge1
        mov di,offset sndfil    ;file holen
	sub cl,cl
cmdge2: mov [di],al
	inc cl
	cmp cl,13
        jnc cmdge3
	inc di
cmdge3: mov al,es:[bx]
	inc bx
	cmp al,0dh
        jz cmdge4
	cmp al," "
        jnz cmdge2
cmdge4: mov [di],byte ptr 0
        clc
        ret
cmdge0: stc
        ret
cmdget	endp

; INIINS => instrumenten-segment initialisieren
iniins	proc near
	mov es,cs:insseg
	xor di,di
	mov bp,255
iniin1:	call iniin0
	dec bp
	jnz iniin1
	mov es,cs:datseg
	mov di,offset envdat	;envelopes resetten
	mov si,offset envpre
	call inien1
	mov di,offset enpdat
	mov si,offset enppre
	call inien1
	mov di,offset enfdat
	mov si,offset enfpre
inien1:	mov dl,64
inien2:	mov cx,enviln/2
	rep movsw
	sub si,enviln
	dec dl
	jnz inien2
	ret

iniin0:	mov al,"-"
	mov cx,32
	rep stosb
	mov cx,16
	sub ax,ax
iniin2:	stosw    		;smpnum,range
	mov ax,255+256*64	;vol,volenv,volflags
	stosw
	mov ax,64		;pan,panenv,panflags
	stosw
	mov ax,0ffffh		;fadeout-speed
	stosw
	sub ax,ax		;vibrato-paras,reserved
	stosw
	stosw
	stosw
	loop iniin2
	ret
iniins	endp

; KONFIG => test, ob 386 => cf=1 error
konfig  proc near
	xor ax,ax       ;386er test
	push ax
	popf
	pushf
	pop ax
	and ax,0f000h
	cmp ax,0f000h
	mov si,offset no38tx
	stc
	jz konfi1
	mov ax,07000h
	push ax
	popf
	pushf
	pop ax
	and ax,07000h
	stc
	jz konfi1
        clc             ;gefunden
konfi1: mov dx,si
	ret
konfig  endp

; MAKCRN => alle samples mit crunch-status versehen (8bit=1, 16bit=2)
makcrn	proc near
	mov bx,offset smpdat+smptyp
	mov cx,255
	mov dl,0f3h
makcr1: mov ah,[bx]
	and ah,1
	inc ah
        and ah,3
	shl ah,2
	and [bx],dl
	or [bx],ah
	add bx,smpiln
	loop makcr1
	ret
makcrn	endp

;==== P A T T E R N - S P E I C H E R V E R W A L T U N G ===================

; EXTMEM => feststellen, ob und welcher erweiterungs-mem verfgbar => cf=0 ok
extmem  proc near
	mov ax,3567h    ;ems suchen
	int 21h
	mov di,10
	mov si,offset emstxt
	mov cx,8
extme1: cmpsb
	jnz extme2
	loop extme1
	mov ah,46h      ;ems-version bestimmen
	int 67h
	or ah,ah
	jnz extme2
	shr al,4
	cmp al,4
	jc extme2
	mov cs:memtyp,0
	mov ah,41h      ;page-frame holen
	int 67h
	or ah,ah
	jnz extme2
	mov cs:emsseg,bx
        mov patanz,ah
        mov cs:loganz,ah
	ret
extme2: stc             ;*** hier: eventuell XMS
	ret
extmem  endp

; INSPAT => al=len-1 => neuen pattern anlegen => patanz=patanz+1 => cf=0 ok
inspat  proc near
	cmp patanz,255
	cmc
	jc inspa0
	sub ah,ah
	push ax
	inc ax
	mov dx,32*6
	mul dx
	movzx eax,ax	;eax=patlen
	push cs:patmem
	add eax,cs:patmem
	mov ecx,eax
	call cptmem
	pop eax
	pop cx
	jc inspa0
	movzx bx,patanz
	mov edipat,bl
	mov [bx.patlen],cl
	shl bx,2
	mov [bx.patofs],eax
	inc patanz
	call setpat
	mov ax,cs:edipl1
	mov dx,32*6/4
	mul dx
	mov cx,ax
	sub eax,eax
	mov di,ax
	mov es,cs:patseg
	rep stosd
inspa1:	clc
inspa0:	ret
inspat	endp

; DEAPAT => alle pattern freigeben => patanz=0
deapat  proc near
	sub ecx,ecx
	mov patanz,cl
	jmp cptmem
deapat  endp

; DELPAT => letzten pattern freigeben => patanz=patanz-1
delpat  proc near
	movzx bx,patanz
	sub bl,1
	jc inspa0
	mov patanz,bl
	movzx ax,[bx.patlen]
	inc ax
	mov dx,32*6
	mul dx
	cwde
	neg eax
	add eax,cs:patmem
	mov ecx,eax
delpat	endp

; CPTMEM => ecx=neue laenge => pattern-memory veraendern => cf=0 ok
cptmem	proc near
	mov eax,cs:patmem
	mov pmmold,eax
	cmp cs:patmem,0
	mov cs:patmem,ecx
	jnz cptme2
	add ecx,16383		;mem neu anlegen
	shr ecx,14
	jz inspa1
	mov bx,cx
	mov cs:loganz,bl
	mov ah,43h
	int 67h
	cmp ah,1
	cmc
	jnc cptme1
	mov cs:loganz,0
	mov cs:patmem,0
	ret
cptme1:	mov cs:pathnd,dx
	ret
cptme2: add ecx,16383
	shr ecx,14
	jnz cptme3
	mov ah,45h		;mem freigeben
	mov dx,cs:pathnd
	int 67h
	mov cs:loganz,0
	clc
	ret
cptme3: mov ah,51h		;mem veraendern
	mov dx,cs:pathnd
	mov bx,cx
	push bx
	int 67h
	pop bx
	cmp ah,1
	cmc
	jc cptme4
	mov cs:loganz,bl
	ret
cptme4: mov eax,pmmold
	mov cs:patmem,eax
	ret
cptmem	endp

; RESPAT => al=anzahl => mem fuer al-pattern reservieren => cf=0 ok
respat  proc near
	push ax
	call deapat
	pop cx
	sub ch,ch
respa1: push cx
	mov al,63
	call inspat
	pop cx
	jc respa2
	loop respa1
	clc
respa2: ret
respat  endp

; SETTRK => ax=track-nummer => track einblenden => patse1:si=track
settrk  proc near
	mov si,offset patse1
	push ax
	shr ax,5
	call setpt1
	pop ax
	and al,31
	mov ah,6
	mul ah
	mov si,ax
	ret
settrk  endp

; SETPAT => pattern in edipat einblenden
setpat  proc near
	mov si,offset patseg
	mov al,edipat
setpt1: movzx bx,al
	movzx ax,[bx.patlen]
	mov cs:edipln,al
	inc ax
	mov cs:edipl1,ax
	shl bx,2
	mov eax,[bx.patofs]	;eax=adr im ems-ram
	mov bx,ax
	shr eax,14		;ax=erste page
	and bx,16383
	shr bx,4
	add bx,cs:emsseg	;bx = (patofs mod 16384)/16+emsseg = patseg
	mov cs:[si],bx
	mov bx,ax
	mov cs:emspag,ax
setpt0:	mov dx,cs:pathnd
setpt2:	mov ax,4400h    ;mapping setzen
	push bx
	push dx
	int 67h
	pop dx
	pop bx
	mov ax,4401h
	inc bx
	push bx
	push dx
	int 67h
	pop dx
	pop bx
	mov ax,4402h
	inc bx
	push bx
	push dx
	int 67h
	pop dx
	pop bx
	mov ax,4403h
	inc bx
	int 67h
	ret
setpat  endp

;==== S A M P L E - S P E I C H E R V E R W A L T U N G =====================

; CSMLEN => ecx=laenge => aendert groesse des aktuellen samples => cf=1 nomem
csmlen  proc near

	bt cx,0			;laenge gerade aufrunden, falls noetig
	adc ecx,0
	call smpadr
	cmp [bx.smplen],0
	jz csmle9		;alte len=0 -> sample hinten dranhaengen
	mov edx,ecx
	sub ecx,[bx.smplen]
	jz csmle4		;neue=alte laenge -> fertig!!
	jnc csmle5		;neue>alte

csmle1:	mov [bx.smplen],edx	;*** in alter bank lassen, len eintragen
	movzx bx,smpnum
	push bx
	mov bl,cs:[bx.smpbnk]
	shl bl,2
	mov eax,cs:[bx.bnklen]	;eax=banklaenge
	push ecx
	add ecx,eax
	call csmmem		;memory-groesse veraendern
	pop ecx
	mov ebp,cs:[bx.bnkofs]
	pop bx
	shl bx,2
	add bx,offset smpofs
	mov edi,[bx]
	add edi,edx		;ziel   = smpofs + neue laenge
	mov esi,edi
	sub esi,ecx		;quelle = smpofs + alte laenge
	add eax,ebp
	sub eax,esi		;len    = banklaenge - quelle + bankoffset
	jz csmle4		;keine folgenden samples -> fertig!!
	push ecx
	mov ecx,eax
	call mvsmbl
	pop ebp
	mov si,offset smpbnk	;(si)=banknummern
	mov di,offset smpofs	;(di)=smpoffsets
	movzx bx,smpnum
	mov al,cs:[bx.smpbnk]	;al=aktuelle banknummer
	shl bx,2
	mov edx,[bx.smpofs]
	mov cx,255
csmle2:	cmp al,cs:[si]
	jnz csmle3
	cmp [di],edx
	jbe csmle3
	add [di],ebp		;offsets folgender samples korrigieren
csmle3:	add di,4
	inc si
	loop csmle2
	clc
csmle4:	ret

csmle5: push bx			;*** sample vergroessern
	movzx bx,smpnum
	mov al,cs:[bx.smpbnk]
	mov bl,al
	shl bl,2
	push ecx
	mov edi,cs:[bx.bnklen]
	push edi
	add ecx,edi
	call csmmem
	pop ecx
	jc csmled
	call csmmem		;passt in selbe bank, verschieben
	pop ecx
	pop bx
	jmp csmle1
csmled: pop ecx
	pop bx
	sub ah,ah		;andere freie bank suchen
	sub bx,bx
csmle6: cmp al,ah
	jz csmle7
	mov esi,cs:[bx.bnklen]
	add esi,edx
	push ecx
	mov ecx,esi
	call csmmem
	pop ecx
	jnc csmle8		;bank mit genuegend platz gefunden
csmle7:	add bx,4
	inc ah
	cmp ah,cs:bnkanz
	jnz csmle6
	stc			;keine freie bank mehr -> memory full
	ret
csmle8:	sub esi,edx
	add esi,cs:[bx.bnkofs]	;neue ofs
	push esi		;neuofs(esi),bnknum(ah),neulen(edi) sichern
	push ax
	push edx
	mov edi,esi		;ziel   = neuer offset
	sub edx,ecx
	mov ecx,edx		;laenge = neue - (neue - alte) = alte laenge
	push ecx
	movzx bx,smpnum
	shl bx,2
	mov esi,[bx.smpofs]	;quelle = alter offset
	call mvsmbl
	pop ecx
	neg ecx
	sub edx,edx
	call smpadr
	call csmle1		;sample aus alter bank loeschen
	pop ecx
	pop ax
	pop esi
csmlec:	movzx bx,smpnum
	mov cs:[bx.smpbnk],ah	;neue bank eintragen
	shl bx,2
	mov [bx.smpofs],esi	;neuen offset eintragen
	call smpadr
	mov [bx.smplen],ecx	;neue laenge eintragen
	clc
	ret

csmle9:	sub ah,ah		;*** sample an freie bank dranhaengen
	sub bx,bx
csmlea: mov esi,cs:[bx.bnklen]
	push ecx
	add ecx,esi
	call csmmem
	pop ecx
	jnc csmleb		;frei bank gefunden
	add bx,4
	inc ah
	cmp ah,cs:bnkanz
	jnz csmlea
	stc			;keine freie bank mehr -> memory full
	ret
csmleb:	add esi,cs:[bx.bnkofs]
	jmp csmlec

csmlen  endp

; CHGLEN => ecx=len => smplen aendern, eventuell ende fuellen
chglen  proc near
	bt cx,0
	adc ecx,0
	push ecx
	call getlen
	pop edx
	xchg ecx,edx
	push ecx
	push edx
	call csmlen
	pop edx         ;alte
	pop ecx         ;neue
	jnc chgle1      ;mem full?
chgle0: ret
chgle1: cmp edx,ecx
	jnc chgle0      ;alte>=neue -> ok
	movzx bx,smpnum
	shl bx,2
	mov edi,[bx.smpofs]
	add edi,edx
	sub ecx,edx
	jz chgle2
	sub ax,ax
	call smpfil
chgle2: clc
	ret
chglen  endp

; MVSMBL => esi=quelle,edi=ziel,ecx=laenge => block im samplemem verschieben
mvslen  dd 0

mvsmbl  proc near
	mov cs:mvslen,ecx
	cmp esi,edi
	jnc mvsmb1

	add esi,ecx     ;quelle<ziel -> rueckwaerts
	add edi,ecx
mvsmb4: cmp ecx,65535
	jc mvsmb5
	mov ecx,65535
mvsmb5: sub esi,ecx
	sub edi,ecx
	push esi
	push edi
	mov es,cs:sbfseg
	sub di,di
	push cx
	call smplod
	pop cx
	mov ds,cs:sbfseg
	sub si,si
	pop edi
	push edi
	call smpsto
	pop edi
	pop esi
	sub cs:mvslen,65535
	mov ecx,cs:mvslen
	ja mvsmb4
mvsmb3: mov ds,cs:datseg
	ret

mvsmb1: push esi        ;quelle>ziel -> vorwaerts
	push edi
	cmp ecx,65535
	jc mvsmb2
	mov cx,65535
mvsmb2: mov es,cs:sbfseg
	sub di,di
	push cx
	call smplod
	pop cx
	mov ds,cs:sbfseg
	sub si,si
	pop edi
	push edi
	call smpsto
	pop edi
	pop esi
	sub cs:mvslen,65535
	jna mvsmb3
	add edi,65535
	add esi,65535
	mov ecx,cs:mvslen
	jmp mvsmb1
mvsmbl  endp

; SMPFIL => ax=fuellword, edi=ziel, ecx=laenge => fuellt bereich im samplemem
smpfil  proc near
	mov bx,ax
	shl eax,16
	mov ax,bx
	mov es,cs:sbfseg
	push cx
	push di
	sub di,di
	mov cx,65536/4
	rep stosd
	pop di
	pop cx
	mov ds,cs:sbfseg
smpfi1: push ecx
	push edi
	cmp ecx,65535
	jc smpfi2
	mov cx,65535
smpfi2: sub si,si
	call smpsto
	pop edi
	pop ecx
	add edi,65535
	sub ecx,65535
	ja smpfi1
	mov ds,cs:datseg
	ret
smpfil  endp

;============================================================================
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;----------------------------------------------------------------------------
;######/                                                              \######
;#####<  D I G I T A L - T R A K K E R    S O U N D - R O U T I N E N  >#####
;######\                                                              /######
;----------------------------------------------------------------------------
;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
;============================================================================

;==== V A R I A B L E N =====================================================

snddev db 0     ;0=gus
smpbnk db 255 dup(0)
bnklen dd 4 dup(0)
bnkofs dd 0,256*1024,512*1024,768*1024,1024*1024
bnkanz db 0

devjan = 13
sbljmp dw sblsto,sbllod,sblrby,sblwby,sblcsm
       dw sblini,sblvoi,sblon,sbloff,sblpan,sblof0,sblrrf,sblpos

;device-spezifische jumps
jmpsto	dw 0
jmplod	dw 0
jmprby	dw 0
jmpwby	dw 0
jmpcsm  dw 0
jmpini	dw 0
jmpvoi	dw 0
jmpon	dw 0
jmpoff	dw 0
jmppan	dw 0
jmpof0	dw 0
jmprrf  dw 0
jmppos  dw 0

;==== A L L G E M E I N E S =================================================

; MUSINI => sound-device & sample-speicher initialisieren => cf=1 error
musini  proc near
        mov cs:snddev,1
	mov cs:bnkanz,1
	mov si,offset sbljmp
        mov di,offset jmpsto
	mov ax,cs:codseg
	mov ds,ax
	mov es,ax
	mov cx,devjan
	rep movsd
	mov ds,cs:datseg
	clc
	ret
musini  endp

; SNDINI => kompletten sound zuruecksetzen
sndini  proc near
	mov sngspd,6    ;allgemeine parameter resetten
	mov sngbpm,125
sndin0: ret
sndini  endp

;==== S A M P L E - R A M ===================================================

; CSMMEM => bx=lentab, ecx=neue laenge => aendert groesse einer speicherbank
;	 => keine regs veraendert, cf=0 ok
csmmem	proc near
	jmp cs:[jmpcsm]
csmmem	endp

; SMPRES => komplettes sample-ram freigeben
smpres	proc near
	sub bx,bx
	sub ecx,ecx
	mov al,cs:bnkanz
smpre1:	call csmmem
	add bx,4
	dec al
	jnz smpre1
	ret
smpres	endp

; SMPSST => ds:si=quelle, cx=laenge, edi=ziel, bx=8/16 bit maske
;        => block +- speichern
smpsst  proc near
	push cx
	push si
	inc cx
	shr cx,1
smpss1:	lodsw
	xor ax,bx
	mov [si-2],ax
	loop smpss1
	pop si
	pop cx
smpsst  endp

; SMPSTO => ds:si=quelle, cx=len, edi=ziel => block ins sample-ram kopieren
smpsto  proc near
	jmp cs:[jmpsto]
smpsto  endp

; SMPLOD => es:di=ziel, cx=len, esi=quelle => block aus dem sample-ram holen
smplod  proc near
	jmp cs:[jmplod]
smplod  endp

; SMPRBY => esi=speicherplatz => liest byte aus gusram => al=byte
; (!!kein register veraendert, auer AX!!)
smprby  proc near
	jmp cs:[jmprby]
smprby  endp

; SMPWBY => edi=speicherplatz,al=wert => schreibt byte ins sampleram
; (!!kein register veraendert, auer AX!!)
smpwby  proc near
	jmp cs:[jmpwby]
smpwby  endp

; SMPRRF => sample-repeats updaten
smprrf	proc near
	jmp cs:[jmprrf]
smprrf	endp

; SMPPOS => al=kanal => ebp=adresse des samples
smppos	proc near
	jmp cs:[jmppos]
smppos	endp

; SMPDLB => 2.letztes byte in sample ins letzte kopieren
smpdlb  proc near
	pushf
	call getlen
	cmp ecx,3
	jc smpdl0
	movzx bx,smpnum
	shl bx,2
	mov esi,[bx.smpofs]
	sub ecx,2
	add esi,ecx
	call smprby
	mov edi,esi
	inc edi
	call smpwby
smpdl0: popf
	ret
smpdlb  endp

;==== S A M P L E - S P E I C H E R =========================================

; SBLCSM => ecx=neue laenge => memgroesse aendern => no reg changed, cf=0 ok
sblcsm	proc near
	pushad
	call sblcs1
	call cptmem
	call sblcs1
	popad
	jc sblcs0
	mov cs:bnklen,ecx
sblcs0:	ret
sblcs1: mov eax,cs:patmem
	xchg eax,cs:sblmem
	mov cs:patmem,eax
	mov eax,dword ptr cs:pathnd
	xchg eax,dword ptr cs:sblhnd
	mov dword ptr cs:pathnd,eax
	ret
sblcsm	endp

; SBLSTO => ds:si=quelle, cx=laenge, edi=ziel => block speichern
sblsto	proc near
	push es
	mov es,cs:emsseg
	cmp cx,32768
	jna sblst1
	push cx
	push edi
	mov cx,32768
	call sblst0
	pop edi
	pop cx
	sub cx,32768
	add edi,32768
sblst1:	call sblst0
	pop es
	mov bx,cs:emspag
	call setpt0
	ret
sblst0:	mov ebx,edi
	and di,16383
	shr ebx,14
	push cx
	push di
	push si
	mov dx,cs:sblhnd
	call setpt2
	pop si
	pop di
	pop cx
	rep movsb
	ret
sblsto	endp

; SBLLOD => esi=quelle, cx=laenge, es:di=ziel => block laden
sbllod	proc near
	push ds
	mov ds,cs:emsseg
	cmp cx,32768
	jna sbllo1
	push cx
	push esi
	mov cx,32768
	call sbllo0
	pop esi
	pop cx
	sub cx,32768
	add esi,32768
sbllo1:	call sbllo0
	pop ds
	mov bx,cs:emspag
	call setpt0
	ret
sbllo0:	mov ebx,esi
	and si,16383
	shr ebx,14
	push cx
	push di
	push si
	mov dx,cs:sblhnd
	call setpt2
	pop si
	pop di
	pop cx
	rep movsb
	ret
sbllod	endp

; SBLRBY => esi=speicherplatz => liest byte aus sampleram => al=byte
; (!!kein register veraendert, auer AX!!)
sblbyt	db 0

sblrby	proc near
	pushad
	push es
	mov es,cs:emsseg
	mov ebx,esi
	shr ebx,14
	and si,16383
	push si
	mov dx,cs:sblhnd
	mov ax,4400h
	int 67h
	pop si
	mov al,es:[si]
	mov cs:sblbyt,al
	mov bx,cs:emspag
	mov dx,cs:pathnd
	mov ax,4400h
	int 67h
	pop es
	popad
	mov al,cs:sblbyt
	ret
sblrby	endp

; SBLWBY => edi=speicherplatz, al=byte => schreibt byte ins sampleram
; (!!kein register veraendert, auer AX!!)
sblwby	proc near
	mov cs:sblbyt,al
	pushad
	push es
	mov es,cs:emsseg
	mov ebx,edi
	shr ebx,14
	and di,16383
	push di
	mov dx,cs:sblhnd
	mov ax,4400h
	int 67h
	pop si
	mov al,cs:sblbyt
	mov es:[si],al
	mov bx,cs:emspag
	mov dx,cs:pathnd
	mov ax,4400h
	int 67h
	pop es
	popad
	ret
sblwby	endp


sblini	proc near
	ret
sblini	endp

sblvoi	proc near
	ret
sblvoi	endp

sblon	proc near
	ret
sblon	endp

sbloff	proc near
	ret
sbloff	endp

sblpan	proc near
	ret
sblpan	endp

sblof0	proc near
	ret
sblof0	endp

sblrrf	proc near
	ret
sblrrf	endp

sblpos	proc near
	mov ebp,-1
	ret
sblpos	endp

;==== F A R   V E R B I N D U N G S - R O U T I N E N =======================

f_clrsm0:call clrsm0
	retf
f_inclr:call inclr
	retf
f_respat:call respat
	retf
f_settrk:call settrk
	retf
f_getlen:call getlen
	retf
f_csmlen:call csmlen
	retf
f_setpat:call setpat
	retf
f_inspat:call inspat
	retf
f_deapat:call deapat
	retf
f_smprby:call smprby
	retf
f_smpwby:call smpwby
	retf
f_pedip0:retf
f_smpdlb:call smpdlb
	retf
f_sndini:call sndini
	retf
f_sndin0:call sndin0
	retf
f_smpsto:call smpsto
	retf
f_smpsst:call smpsst
	retf
f_ldiff6:call ldiff6
	retf
f_pinstr:retf
f_palsm1:retf
f_smclr2:call smclr2
	retf
f_smpadr:call smpadr
	retf
f_clrem0:call clrem0
	retf
f_smplod:call smplod
	retf
f_suenv:call suenv
	retf
f_suen00:call suen00
	retf

xmldh   proc far
	cmp bl,128
	jnz xmldm
xmldh1:	push cx		;deltas umwandeln
	push si
	mov ah,byte ptr cs:xmlast	;08 bit
xmldi:	lodsb
	add al,ah
	mov [si-1],al
	mov ah,al
	loop xmldi
	mov byte ptr cs:xmlast,ah
	pop si
	pop cx
	call smpsto
	retf
xmldm:	mov ax,cs:xmlast		;16 bit
	push cx
	push si
	shr cx,1
xmldn:	add ax,[si]
	mov [si],ax
	add si,2
	loop xmldn
	mov cs:xmlast,ax
	pop si
	pop cx
	call smpsto
	retf
xmldh	endp

CODE    ends

CODE1   segment para use16 'code'
	assume cs:code1

codseg1 dw code

f_mdlld:call mdlld
	retf
f_modld:call modld
	retf
f_s3mld:call s3mld
	retf
f_mtmld:call mtmld
	retf
f_c69ld:call c69ld
	retf
f_ultld:call ultld
	retf
f_farld:call farld
	retf
f_xmld:	call xmld
	retf
f_ptmld:call ptmld
	retf
f_dsmld:call dsmld
	retf
f_dmfld:call dmfld
	retf
f_mdlsv:call mdlsv
	retf
f_clrnul:mov gs,cs:codseg1
	call clrnul
	retf
f_sfnma7:call sfnma7
	retf

;==== L A D E - R O U T I N E N =============================================

; AUTDET => module-autodetection => bl:0-10=typ,255=error,254=unknown

autanz = 15

auttab:
db 01,056,4,4,"M.K."
db 01,056,4,4,"FLT4"
db 01,057,4,3,"CHN"
db 01,058,4,2,"CH"
db 02,2ch,0,4,"SCRM"
db 08,2ch,0,4,"PTMF"
db 04,00h,0,10,"MAS_UTrack"
db 04,00h,0,10,"MAS_",0f5h,"Track"
db 05,00h,0,2,69h,66h
db 06,00h,0,4,"FAR",254
db 07,00h,0,16,"Extended Module:"
db 09,00h,0,4,"DSm",1ah
db 00,00h,0,4,"DMDL"
db 10,00h,0,4,"DDMF"
db 03,00h,0,3,"MTM"

autdet	proc far
	mov ax,3d00h
	mov dx,offset filnam
	int 21h
	mov bl,255
	jc autde5
	mov bx,ax
	mov gs:fhandl,ax
	mov dx,offset lodbuf
	mov cx,1084
	mov ah,3fh
	int 21h
	mov cl,bl
	mov bl,255
	jc autde4
	mov bl,cl
	mov ax,4200h
	xor cx,cx
	xor dx,dx
	int 21h
	mov si,offset auttab
	mov dl,autanz
autde1:	mov bl,cs:[si]
	inc si
	mov di,cs:[si]
	add si,2
	add di,offset lodbuf
	movzx cx,cs:[si]
	inc si
autde2:	mov al,cs:[si]
	cmp al,[di]
	jnz autde3
	inc si
	inc di
	loop autde2
	retf
autde3:	add si,cx
	dec dl
	jnz autde1
	cmp dword ptr filnam+8,"DOM."
	mov bl,1
	jz autde5
	cmp dword ptr filnam+8,"TSN."
	jz autde5
	mov bl,254
autde4:	push bx
	mov bx,gs:fhandl
	mov ah,3eh
	int 21h
	pop bx
autde5:	retf
autdet	endp

; ???LD => laedt sound-module aus geoeffneter datei
;       => cf=1 error (al=2 while loading,al=3 memory full)

; MDLLD => laedt MDL (digitrakker)
mdlld   proc near
	load 5,lodbuf                   ;*** "DMDL" kennung *****************
	cmp dword ptr lodbuf,"LDMD"
	stc
	jnz mdlsv0
	mov al,lodbuf+4
	shr al,4
	mov gs:mdlver,al
	cmp al,2
	cmc
	jc mdlsv0

	mov bp,offset idtmdl		;bloecke suchen
	mov gs:idanz,idamdl
	call blkpos
	jc mdlsv0

	mov ecx,gs:[idadr+0]            ;*** "IN" infoblock *****************
	mov es,gs:datseg
	or ecx,ecx
	jz mdlldq
	sub ecx,4
	call blseek
	jc mdlsv0
	load 4,lodbuf
	call clrchn
	mov ax,word ptr lodbuf
	push ax
	load ax,sngnam
	mov si,offset snglst
	mov ax,word ptr snglen
	add si,ax
	mov di,offset chnnam
	pop cx
	push si
	sub cx,ax
	sub cx,91+1
	add di,cx
	add si,cx
	inc cx
	std
	rep movsb
	cld
	pop di
	mov cx,255
	sub cx,ax
	xor al,al
	rep stosb

mdlldq:	call clrmes			;*** "ME" message *******************
	mov ecx,gs:[idadr+20]
	or ecx,ecx
	jz mdlldw
	sub ecx,4
	call blseek
	jc mdlsv0
	load 4,lodbuf
	mov ax,word ptr lodbuf
	load ax,lodbuf
	mov si,offset lodbuf
	mov di,offset sngmes
	mov ch,64
mdlldt: mov bp,di
	mov cl,76
mdlldu:	lodsb
	or al,al
	jz mdlldw
	cmp al,13
	jz mdlldv
	or cl,cl
	jz mdlldu
	stosb
	dec cl
	jmp mdlldu
mdlldv:	mov di,bp
	add di,76
	dec ch
	jnz mdlldt

mdlldw: call clrpnm			;*** "PN" pattern-namen (v0.0) ******
	mov ecx,gs:[idadr+24]
	or ecx,ecx
	jz mdllds
	sub ecx,4
	call blseek
	jc mdlsv0
	load 4,lodbuf
	mov ax,word ptr lodbuf
	load ax,patnam

mdllds: call far ptr f_deapat
	mov ecx,gs:[idadr+4]            ;*** "PA" pattern *******************
	or ecx,ecx
	jz mdlldo
	sub ecx,4
	call blseek
	jc mdlsv0
	load 5,lodbuf
	mov al,lodbuf+4
	mov gs:xmins,al
	mov ax,word ptr lodbuf
	mov ds,gs:sbfseg
	load ax,0
	cmp gs:mdlver,0
	jnz mdllp5
	mov al,gs:xmins		;v0.0 loader
	mov ds,gs:datseg
	call far ptr f_respat
	jc mdlldb
	jmp mdlldx
mdllp5:	mov di,offset patnam    ;v1.0 loader
	xor si,si
	mov bp,32768
mdllp1: mov al,[si+1]
	push si
	push di
	push bp
	mov ds,gs:datseg
	call far ptr f_inspat
	pop bp
	pop di
	pop si
	jc mdlldb
	mov ds,gs:sbfseg
	mov dh,[si]
	add si,2
	mov cx,16/2
	mov es,gs:datseg
	rep movsw
	mov cl,32
	sub cl,dh
	or dh,dh
	jz mdllp3
mdllp2:	lodsw
	mov ds:[bp],ax
	add bp,2
	dec dh
	jnz mdllp2
	or cl,cl
	jz mdllp4
mdllp3:	mov ds:[bp],word ptr 0
	add bp,2
	dec cl
	jnz mdllp3
mdllp4:	dec gs:xmins
	jnz mdllp1
	mov es,gs:sbfseg
	mov si,32768
	xor di,di
	mov cx,16384/2
	rep movsw

mdlldx: mov ds,gs:datseg
	mov ecx,gs:[idadr+8]            ;*** "TR" tracks ********************
	or ecx,ecx
	stc
	jz mdlsv0
	call blseek
	jc mdlsv0
	load 2,lodbuf
	mov cx,word ptr lodbuf
	or cx,cx
	jz mdlldo
	mov gs:mstrnm,1
mdlldc: push cx
	load 2,lodbuf           ;gecrunchten track laden
	mov si,word ptr lodbuf
	mov ax,gs:sbfseg
	mov ds,ax
	mov es,ax
	load si,32768
	mov dx,si	;dx=bytes
	mov si,32768    ;ds:si=quelle
	mov di,49152    ;es:di=ziel
	mov cx,6*256/2
	xor ax,ax
	rep stosw	;ziel loeschen
	mov di,49152
mdlldd: lodsb                   ;track entpacken
	dec dx
	mov cl,al
	shr cl,2
	and al,3
	jnz mdllde
	inc cl                  ;fall 0 => leerstellen
	mov ch,cl
	add cl,cl
	add cl,ch
	xor ch,ch
	xor ax,ax
	rep stosw
	jmp mdlldk
mdllde: dec al
	jnz mdlldg
	inc cl                  ;fall 1 => letzten wiederholen
	xor ch,ch
	mov eax,es:[di-6]
	mov bx,es:[di-2]
mdlldf: stosd
	mov es:[di],bx
	add di,2
	loop mdlldf
	jmp mdlldk
mdlldg: dec al
	jnz mdlldh
	mov al,6                ;fall 2 => wie pos cl
	mul cl
	mov bx,ax
	mov eax,es:[bx.49152]
	stosd
	mov ax,es:[bx.49156]
	stosw
	jmp mdlldk
mdlldh: mov ch,6                ;fall 3 => note setzen
mdlldi: xor al,al
	shr cl,1
	jnc mdlldj
	lodsb
	dec dx
mdlldj: stosb
	dec ch
	jnz mdlldi
mdlldk: or dx,dx
	jnz mdlldd
	xor si,si               ;track in pattern kopieren
	mov ds,gs:datseg
	movzx cx,patanz
	shl cx,5
	mov ax,gs:mstrnm
mdlldl: cmp ax,es:[si]
	jnz mdlldm
	push si
	push cx
	push ax
	mov ax,si
	shr ax,1
	call far ptr f_settrk
	mov es,gs:patse1
	mov ds,gs:sbfseg
	mov di,si
	mov si,49152
	mov dx,32*6-6
	mov cx,gs:edipl1
mdlldn: lodsd
	stosd
	lodsw
	stosw
	add di,dx
	loop mdlldn
	pop ax
	pop cx
	pop si
	mov ds,gs:datseg
	mov es,gs:sbfseg
mdlldm: add si,2
	loop mdlldl
	inc gs:mstrnm
	pop cx
	dec cx
	jnz mdlldc

mdlldo: mov ecx,gs:[idadr+28]		;*** "II" instruments ***************
	or ecx,ecx
	jz mdlli4
	sub ecx,4
	call blseek
	load 5,lodbuf
	mov bp,word ptr lodbuf+4
	mov ax,word ptr lodbuf
	mov ds,gs:sbfseg
	load ax,0
	xor si,si
	mov es,gs:insseg
	mov dx,bp
	or dl,dl
	jz mdlli3
mdlli1:	lodsw
	dec al
	mov dh,ah
	mov ah,al
	xor al,al
	mov di,ax
	mov cx,32/2
	rep movsw
	mov al,14/2
	mul dh
	or al,al
	jz mdlli2
	mov cx,ax
	rep movsw
mdlli2:	dec dl
	jnz mdlli1
mdlli3:	mov ds,gs:datseg

mdlli4:	mov ecx,gs:[idadr+32]		;*** "VE" vol-envelope **************
	or ecx,ecx
	jz mdlldz
	sub ecx,4
	call blseek
	load 5,lodbuf
	mov ax,word ptr lodbuf
	mov bp,word ptr lodbuf+4
	mov ds,gs:sbfseg
	load ax,0
	mov bx,offset envdat
	call mdlle

mdlldz:	mov ecx,gs:[idadr+36]		;*** "PE" pan-envelope **************
	or ecx,ecx
	jz mdllz1
	sub ecx,4
	call blseek
	load 5,lodbuf
	mov ax,word ptr lodbuf
	mov bp,word ptr lodbuf+4
	mov ds,gs:sbfseg
	load ax,0
	mov bx,offset enpdat
	call mdlle

mdllz1:	mov ecx,gs:[idadr+40]		;*** "FE" frq-envelope **************
	or ecx,ecx
	jz mdlldy
	sub ecx,4
	call blseek
	load 5,lodbuf
	mov ax,word ptr lodbuf
	mov bp,word ptr lodbuf+4
	mov ds,gs:sbfseg
	load ax,0
	mov bx,offset enfdat
	call mdlle

mdlldy:	cmp gs:[idadr+12],dword ptr 0	;*** "IS" sampleinfos ***************
	jnz mdlldr
	xor al,al
	ret
mdlldr: call far ptr f_clrsm0
	mov ecx,gs:[idadr+12]
	sub ecx,4
	call blseek
	jc mdlsv0
	load 5,lodbuf
	mov ax,word ptr lodbuf
	dec ax
	jz mdlld7
	mov ds,gs:sbfseg
	load ax,0
	mov es,gs:datseg
	mov dl,es:[lodbuf+4]    ;dl=anz instr.
	xor si,si               ;es:si=instdata
mdlld6: lodsb
	mov ah,smpiln
	mul ah
	add ax,offset (smpdat-smpiln)
	mov di,ax
	cmp gs:mdlver,0
	jz mdlls2
	mov cx,smpiln
	rep movsb
	jmp mdlls3
mdlls2:	mov cx,(32+8+2)/2
	rep movsw
	xor ax,ax
	stosw
	mov cx,14/2
	rep movsw
mdlls3:	dec dl
	jnz mdlld6
	mov ds,gs:datseg

mdlld7: mov ecx,gs:[idadr+16]           ;*** "SA" samples *******************
	or ecx,ecx
	jz mdlsv0
	call blseek
	jc mdlsv0
	call mdlld8
	mov gs:mdlver,0
	jc mdlsvz
mdll71:	call far ptr f_sndin0
	xor al,al
	jmp mdlsvz

mdlld8:	push word ptr insmod
	mov insmod,1
        call far ptr f_setimd
	mov gs:sgnmsk,0
	mov cx,255
	call mdll81
	pop ax
	pushf
	mov insmod,al
        call far ptr f_setimd
	popf
	ret

mdll81: push cx
	mov al,255
	sub al,cl
	mov smpnum,al
	call far ptr f_getlen     ;bx=dat,ecx=len,zf=[len]
	jz mdlld9
	mov [bx.smplen],0
	call far ptr f_csmlen
	jnc mdllda
	pop cx
mdlldb: mov al,3
	ret
mdllda: call far ptr f_palsm1
	cmp gs:mdlver,0
	jnz mdlls1
	call s2icnv
mdlls1:	call lodsmp
mdlld9: pop cx
        jc mdlldp
	loop mdll81
	xor al,al
	ret
mdlldp: mov al,2
	ret

; MDLLE => bx=envdat,bplow=envanz,ds:0=data => envelopes kopieren
mdlle:  mov es,gs:datseg
	mov dx,bp
	or dl,dl
	jz mdlle2
	xor si,si
mdlle1:	lodsb
	xor ah,ah
	shl ax,5
	add ax,bx
	mov di,ax
	mov cx,32/2
	rep movsw
	dec dl
	jnz mdlle1
mdlle2:	mov ds,gs:datseg
	ret

; BLKPOS => idanz=anz bloecke, bp=idtab adr => bloecke suchen und adr merken
blkpos:	mov di,offset idadr
	movzx cx,gs:idanz
	mov gs:idcnt,cl
	mov es,gs:codseg
	xor eax,eax
	rep stosd
	xor cx,cx
	xor dx,dx
mdlld1: mov ax,4201h
	mov bx,gs:fhandl
	int 21h
	jc mdlld5
	mov word ptr gs:idnow,ax
	mov word ptr gs:idnow+2,dx
	mov cx,6
	mov dx,offset lodbuf
	mov ah,3fh
	mov bx,gs:fhandl
	int 21h
	jc mdlld5
	cmp ax,cx
	jc mdlld5
	mov ax,word ptr lodbuf
	mov bx,bp
	movzx cx,gs:idanz
mdlld2: cmp ax,gs:[bx]
	jz mdlld3
	add bx,2
	loop mdlld2
	jmp mdlld4
mdlld3: sub bx,bp
	add bx,bx
	mov eax,gs:idnow
	add eax,6
	mov gs:[bx.idadr],eax
	dec gs:idcnt
	jz mdlld5
mdlld4: mov dx,word ptr lodbuf+2
	mov cx,word ptr lodbuf+4
	jmp mdlld1
mdlld5: clc
	ret

mdlld   endp

; MODLD => laedt MOD (noisetracker,protracker,fasttracker & octacomposer)
modld   proc near
	mov cx,1084             ;kopf laden
	mov dx,offset lodbuf
	call fload
	jnc modld1
modld4: mov al,2
	ret

modld1: mov si,offset kennbt    ;test, ob 31 instrument-mod
	mov di,offset lodbuf+1080
	cmp word ptr [di+2],"HC"
	jz modl1b
	cmp word ptr [di+1],"HC"
	jnz modl1a
	cmp byte ptr [di+3],"N"
	jnz modl1a
	mov al,[di]		;xCHN module
	sub al,"0"
modl1c:	mov gs:numchn,al
	jmp modl2a
modl1b: mov cx,[di]		;xxCH module
	sub cl,"0"
	sub ch,"0"
	mov al,10
	mul cl
	add al,ch
	jmp modl1c
modl1a:	mov cx,6
modld2: call typcp
	jnz modld3
	inc cl
	and cl,0feh
	neg cl
	add cl,10
	mov gs:numchn,cl
modl2a:	mov si,offset lodbuf+950
	mov cx,31
	jmp modld5
modld3: loop modld2

	mov ax,4200h            ;15 instrument-mod, zeigerpos korrigieren
	mov bx,gs:fhandl
	xor cx,cx
	mov dx,600
	int 21h
	jc modld4
	mov gs:numchn,4
	mov si,offset lodbuf+470
	mov cx,15

;si=beginn songdaten, cx=anzahl instrumente, numchn=kanalanzahl

modld5: push cx                 ;sngrep,snglen,snglst,patanz holen
	lodsw
	mov snglen,al
	mov sngrep,0
	cmp ah,al
	jnc modld6
	mov sngrep,ah
modld6: mov cx,64
	mov di,offset snglst
	mov es,gs:datseg
	rep movsw
	xor al,al
	mov cl,128
	sub di,128
modld7: cmp al,[di]
	jnc modld8
	mov al,[di]
modld8: inc di
	loop modld7
	inc al
	call far ptr f_respat
	jnc modld9
	pop cx
	mov al,3
	ret

modld9: mov si,offset lodbuf    ;sngnam holen, sngcom loeschen
	mov di,offset sngnam
	mov es,gs:datseg
	mov cx,20
modldc: lodsb
	or al,al
	jz modldd
	stosb
	loop modldc
modldd: add cl,12
	mov al,32
	rep stosb
	mov eax,"-DOM"
	call setcom
	mov di,offset sngchn
	mov es,gs:datseg
	mov cx,32/4
	mov eax,0c0c0c0c0h
	rep stosd
	sub di,32
	mov si,offset panmod
	movzx cx,gs:numchn
	mov ds,gs:codseg
	rep movsb
	mov ds,gs:datseg
	mov trkpos,0
	call clrmes
	call clrchn
	call clrpnm

	call far ptr f_clrsm0
	pop bp                  ;sample-infos holen
	mov si,offset lodbuf+20
	mov bx,offset smpdat
	mov es,gs:datseg
modlde: mov di,bx       ;name
	add di,smpnam
	mov cx,22
	call messmp
modldj: lodsb
	or al,al
	jnz modldk
	mov al,32
modldk: stosb
	loop modldj
	mov cl,10
	mov al,32
	rep stosb
	lodsw		;lenght
	xchg al,ah
	cmp ax,2
	jc modlda
	movzx eax,ax
	add eax,eax
	mov [bx.smplen],eax
modlda:	lodsw           ;volume
	mov dl,al
	mov al,ah
	call cnvvol
	mov [bx.smpvol],al
	mov al,dl
	and al,15       ;finetune
	add al,al
	xor ah,ah
	mov di,ax
	movzx eax,gs:[di.ftfreq]
	mov [bx.smpfre],eax
	lodsw           ;repeat
	xchg al,ah
	add ax,ax
	movzx eax,ax
	mov [bx.smprep],eax
	lodsw           ;repeat-lenght
	xchg al,ah
	cmp ax,2
	jc modldm
	add ax,ax
	movzx eax,ax
	mov [bx.smprln],eax
modldm: add bx,smpiln
	dec bp
	jnz modlde
	call sfnmak	;samplenamen in filenamen konvertiern

	mov edipat,0            ;pattern laden
modldg: call far ptr f_setpat
	mov dx,offset lodbuf
	mov ch,gs:numchn
	xor cl,cl
	call fload
	jc modld4
	mov si,offset lodbuf
	xor di,di
	mov es,gs:patseg
	call cvmod
	mov al,patanz
	inc edipat
	cmp edipat,al
	jnz modldg

modldh: mov gs:sgnmsk,0            ;samples laden
	call ldasmp
	jc modld4

	call far ptr f_sndini     ;laden erfolgreich beendet
	xor al,al
	ret
modld   endp

; SETCOM => eax="typ" => composer-name setzen
setcom	proc near
	mov si,offset cnvcom
	mov di,offset sngcom
	mov es,gs:datseg
	mov cx,20/2
	rep movsw
	mov dword ptr sngcom+11,eax
	ret
setcom	endp

; TYPCP => vergleicht 4 zeichen in gs:si mit lodbuf => zf=1 gleich, si=si+4
typcp   proc near
	mov di,offset lodbuf+1080
	mov eax,gs:[si]
	add si,4
	cmp eax,[di]
	ret
typcp   endp

; FLOAD => ds:dx=ziel,cx=len => block von file lesen
fload   proc near
	mov ax,3F00h
	mov bx,gs:fhandl
	int 21h
	ret
fload   endp

; LODSMP => gs:sgnmsk=signchange-flag => laedt smpnum-sample aus fhandl-datei
lodsmp  proc near
	call far ptr f_getlen             ;smplen und ofs holen
	mov al,[bx.smptyp]
	shr al,2
	and al,3
	jnz sdecr

lodsm0: mov gs:sgnjmp,offset far ptr f_smpsto   ;*** ungecrunchten sample laden *****
	cmp gs:sgnmsk,0
	jz lodsm4
	mov gs:sgnjmp,offset far ptr f_smpsst
lodsm4: call far ptr f_smpadr
	mov ah,80h
	mov al,[bx.smptyp]
	and al,1
	xor al,1
	ror al,1
	mov gs:sgntyp,ax
	movzx bx,smpnum
	shl bx,2
	mov edi,[bx.smpofs]
	mov ds,gs:sbfseg
lodsm1: push ecx                ;teil laden
	push edi
	cmp ecx,65529
	jc lodsm2
	mov cx,65528
lodsm2: xor dx,dx
	call fload
	jc lodsm6
	xor si,si               ;ins sample-ram speichern
	pop edi
	push edi
	mov bx,gs:sgntyp
	call dword ptr gs:sgnjmp
	pop edi
	pop ecx
	add edi,65528
	sub ecx,65528
	ja lodsm1
lodsm5:	mov ds,gs:datseg
	clc
	ret
lodsm6: mov ds,gs:datseg        ;fehler, stack raeumen
	pop eax
	pop eax
	ret

;di =sample-datas
;si =crunch-datas
;bp =ziel-laenge
;ebx=bits
;ch =bitcounter
;ah =letztes byte
;al =delta
;dx =bits

sdecr:  and al,2
	xor al,3
	mov gs:crn16b,al
	mov gs:clslen,ecx	;len sample
	movzx bx,smpnum
	shl bx,2
	mov eax,[bx.smpofs]	;adr sample
	mov gs:dcziel,eax
	mov dx,offset crnlen    ;len crunch
	mov ds,gs:codseg
	mov cx,4
	mov bx,gs:fhandl
	mov ah,3fh
	int 21h
	mov si,65536-4		;si=crunch
	mov ch,1		;ch=bitcount
	xor ah,ah		;ah=altes byte
	mov ds,gs:sbfseg
	mov es,gs:sbfseg
sdecr0: mov ebp,gs:clslen
	cmp ebp,32768+1
	jc sdecr9
	mov ebp,32768
sdecr9: sub gs:clslen,ebp
	xor di,di
	mov gs:dcblen,bp

sdecr1:	xor gs:crn16b,1
	jnz sdec11
	rept 8		;low-byte von 16 bit sample holen
	call getbit
	rcr al,1
	endm
	jmp sdec71
sdec11:	xor dl,dl       ;dl=maske
	call getbit
	sbb dl,0
	call getbit
	jnc sdecr4
	cmp ch,4        ;** 3 bits holen
	jc sdecr3
	mov al,bl
	and al,7
	shr ebx,3
	sub ch,3
	jmp sdecr7
sdecr3: xor al,al
	call getbit
	rcr al,1
	call getbit
	rcr al,1
	call getbit
	rcr al,6
	jmp sdecr7
sdecr4: mov dh,-8       ;** 4 bits holen
sdecr5: add dh,16
	call getbit
	jnc sdecr5
	cmp ch,5
	jc sdecr6
	mov al,bl
	and al,15
	shr ebx,4
	sub ch,4
	jmp sdecr8
sdecr6: xor al,al
	call getbit
	rcr al,1
	call getbit
	rcr al,1
	call getbit
	rcr al,1
	call getbit
	rcr al,5
sdecr8: add al,dh
sdecr7: xor al,dl
	add al,ah
	mov ah,al
sdec71:	stosb
	dec bp
	jnz sdecr1

	pusha		;sample-teil speichern
	push ebx
	xor si,si
	movzx ecx,gs:dcblen
	mov edi,gs:dcziel
	add gs:dcziel,ecx
	call far ptr f_smpsto
	pop ebx
	popa
	cmp gs:clslen,0
	jnz sdecr0
	jmp lodsm5

; ch=bitcounter, ebx=bits => holt ein bit => cf=bit
getbit: dec ch
	jz getbi1
	shr ebx,1
	ret
getbi1: add si,4
	jz getbi2
getbi4: mov ebx,[si]
	shr ebx,1
	mov ch,32
	ret
getbi2: push ax
	push cx
	push dx
	mov edx,32768
	mov si,dx
	mov ecx,gs:crnlen
	cmp ecx,edx
	jbe getbi3
	mov ecx,edx
getbi3: sub gs:crnlen,ecx
	mov ah,3fh
	mov bx,gs:fhandl
	int 21h
	jc lodsm6
	pop dx
	pop cx
	pop ax
	jmp getbi4

lodsmp  endp

; CVMOD => ds:si=modpat, es:di=mdlpat, gs:numchn => convertiert mod-pattern
cvmod   proc near
	mov cl,64
cvmod1: push di                 ;notpos-loop
	mov ch,gs:numchn
	mov gs:cvmchn,0
cvmod2: push cx                 ;kanal-loop
	mov ax,[si]
	mov bl,al       ;sample
	and bl,0f0h
	mov bh,[si+2]
	shr bh,4
	or bl,bh
	mov es:[di+1],bl
	xor dl,dl       ;note
	and al,0fh
	xchg al,ah
	or ax,ax
	jz cvmod4
	mov bx,offset notfrq
	mov cx,12*10
	xor dl,dl
cvmod3: inc dl
	mov bp,[bx]
	shr bp,3
	cmp ax,bp
	jnc cvmod4
	add bx,2
	loop cvmod3
cvmod4: mov es:[di],dl

	mov bx,[si+2]   ;commando konvertierung
	call cvmodx
	add si,4
	add di,6
	inc gs:cvmchn
	pop cx
	dec ch
	jnz cvmod2
	pop di
	add di,6*32
	dec cx
	jnz cvmod1
	ret
cvmod   endp

cvmodx: and bl,15
cvmox1:	mov al,bh
	mov dl,bl
	add bl,bl
	xor bh,bh
	mov ah,bh
	jmp gs:[bx.cvmjmp]

cvmd0:  mov dl,005h     ;arpeggio oder nichts
	xor ah,ah
	or al,al
	jnz cvmod5
	xor dl,dl
	jmp cvmod5
cvmd1:  cmp al,0e0h     ;note slide up/down
	jc cvmod5
	mov al,0dfh
	jmp cvmod5
cvmd2:  jmp cvmd1
cvmd3:  jmp cvmod5      ;portamento
cvmd4:  jmp cvmod5      ;vibrato
cvmd5:  sub dl,2        ;port+volslide
	jmp cvmda0
cvmd6:  jmp cvmd5       ;vibr+volslide
cvmd7:  mov dl,040h     ;tremolo
	xchg al,ah
	jmp cvmod5
cvmd8:  jmp cvmod5      ;fine-panning
cvmd9:  mov dl,0eh      ;smp-offset
	mov ah,al
	mov al,0f0h
	jmp cvmod5
cvmda:  xor dl,dl	;volume slide
cvmda0: movzx bx,gs:cvmchn
	add bx,offset cvmovl
	or al,al
	jnz cvmda2
	mov al,gs:[bx]
cvmda2: mov gs:[bx],al
	mov ah,al
	shr ah,4
	and al,15
	add dl,10h
	sub ah,al
	ja cvmda1
	add dl,10h
	neg ah
cvmda1: shl ah,2
	xor al,al
	jmp cvmod5
cvmdb:  jmp cvmod5      ;position-jump
cvmdc:  call cnvvol     ;volume
	mov es:[di+2],al
	xor ax,ax
	xor dl,dl
	jmp cvmod5
cvmdd:  jmp cvmod5      ;pattern-break
cvmde:  mov bl,al       ;e-commando
	shr bl,4
	xor bh,bh
	add bl,bl
	jmp gs:[bx.cvmejp]

cvme0:  xor dl,dl       ;filter -> not implemented
	xor al,al
	jmp cvmod5
cvme1:  mov dl,1        ;fine slide up/down
	or al,0f0h
	jmp cvmod5
cvme2:  mov dl,2
	or al,0f0h
	jmp cvmod5
cvme3:  jmp cvmod5      ;glissando & vibrato-control
cvme4:  jmp cvmod5
cvme5:  jmp cvmod5      ;fintune
cvme6:  jmp cvmod5      ;loop
cvme7:  jmp cvmod5      ;tremolo-control
cvme8:  mov dl,8
	and al,15
	shl al,3
	jmp cvmod5
cvme9:  jmp cvmod5      ;retrig note
cvmea:  mov dl,10h      ;fine vol slide up/down
	or al,0f0h
	xchg al,ah
	jmp cvmod5
cvmeb:  mov dl,20h
	or al,0f0h
	xchg al,ah
	jmp cvmod5
cvmec:  jmp cvmod5      ;note-cut
cvmed:  jmp cvmod5      ;note-delay
cvmee:  jmp cvmod5      ;pattern-delay
cvmef:  jmp cvme0       ;funk-repeat -> not implemented

cvmdf:	or al,al	;speed
	jz cvmdf1
	cmp al,33
	jc cvmod5
cvmdf1:	mov dl,7

cvmod5: mov es:[di+3],dl
	mov es:[di+4],ax
	ret

; LDASMP => laedt alle belegten samps aus geoeffneter datei
ldasmp	proc near
	mov smpnum,0
ldasm1:	call ldasm0
	jc ldasm6
	inc smpnum
	cmp smpnum,255
	jnz ldasm1
	mov smpnum,0
	clc
ldasm6:	ret

ldasm0: call far ptr f_getlen
	jz ldasm5
	push ecx
	inc ecx
	mov ebp,gs:ldslen
	mov gs:ldslen,0
	mov [bx.smplen],ebp
	call far ptr f_csmlen
	jnc ldasm2
	pop ecx
	mov al,3
	ret
ldasm2: call s2icnv
	pop ecx
	push ecx
	call gs:ldajmp
	pop edx
	jnc ldasm3
	mov al,2
	ret
ldasm3: call far ptr f_getlen   ;ecx=reservierte laenge,edx=echte laenge
	cmp ecx,3
	jc ldasm5
	movzx bx,smpnum
	shl bx,2
	mov esi,[bx.smpofs]
	add esi,edx
	dec esi
	sub ecx,edx
	call far ptr f_smprby
	mov edi,esi
ldasm4:	inc edi
	call far ptr f_smpwby
	loop ldasm4
ldasm5: clc
	ret
ldasmp	endp

clrmes:	mov di,offset sngmes	;song-message loeschen
	mov es,gs:datseg
	mov cx,76*64/4
	mov eax,"    "
	rep stosd
	mov mescrx,0
	mov mescry,0
	mov mespos,0
	ret

clrchn:	mov di,offset chnnam	;track-namen loeschen
	mov es,gs:datseg
	mov cx,32*8/4
	mov eax,"    "
	rep stosd
	ret

clrpnm:	mov di,offset patnam	;pattern-namen loeschen
	mov es,gs:datseg
	mov cx,255*16/4
	mov eax,"    "
	rep stosd
	ret

; BLSEEK => ecx=block-adr => dateizeiger auf block positionieren
blseek  proc near
	mov dx,cx
	shr ecx,16
	mov bx,gs:fhandl
	mov ax,4200h
	int 21h
	ret
blseek  endp

; MTMLD => laedt MTM (multitracker)
mtmld   proc near
	load 66,lodbuf                  ;*** song-infos *********************
	mov lodbuf+3," "
	cmp dword ptr lodbuf," MTM"
	stc
	jnz mdlsv0

	mov di,offset sngnam    ;name
	mov es,gs:datseg
	mov si,offset lodbuf+4
	mov cx,20/4
	rep movsd
	mov eax,"    "
	stosd
	stosd
	stosd
	mov cx,32
	mov di,offset sngnam
	call clrnul
	lodsw                   ;tracks
	mov gs:mstrmx,ax
	lodsb                   ;patanz
	inc al
	push si
	push es
	call far ptr f_respat
	pop es
	pop si
	jc mdlldb
	lodsb                   ;snglen
	inc al
	mov snglen,al
	lodsw                   ;extra-comment-field-lenght
	mov gs:mtmexl,ax
	lodsb                   ;sample-anzahl
	mov gs:mtmsnm,al
	lodsb                   ;attribute
	lodsb                   ;tracklen
	lodsb                   ;pannel+aktive kanaele
	mov dl,32
	sub dl,al
	mov di,offset sngchn
	mov cx,32
mtmld1: lodsb
	and al,15
	shl al,3
	cmp dl,cl
	jc mtmld2
	or al,128
mtmld2: stosb
	loop mtmld1
	mov eax,"-MTM"
	call setcom
	call clrmes
	call clrpnm
	call clrchn

	call far ptr f_clrsm0                     ;*** instruments ********************
	mov al,gs:mtmsnm
	or al,al
	jz mtmld5
	mov ah,37
	mul ah
	mov ds,gs:sbfseg
	load ax,0
	mov es,gs:datseg
	mov bp,offset smpdat
	xor si,si
	mov dl,gs:mtmsnm
mtmld3: mov di,bp
	add di,smpnam   ;smpnam
	mov cx,11
	rep movsw
	mov ax,"  "
	mov cx,5
	rep stosw
	sub di,32
	mov cx,32
	call clrnul
	lodsd           ;len,rep,replen
	cmp eax,2
	jc mtmldo
	mov es:[bp.smplen],eax
mtmldo: lodsd
	mov es:[bp.smprep],eax
	mov ebx,eax
	lodsd
	sub eax,ebx
	cmp eax,2
	ja mtmlo1
	sub eax,eax
mtmlo1:	mov es:[bp.smprln],eax
	lodsb
	and al,15       ;finetune
	add al,al
	xor ah,ah
	mov di,ax
	movzx eax,gs:[di.ftfreq]
	mov es:[bp.smpfre],eax
	lodsb
	call cnvvol
	mov es:[bp.smpvol],al
	lodsb
	and al,1
	mov es:[bp.smptyp],al
	add bp,smpiln
	dec dl
	jnz mtmld3
	mov ds,gs:datseg
	call sfnmak     ;samplenamen in filenamen konvertiern

mtmld5: load 128,snglst                 ;*** sequencer **********************

	mov ax,4201h                    ;*** pattern ************************
	xor cx,cx
	xor dx,dx
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov word ptr gs:mstrfp,ax
	mov word ptr gs:mstrfp+2,dx
	mov ax,gs:mstrmx
	mov dx,192
	mul dx
	mov cx,dx
	mov dx,ax
	mov ax,4201h    ;tracks ueberspringen
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov al,patanz
	xor ah,ah
	shl ax,6
	mov ds,gs:patse3
	load ax,0
	mov ds,gs:datseg

	mov dx,gs:mtmexl                ;*** extra-feld *********************
	or dx,dx
	jz mtmldq
	load dx,lodbuf
	call clrmes
	call clrchn
	mov si,offset lodbuf
	mov di,offset sngmes
	mov cx,gs:mtmexl
	mov dx,40
mtmldr:	lodsb
	or al,al
	jnz mtmlds
	mov al,32
mtmlds:	stosb
	dec dl
	jnz mtmldt
	mov dl,40
	add di,76-40
	inc dh
	cmp dh,64
	jz mtmldq
mtmldt:	loop mtmldr

mtmldq:	mov gs:sgnmsk,1                 ;*** samples ************************
	call ldasmp
	jc mdlsv0

	cmp gs:mstrmx,0                 ;*** tracks *************************
	jz mtmld6
	mov dx,word ptr gs:mstrfp
	mov cx,word ptr gs:mstrfp+2
	mov bx,gs:fhandl
	mov ax,4200h
	int 21h
	jc mdlsv0
	mov gs:mstrnm,1
mtmld7: load 192,lodbuf         ;mtm-track laden
	mov es,gs:datseg
	mov cx,64
	mov si,offset lodbuf    ;track convertieren
	mov di,offset lodbuf+192
mtmld8: push cx
	lodsw
	mov bl,ah
	mov bh,[si]
	inc si
	mov cl,al
	shr cl,2
	jz mtmld9
	add cl,12*2+1
mtmld9: mov [di],cl
	xchg al,ah
	shr ax,4
	and al,63
	mov [di+1],al
	mov [di+2],byte ptr 0   ;?????
	call cvmodx
	add di,6
	pop cx
	loop mtmld8
	mov fs,gs:patse3        ;track in pattern kopieren
	xor si,si
	movzx cx,patanz
	shl cx,5
	mov ax,gs:mstrnm
mtmldl: cmp ax,fs:[si]
	jnz mtmldm
	push si
	push cx
	push ax
	mov ax,si
	shr ax,1
        call far ptr f_settrk
	mov es,gs:patse1
	mov di,si
	mov si,offset lodbuf+192
	mov dx,32*6-6
	mov cx,64
mtmldn: lodsd
	stosd
	lodsw
	stosw
	add di,dx
	loop mtmldn
	pop ax
	pop cx
	pop si
mtmldm: add si,2
	loop mtmldl
	inc gs:mstrnm
	dec gs:mstrmx
	jnz mtmld7

mtmld6: call far ptr f_sndini
	xor al,al
	jmp mdlsvz

mtmld   endp

; SFNMAK => alle smpnam nach smpfle konvertieren
sfnmak  proc near
	xor al,al
sfnma5: push ax
	call sfnma6
	pop ax
	inc al
	cmp al,255
	jc sfnma5
	ret
sfnma6: mov ah,smpiln
	mul ah
	mov bx,ax
	add bx,offset smpdat
	mov es,gs:datseg
	mov di,bx
	add di,smpfle
	mov si,bx
	add si,smpnam

;ds:si=name, es:di=file
sfnma7:	mov eax,"    "
	stosd
	stosd
	sub di,8
	mov cx,32+8*256
	mov al,[si]
	call fsetbg
	cmp al,"S"
	jnz sfnma1
	mov al,[si+1]
	call fsetbg
	cmp al,"T"
	jnz sfnma1
	cmp [si+2],byte ptr "-"
	jnz sfnma1
	cmp [si+5],byte ptr ":"
	jnz sfnma1
	add si,6
	sub cl,6
sfnma1: lodsb
	cmp al,"0"
	jc sfnma3
	cmp al,"9"+1
	jc sfnma2
	cmp al,"A"
	jc sfnma3
	cmp al,"Z"+1
	jc sfnma2
	cmp al,"a"
	jc sfnma3
	cmp al,"z"+1
	jnc sfnma3
sfnma2: stosb
	dec ch
	jz sfnma4
sfnma3: dec cl
	jnz sfnma1
sfnma4: ret
sfnmak  endp

fsetbg:	cmp al,"a"
	jc fsetb1
	cmp al,"z"+1
	jnc fsetb1
	sub al,32
fsetb1: ret

; CLRNUL => es:di=text, cx=len => alle 0 in 32 umwandlen
clrnul  proc near
	cmp es:[di],byte ptr 0
	jnz clrnu1
	mov es:[di],byte ptr 32
clrnu1: inc di
	loop clrnul
	ret
clrnul  endp

; S3MLD => laedt S3M (scream-tracker 3)
s3mld   proc near
	load 60h,lodbuf                 ;*** songinfos **********************
	cmp dword ptr lodbuf+2ch,"MRCS"
	stc
	jnz mdlsv0
	mov eax,"-M3S"
	call setcom
	call clrmes
	call clrpnm
	call clrchn
	mov si,offset lodbuf    ;songname
	mov di,offset sngnam
	mov cx,28/4
	rep movsd
	mov [di],dword ptr "    "
	sub di,28
	mov cx,32
	call clrnul
	lodsd                   ;version+muell  (schwachsinn)
	lodsw
	mov gs:s3msln,al        ;s3m-songlenght
	lodsw
	mov gs:mtmsnm,al        ;sample-anzahl
	lodsw                   ;pattern-anzahl
	mov gs:s3mpan,al
	lodsw                   ;flags          (schwachsinn)
	lodsd                   ;versionen      (schwachsinn)
	lodsd                   ;"scrm"
	lodsb
	call cnvvol             ;main-volume
	mov sngvol,al
	lodsw
	mov sngspd,al           ;speed & bpm
	mov sngbpm,ah
	mov es,gs:datseg
	mov si,offset lodbuf+40h
	mov di,offset sngchn	;channels
	mov cx,32
s3mld1: lodsb
	mov ah,128+64
	cmp al,255
	jz s3mld2
	mov ah,al
	and ah,128
	add ah,16
	and al,127
	cmp al,8
	jc s3mld2
	add ah,127-32
	cmp al,16
	jc s3mld2
	mov ah,128+64
s3mld2: mov al,ah
	stosb
	loop s3mld1
	movzx cx,gs:s3msln         ;songlist & snglen
	load cx,lodbuf
	mov di,offset snglst
	mov si,offset lodbuf
s3mld3: lodsb
	cmp al,254
	jnc s3mld4
	stosb
s3mld4:	loop s3mld3
	sub di,offset snglst
	mov ax,di
	mov snglen,al
	mov al,gs:s3mpan
        call far ptr f_respat
	jc mdlldb
	mov al,patanz           ;instrument- und pattern-parapointer laden
	add al,gs:mtmsnm
	xor ah,ah
	add ax,ax
	load ax,lodbuf

	call far ptr f_clrsm0                     ;*** instruments & samples **********
	mov gs:sgnmsk,1
	mov si,offset lodbuf
	mov di,offset smpdat
	mov smpnum,0
	movzx cx,gs:mtmsnm
s3mld5: push cx
	lodsw                   ;instrument laden
	push si
	push di
	movzx ecx,ax
	shl ecx,4
	mov dx,cx
	shr ecx,16
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	mov al,2
	jc s3mld6
	load 50h,lodbuf+1024
	mov cx,28
	mov si,offset lodbuf+1024+30h
	call messmp
	mov si,offset lodbuf+1025
	cmp [si-1],byte ptr 1
	clc
	jnz s3mld6
	pop bp
	push bp
	call ldscs
s3mld6: pop di
	pop si
	pop cx
	jc mdlsvz
	add di,smpiln
	inc smpnum
	dec cx
	jnz s3mld5

	movzx ax,gs:mtmsnm              ;*** pattern ************************
	add ax,ax
	add ax,offset lodbuf
	mov gs:mtmexl,ax
	mov edipat,0
s3mld8: call far ptr f_setpat
	mov si,gs:mtmexl
	movzx ecx,word ptr [si]
	shl ecx,4
	mov dx,cx
	shr ecx,16
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	load 2,lodbuf
	mov ax,word ptr lodbuf
	mov ds,gs:sbfseg
	load ax,0
	mov es,gs:patseg
	xor si,si
	xor di,di
	mov cx,64
s3mld9: lodsb
	or al,al
	jz s3mlde
	mov dl,al
	and al,31
	mov ah,6
	mul ah
	mov bx,ax
	shr dl,6
	jnc s3mlda
	lodsw
	mov es:[di.bx.1],ah     ;sample
	cmp al,254
	ja s3mlda
	jnz s3mldb
	inc al                  ;stopper
	jmp s3mldt
s3mldb: mov dh,al
	and dh,15
	shr al,4
	mov ah,12
	mul ah
	add al,dh
	inc al
s3mldt: mov es:[di.bx],al       ;note
s3mlda: shr dl,1
	jnc s3mldc
	lodsb
	inc al
	jz s3mldd
	dec al
	call cnvvol
s3mldd: mov es:[di.bx.2],al     ;volume
s3mldc: shr dl,1
	jnc s3mld9
	lodsw                   ;commandos

	push cx
	mov dh,al       ;dh=num
	mov al,ah       ;al=data,ah=0
	xor ah,ah
	dec dh
	mov dl,0fh      ;speed
	jnz s3mlc1
s3mlc2:	or al,al
	jnz s3mldf
	xor dl,dl
	jmp s3mldf
s3mlc1:	dec dh
	mov dl,0bh      ;position jump
	jz s3mldf
	dec dh
	mov dl,0dh      ;pattern break
	jz s3mldf
	dec dh
	jnz s3mcve
	xor dl,dl       ;volume slide
s3mcvd:	or al,al
	jnz s3mcd5

	neg cl       ;0 => identisch mit letztem volslide
	add cl,64
	jz s3mcd5
	push di
s3mcd6: sub di,32*6
	mov al,es:[di.bx.3]
	and al,0f0h
	cmp al,10h
	jz s3mcd7
	cmp al,20h
	jz s3mcd7
	loop s3mcd6
	xor al,al
	pop di
	jmp s3mcd5
s3mcd7: add dl,al
	xor ax,ax
	pop di
	jmp s3mldf

s3mcd5: mov ah,al    ;nicht 0
	shr ah,4
	and al,15
	cmp al,0fh
	jz s3mcd2
	cmp ah,0fh
	jz s3mcd3
s3mcd4: or al,al     ;normal
	jz s3mcd8
	xor ah,ah
s3mcd8: add dl,10h
	sub ah,al
	jnc s3mcd1
	add dl,10h
	neg ah
s3mcd1: shl ah,2
	xor al,al
	jmp s3mldf
s3mcd3: or al,al     ;fine
	jz s3mcd4
	xchg al,ah
	add dl,10h
s3mcd2: or ah,ah
	jz s3mcd4
	or ah,0f0h
	xor al,al
	add dl,10h
	jmp s3mldf

s3mcve: dec dh
	mov dl,2        ;slide down
	jz s3mldf
	dec dl          ;slide down
	dec dh
	jz s3mldf
	dec dh
	mov dl,3        ;portamento
	jz s3mldf
	inc dl          ;vibrato
	dec dh
	jz s3mldf
	dec dh
	jnz s3mcvj
	mov dl,50h      ;tremor
	xchg al,ah
	jmp s3mldf
s3mcvj: dec dh
	mov dl,5        ;arpeggio
	jz s3mldf
	dec dh
	mov dl,4        ;vibrato + volslide
	jz s3mcvd
	dec dl          ;portamento + volslide
	dec dh
	jz s3mcvd
	sub dh,3
	jnz s3mcvq
	mov dl,0eh      ;smp-offset
	mov ah,al
	mov al,0f0h
	jmp s3mldf
s3mcvq: sub dh,2
	jnz s3mcvr
	mov dl,30h	;note-retrig
	xchg ah,al
	jmp s3mldf
s3mcvr: dec dh
	jnz s3mcvs
	xchg al,ah      ;tremolo
	mov dl,40h
	jmp s3mldf
s3mcvs: dec dh
	jz s3mcs        ;s-commands
	dec dh
	mov dl,7        ;bpm
	jz s3mlc2
	sub dh,2
	mov dl,0ch      ;main volume
	jz s3mldf
	sub dh,2
	mov dl,8
	jz s3mldf
	xor ax,ax
	xor dl,dl
s3mldf: pop cx
	mov es:[di.bx.3],dl
	mov es:[di.bx.4],ax
	jmp s3mld9

s3mcs:  mov dh,al       ;s-commands
	shr dh,4
	and al,15
	dec dh
	mov ah,30h      ;glissando
	jz s3mcsx
	dec dh
	jnz s3mcs3
	add al,8        ;finetune
	and al,15
	mov ah,50h
	jmp s3mcsx
s3mcs3: dec dh
	mov ah,40h      ;vibrato-waveform
	jz s3mcsx
	dec dh
	mov ah,70h      ;tremolo-waveform
	jz s3mcsx
	sub dh,4
	jnz s3mcsb
	shl al,3        ;panning
	xor ah,ah
	mov dl,8
	jmp s3mldf
s3mcsb: sub dh,3
	mov ah,60h      ;pattern loop
	jz s3mcsx
	dec dh
	mov ah,0c0h     ;note cut
	jz s3mcsx
	dec dh
	mov ah,0d0h     ;note delay
	jz s3mcsx
	dec dh
	mov ah,0e0h     ;pattern delay
	jz s3mcsx
	xor ax,ax
	xor dl,dl
	jmp s3mldf
s3mcsx: or al,ah
	xor ah,ah
	mov dl,0eh
	jmp s3mldf

s3mlde: add di,32*6
	dec cx
	jnz s3mld9
	mov ds,gs:datseg
	inc edipat
	add gs:mtmexl,2
	mov al,patanz
	cmp al,edipat
	jnz s3mld8
	call far ptr f_clrem0
	jmp mdll71

s3mld   endp

flecnv:	mov di,bp
	add di,smpfle           ;filename
	mov eax,"    "
	stosd
	stosd
	mov cx,8
	sub di,cx
flecn1: lodsb
	dec cl
	cmp al,"."
	jz flecn2
	or al,al
	jz flecn2
	stosb
	or cl,cl
	jnz flecn1
flecn2: add si,cx
	ret

; CNVVOL => al=volume (0-64) => konvertiert mod-volume => al=volume (1-255)
cnvvol  proc near
	or al,al
	mov ah,1
	jz cnvvo1
	cmp al,64
	mov ah,255
	jnc cnvvo1
	mov ah,al
	shl ah,2
cnvvo1: mov al,ah
	ret
cnvvol  endp

; ULTLD => laedt ULT (ultra-tracker)
ultld	proc near
	load 15,lodbuf          	;*** kennung ************************
	mov eax,"-TLU"
	call setcom
	mov al,lodbuf+14
	sub al,"0"
	mov gs:ultvs,al
	load 32,sngnam			;*** songname ***********************
	mov es,gs:datseg
	mov di,offset sngnam
	mov cx,32
	call clrnul
	call clrmes			;*** songmessage ********************
	call clrchn
        call clrpnm
	load 1,lodbuf
	movzx ax,lodbuf
	or al,al
	jz ultld2
	shl ax,5
	load ax,lodbuf+1
	mov al,lodbuf
	cmp al,65
	jc ultl11
	mov al,64
ultl11:	mov si,offset lodbuf+1
	mov di,offset sngmes
ultld1:	mov cx,32
	rep movsb
	add di,76-32
	dec al
	jnz ultld1
ultld2:	load 1,lodbuf			;*** instruments ********************
	call far ptr f_clrsm0
	mov es,gs:datseg
	movzx cx,lodbuf
	or cl,cl
	jz ultld5
	mov bp,offset smpdat
ultld3: push cx
	cmp gs:ultvs,4
	mov ax,64
	jc ultl3a
	mov ax,66
ultl3a:	load ax,lodbuf
	mov di,bp	;name
	add di,smpnam
	mov si,offset lodbuf
	mov cx,32/4
	rep movsd
	sub di,32
	mov cx,32
	call clrnul
	call flecnv	;file
	add si,4
	lodsd
	mov ds:[bp.smprep],eax	;repeat
	mov ebx,eax
	lodsd
	sub eax,ebx
	mov ds:[bp.smprln],eax	;replen
	lodsd
	mov ebx,eax
	lodsd
	sub eax,ebx
	mov ds:[bp.smplen],eax	;length
	lodsd
	cmp al,1
	adc al,0
	mov ds:[bp.smpvol],al	;volume
	test ah,8
	jnz ultld4
	mov ds:[bp.smprln],0
	mov ds:[bp.smprep],0
ultld4:	test ah,4
	setnz al
	test ah,16
	setnz ah
	shl ah,1
	or al,ah
	mov ds:[bp.smptyp],al	;typ
	test al,1
	jz ultl4b
	shl ds:[bp.smprep],1
	shl ds:[bp.smprln],1
	shl ds:[bp.smplen],1
ultl4b:	shr eax,16		;finetune (????)
	cmp gs:ultvs,4
	jnc ultl4a
	mov eax,8363
ultl4a:	mov ds:[bp.smpfre],eax
	add bp,smpiln
	pop cx
	dec cx
	jnz ultld3
ultld5:	load 258,lodbuf                 ;*** infos **************************
	mov si,offset lodbuf	;songlist
	mov di,offset snglst
	mov cl,255
ultld6:	lodsb
	cmp al,255
	jz ultld7
	stosb
	dec cl
	jnz ultld6
ultld7:	neg cl
	add cl,255
	mov snglen,cl
	mov ax,word ptr lodbuf+256
	inc ah
	mov gs:ultpa,ah		;pattern- + channel-anz
	inc al
	mov gs:ultchn,al
	mov dl,al
	mov di,offset sngchn	;pannel-pos
	mov ax,128+256*255
	mov cx,32/2
	rep stosw
	sub di,32
	mov bp,di
ultld8:	and [di],byte ptr 127
	inc di
	dec dl
	jnz ultld8
	cmp gs:ultvs,3
	jc ultlda
	movzx ax,gs:ultchn
	load ax,lodbuf
	mov di,offset sngchn
	mov si,offset lodbuf
	movzx cx,gs:ultchn
ultld9:	lodsb
	shl al,3
	stosb
	loop ultld9
ultlda: mov al,gs:ultpa   			;*** pattern ************************
        call far ptr f_respat
	jc mdlldb
	mov gs:ultcps,0
ultldc:	mov edipat,0
ultldb: call far ptr f_setpat
	mov al,gs:ultcps
	mov ah,6
	mul ah
	mov di,ax
	mov es,gs:patseg
	mov cl,64
ultldd: push cx
	load 5,lodbuf
	cmp lodbuf,0fch
	mov cl,1
	mov si,offset lodbuf
	jnz ultlde
	load 2,lodbuf+5
	mov cl,lodbuf+1
	mov si,offset lodbuf+2
ultlde: mov dh,cl
	lodsw
	or al,al
	jz ultldg
	add al,12*2
ultldg:	mov bp,ax
	lodsb
	ror al,4
	mov dl,al
	lodsw
	xchg al,ah
	call cnvult
ultldf:	mov ax,bp
	stosw
	mov eax,ebx
	stosd
	add di,32*6-6
	dec cl
	jnz ultldf
	pop cx
	sub cl,dh
	jnz ultldd
	mov al,patanz
	inc edipat
	cmp edipat,al
	jnz ultldb
	inc gs:ultcps
	mov al,gs:ultchn
	cmp gs:ultcps,al
	jnz ultldc
	mov gs:sgnmsk,0                 ;*** samples ************************
	mov sngbpm,125
ultldy:	call ldasmp
	jc mdlsv0
	mov sngspd,6
	jmp mdll71
ultld	endp

; CNVULT => dl,ax=commando => commando-convert => ebx=vol,cmd-bytes
cnvult	proc near
	mov dword ptr gs:cnvbuf,0
	pusha
	push dx
	push ax
	mov dh,dl
	and dl,15
	call cnvul1
	cmp dl,0eh
	jnz cnvulh
	mov dh,al
	and dh,0f0h
	cmp dh,0f0h
	jnz cnvulh
	mov gs:cnvbuf+1,dl
	mov word ptr gs:cnvbuf+2,ax
	pop ax
	pop dx
	jmp cnvuli
cnvulh:	call cnvule
	pop ax
	pop dx
	xor dh,dh
	shr dl,4
	mov al,ah
	call cnvul1
	call cnvule
cnvuli:	popa
	mov ebx,dword ptr gs:cnvbuf
cnvul0: ret

; dl=num,al=data => commando reintun
cnvule:	cmp dl,22
	jnz cnvulc
	mov gs:cnvbuf,al
	ret
cnvulc:	push ax
	mov ax,word ptr gs:cnvbuf+1
	ror ax,4
	cmp ah,0efh
	pop ax
	jnz cnvuln
	ret
cnvuln:	or dl,dl
	jz cnvul0
	cmp dl,7
	jnc cnvuld
	test gs:cnvbuf+1,0fh
	jz cnvulf
	rol gs:cnvbuf+1,4
	mov ah,gs:cnvbuf+2
	mov gs:cnvbuf+3,ah
cnvulf:	and gs:cnvbuf+1,0f0h
	or gs:cnvbuf+1,dl
	mov gs:cnvbuf+2,al
	ret
cnvuld:	cmp dl,16
	jc cnvulj
	sub dl,15
	test gs:cnvbuf+1,0f0h
	jz cnvulg
	rol gs:cnvbuf+1,4
	mov ah,gs:cnvbuf+3
	mov gs:cnvbuf+2,ah
cnvulg:	shl dl,4
	and gs:cnvbuf+1,0fh
	or gs:cnvbuf+1,dl
	mov gs:cnvbuf+3,al
	ret
cnvulj:	test gs:cnvbuf+1,0fh
	jz cnvulf
	jmp cnvulg

;dl/x=cmd,al/x=data => dl=cmdnum(1-15,16-21=volcmd,0=nichts,22=vol),al/x=data
cnvul1:	or dl,dl	;arpeggio
	jnz cnvul2
	or al,al
	jz cnvul0
	mov dl,5
	ret
cnvul2:	cmp dl,4	;note slides & portamento
	jnc cnvul3
	cmp al,0e0h
	jc cnvul0
	mov al,0dfh
	ret
cnvul3:	jnz cnvul4
	rol al,4
	ret
cnvul4: cmp dl,5	;sample status
	jnz cnvulk
	or al,al
	jz cnvulz
	mov dl,0eh
	mov al,80h
	ret
cnvulk:	cmp dl,9	;sample offset
	jc cnvulz
	jnz cnvul7
	cmp dh,99h
	jnz cnvul6
	xchg al,ah
	shr ax,6
cnvul5: mov dl,0eh
	xchg al,ah
	or al,0f0h
	ret
cnvul6:	xor ah,ah
	shl ax,2
	jmp cnvul5
cnvul7:	cmp dl,0bh	;volume slide
	jnc cnvul8
	mov ah,al
	and ah,15
	shr al,4
	sub al,ah
	mov dl,16
	jnc cnvull
	inc dl
	neg al
cnvull:	shl al,2
	ret
cnvul8:	jnz cnvul9	;panning
	mov dl,8
	shl al,3
	ret
cnvul9:	cmp dl,0dh	;volume
	jnc cnvula
	cmp al,1
	adc al,0
	mov dl,22
	ret
cnvula:	jz cnvul0	;pattern break
	cmp dl,0fh	;speed
	jnz cnvulb
	cmp al,030h
	jc cnvul0
	mov dl,7
	ret
cnvulb:	cmp dl,0eh	;e-commands
	jnz cnvulz
	mov ah,al
	shr ah,4
	cmp ah,0ch	;cut note
	jz cnvul0
	cmp ah,0dh	;delay note
	jz cnvul0
	cmp ah,9	;retrig note
	jz cnvul0
	or ah,ah
	;...............vib-value - not implemented
	or al,0f0h
	mov dl,ah	;note fine slide up/down
	cmp ah,3
	jc cnvul0
	mov dl,ah	;vol fine up/down
	add dl,6
	cmp ah,0ah
	jc cnvulm
	cmp ah,0bh+1
	jc cnvul0
cnvulm:

cnvulz:	xor al,al	;kein command
	xor dl,dl
	ret
cnvult	endp

; C69LD => laedt 669 (composer 669)
c69ld	proc near
	load 01f1h,lodbuf
	cmp word ptr lodbuf,6669h	;*** 6669 kennung *******************
	stc
	jnz mdlsv0
	mov eax,"-966"
	call setcom
	mov di,offset sngnam
	mov es,gs:datseg
	mov cx,32
	mov al," "
	rep stosb
	sub di,32
	mov si,offset filnam
	mov cx,8/4
	rep movsd
	call clrmes			;*** songmessage ********************
	call clrchn
        call clrpnm
	mov si,offset lodbuf+2
	mov di,offset sngmes
	mov dl,3
c96l11:	mov cx,36/2
	rep movsw
	add di,76-36
	dec dl
	jnz c96l11
	mov al,lodbuf+6eh		;*** infos **************************
	mov gs:c69snm,al	;smpanz
	mov al,lodbuf+6fh
	mov gs:ultpa,al		;patanz
	mov al,lodbuf+70h
	mov sngrep,al		;sngrep
	mov si,offset lodbuf+71h
	mov di,offset snglst	;snglst
	mov cx,128
c69ld1:	lodsb
	cmp al,255
	jz c69lda
	stosb
	loop c69ld1
c69lda:	sub di,offset snglst
	mov ax,di
	mov snglen,al		;snglen
	mov si,offset lodbuf+0f1h
	mov di,offset lodbuf
	mov cx,80h*2/4
	rep movsd
	mov di,offset sngchn	;pannel
	mov ax,192+256*(192)
	mov cx,32/2
	rep stosw
	sub di,32
	mov cx,4
c69ldb:	mov [di],word ptr 16+256*(111)
	add di,2
	loop c69ldb
	call far ptr f_clrsm0                   ;*** instruments ********************
	mov es,gs:datseg
	mov al,gs:c69snm
	or al,al
	jz c69ld3
	mov ah,13+3*4
	mul ah
	load ax,lodbuf+80h*2
	movzx cx,gs:c69snm
	mov si,offset lodbuf+80h*2
	mov bp,offset smpdat
c69ld2:	push cx
	call flecnv
	push si
	mov di,bp
	mov si,bp
	add si,smpfle
	add di,smpnam
	movsd
	movsd
	mov al," "
	mov cx,32-8
	rep stosb
	pop si
	add si,5
	lodsd
	mov ds:[bp.smplen],eax
	lodsd
	mov ds:[bp.smprep],eax
	mov ebx,eax
	lodsd
	sub eax,ebx
	inc eax
	and eax,0fffffh
	mov ds:[bp.smprln],eax
	mov ds:[bp.smpfre],8363
	mov ds:[bp.smpvol],255
	pop cx
	add bp,smpiln
	loop c69ld2
c69ld3: mov al,gs:ultpa   			;*** pattern ************************
        call far ptr f_respat
	jc mdlldb
	mov edipat,0
c69ld4:	load 600h,lodbuf+80h*2
        call far ptr f_setpat
	mov es,gs:patseg
	mov si,offset lodbuf+80h*2
	xor di,di
	mov cl,64
c69ld5:	mov ch,8
c69ld6:	lodsw		;ax=note,smp,vol
	mov bx,ax
	cmp al,254
	jc c69ld7
	jz c69ld8
	jmp c69ld9
c69ld7:	shr al,2
	add al,2*12+1
	mov es:[di],al		;note
	mov al,bh
	mov ah,bl
	shr ax,4
	and al,63
	inc al
	mov es:[di+1],al	;sample
c69ld8: shl bh,4
	cmp bh,1
	adc bh,0
	mov es:[di+2],bh	;volume
c69ld9:	lodsb			;commando
;...
	add di,6
	dec ch
	jnz c69ld6
	add di,6*32-6*8
	loop c69ld5
	mov al,patanz
	inc edipat
	cmp al,edipat
	jnz c69ld4
	mov si,offset lodbuf		;*** speeds & breaks ****************
	mov edipat,0
c69ldc: push si
        call far ptr f_setpat
	pop si
	xor di,di
	mov es,gs:patseg
	lodsb			;speed
	mov es:[di+5],al
	or es:[di+3],byte ptr 0f0h
	mov al,[si+80h-1]	;pattern break
	mov ah,6*32
	mul ah
	mov bp,ax
	or es:[di.bp+3],byte ptr 0d0h
	mov al,patanz
	inc edipat
	cmp edipat,al
	jnz c69ldc
	mov gs:sgnmsk,1                 ;*** samples ************************
	mov sngbpm,80
	jmp ultldy
c69ld	endp

; FARLD => laedt far (farandole-composer)
farld	proc near
	load 98,lodbuf
	cmp dword ptr lodbuf,0fe524146h	;*** kennung ************************
	stc
	jnz mdlsv0
	mov eax,"-RAF"
	call setcom
	mov si,offset lodbuf+4		;*** infos **************************
	mov di,offset sngnam	;songname
	mov es,gs:datseg
	mov cx,32/4
	rep movsd
	mov cx,32
	sub di,cx
	call clrnul
	call clrmes
	call clrpnm
	call clrchn
	mov si,offset lodbuf+50	;chn-status
	mov bx,offset lodbuf+76
	mov di,offset sngchn
	mov cx,16
farld1:	lodsb
	xor al,1
	shl al,7
	mov ah,[bx]
	inc bx
	shl ah,3
	or al,ah
	stosb
	loop farld1
	mov al,080h
	mov cx,16
	rep stosb
	movzx cx,lodbuf+75
	call farspd
	mov sngbpm,al
	mov sngspd,4
	mov ax,word ptr lodbuf+96 ;song-message (berspringen...)
	or ax,ax
	jz farld2
	mov ds,gs:sbfseg
	load ax,0
	mov ds,gs:datseg
farld2:	load 256+3+2*256,lodbuf
	mov si,offset lodbuf	;song-list
	mov di,offset snglst
	mov cx,255
	xor al,al
	rep stosb
	sub di,255
	movzx cx,lodbuf+257
	mov snglen,cl
	rep movsb
	mov al,lodbuf+258	;sngrep
	mov sngrep,al
	mov si,offset lodbuf+259+254*2 ;patanz
	mov cx,255
farld3:	cmp [si],word ptr 1
	jnc farld4
	sub si,2
	loop farld3
farld4:	movzx ax,cl
	mov xmpat,ax
	mov edipat,0   			;*** pattern ************************
	call far ptr f_deapat
	mov si,offset lodbuf+259
farld5: mov ax,[si]
	add si,2
	or ax,ax
	jz farlc2
	push si
	push ax
	sub ax,2
	shr ax,6
	dec ax
	call far ptr f_inspat
	pop ax
	pop si
	jc mdlldb
	mov di,ax
	mov ds,gs:sbfseg
	load ax,0
	push si
	mov si,2
	mov es,gs:patseg
	mov cx,di
	sub cx,2
	xor di,di
	shr cx,6

farld6:	mov ch,16
farld7:	lodsb	;note
	add di,2
	or al,al
	jz farldc
	sub di,2
	add al,12*3
	stosb
	lodsb	;sample
	inc al
	stosb
	dec si
farldc:	lodsb
	lodsb	;volume
	or al,al
	jz farldd
	dec al
	shl al,2
	call cnvvol
farldd:	stosb
	lodsb
	push cx
	call cnfar
	pop cx
	add di,3
	dec ch
	jnz farld7
	add di,16*6
	loop farld6

	pop si
	mov ds,gs:datseg
farlc2:	inc edipat
	mov al,byte ptr xmpat
	cmp al,edipat
	jnz farld5
	load 8,lodbuf			;*** samples ************************
	mov gs:sgnmsk,0
	call far ptr f_clrsm0
	mov smpnum,0
farld8:	movzx bx,smpnum
	mov cl,bl
	mov al,1
	and cl,7
	shl al,cl
	shr bl,3
	test [bx.lodbuf],al
	jz farlda
	mov si,offset lodbuf+8
	load 48,si
        call far ptr f_smpadr
	mov di,bx
	add di,smpnam
	mov cx,32/4
	mov es,gs:datseg
	rep movsd
	mov cx,32
	sub di,cx
	call clrnul
	lodsd			;length
	mov [bx.smplen],eax
	lodsw			;finetune&volume (...not supported)
	mov [bx.smpvol],255
	mov [bx.smpfre],8363
	lodsd			;repeat
	mov ecx,eax
	lodsd			;repend
	mov edx,eax
	lodsw			;type & loop
	and al,1
	mov [bx.smptyp],al
	or ah,ah
	mov [bx.smprep],0
	mov [bx.smprln],0
	jz farld9
	mov [bx.smprep],ecx
	sub edx,ecx
	sub edx,1
	adc edx,0
	inc edx
	mov [bx.smprln],edx
farld9:	call ldasm0
	jc mdlsvz
farlda:	inc smpnum
	cmp smpnum,64
	jc farld8
farla1:	call sfnmak
	jmp mdll71		;ende

;al=commando, di=ziel => convertiert effects
cnfar:	mov ah,al
	and al,15
	shr ah,4
	cmp ah,0fh	;speed
	jnz cnfar2
	movzx cx,al
	call farspd
	mov es:[di],byte ptr 07h
cnfar1:	mov es:[di+1],al
	ret
cnfar2:	cmp ah,0bh	;panning
	jnz cnfar3
	shl al,3
	mov es:[di],byte ptr 08h
	jmp cnfar1
cnfar3:	ret	;#########

farspd: cmp cx,1
	adc cx,0
	mov ax,320
	xor dx,dx
	div cx
	cmp ax,256
	jc cnfar1
	mov al,255
	ret

farld	endp

; PTMLD => laedt ptm (polytracker)
ptmld	proc near
	load 608,lodbuf
	cmp dword ptr lodbuf+44,"FMTP"	;*** kennung ************************
	stc
	jnz mdlsv0
	cmp word ptr lodbuf+29,203h
	stc
	jnz mdlsv0
	mov eax,"-MTP"
	call setcom
	call clrmes
	call clrpnm
	call clrchn
	mov di,offset sngnam		;*** infos **************************
	mov es,gs:datseg
	mov si,offset lodbuf	;song-name
	mov cx,28/4
	rep movsd
	mov eax,"    "
	stosd
	mov cx,28
	mov di,offset sngnam
	call clrnul
	mov sngvol,255
	mov si,offset lodbuf+32
	lodsw
	sub al,ah
	mov snglen,al		;laenge
	mov sngrep,0
	lodsw
	mov gs:xmins,al		;anz.samples
	lodsw
	sub al,ah
	push si
        call far ptr f_respat   ;pattern
	pop si
	jc mdlldb
	mov es,gs:datseg
	lodsw
	mov si,offset lodbuf+64	;kanaele
	mov di,offset sngchn
	mov cx,32
	mov ah,33
	sub ah,al
ptmld1:	lodsb
	shl al,4
	cmp cl,ah
	rcr al,1
	stosb
	loop ptmld1
	mov si,offset lodbuf+96	;songlist
	mov di,offset snglst
	mov cx,255
	rep movsb

	mov smpnum,0                    ;*** sample-infos *******************
	call far ptr f_clrsm0
	cmp gs:xmins,0
	jz ptmld8
	mov gs:mtmexl,offset lodbuf+608
ptmld9: load 80,lodbuf+2000
        call far ptr f_smpadr
	mov si,offset lodbuf+2000+48	;smpnam in songmessage kopieren
	mov cx,28
	call messmp
	mov si,offset lodbuf+2000+22
	lodsd
	mov [bx.smplen],eax
	lodsd
	mov [bx.smprep],eax
	mov ecx,eax
	lodsd
	sub eax,ecx
	mov [bx.smprln],eax
	mov al,lodbuf+2000+13
	call cnvvol
	mov [bx.smpvol],al
	movzx eax,word ptr lodbuf+2000+14
	mov [bx.smpfre],eax
	mov si,offset lodbuf+2000+1
	mov bp,bx
	mov es,gs:datseg
	call flecnv
	mov si,offset lodbuf+2000+48
	mov di,bx
	add di,smpnam
	mov cx,28/4
	rep movsd
	mov eax,"    "
	stosd
	mov cx,32
	sub di,cx
	call clrnul
	mov eax,dword ptr lodbuf+2000+18
	mov si,gs:mtmexl
	add gs:mtmexl,4
	mov [si],eax
	mov ah,lodbuf+2000+46
	test ah,8
	jnz ptmlda
	mov [bx.smprln],0
	mov [bx.smprep],0
ptmlda:	test ah,4
	setnz al
	test ah,16
	setnz ah
	shl ah,1
	or al,ah
	mov [bx.smptyp],al
	inc smpnum
	mov al,smpnum
	cmp al,gs:xmins
	jnz ptmld9

	mov gs:mtmexl,offset lodbuf+608	;*** sample-datas *******************
	mov smpnum,0
ptmldb:	mov si,gs:mtmexl
	add gs:mtmexl,4
	mov cx,[si+2]
	mov dx,[si]
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov gs:xmlast,0
	mov gs:sgnjmp,offset xmldh1
	mov gs:ldajmp,offset lodsm4
	call ldasm0
	mov gs:ldajmp,offset lodsm0
	jc mdlsv0
	inc smpnum
	mov al,smpnum
	cmp al,gs:xmins
	jnz ptmldb

ptmld8:	mov edipat,0			;*** pattern ************************
	mov gs:mtmexl,offset lodbuf+352
ptmld2: call far ptr f_setpat
	mov si,gs:mtmexl
	add gs:mtmexl,2
	movzx ecx,word ptr [si]
	shl ecx,4
	mov dx,cx
	shr ecx,16
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov ds,gs:sbfseg
	mov cx,12*1024
	xor dx,dx
	mov ah,3fh
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov es,gs:patseg
	xor si,si
	xor di,di
	mov cx,64
ptmld3: lodsb
	or al,al
	jz ptmld7
	mov dl,al
	and al,31
	mov ah,6
	mul ah
	mov bx,ax
	shr dl,6
	jnc ptmld5
	lodsw
	mov es:[di.bx.1],ah     ;sample

;...note eventuell convertieren

	mov es:[di.bx],al	;note
ptmld5:	shr dl,1
	jnc ptmld4
	add di,bx
	push cx
	push bx
	push dx
	lodsw			;effects
	mov bx,ax
	mov dl,bl
	mov al,ah
	xor ah,ah
	cmp dl,1	;noteslide
	jz ptmldc
	cmp dl,2
	jz ptmldc
	cmp dl,0ah
	jnz ptmldd
	xor dl,dl	;volslide
	mov ah,al
	shr ah,4
	and al,15
	cmp al,0fh
	jz ptmla2
	cmp ah,0fh
	jz ptmla3
ptmla4: or al,al     ;normal
	jz ptmla8
	xor ah,ah
ptmla8: add dl,10h
	sub ah,al
	jnc ptmla1
	add dl,10h
	neg ah
ptmla1: shl ah,2
	xor al,al
	jmp ptmldc
ptmla3: or al,al     ;fine
	jz ptmla4
	xchg al,ah
	add dl,10h
ptmla2: or ah,ah
	jz ptmla4
	or ah,0f0h
	xor al,al
	add dl,10h
	jmp ptmldc
ptmldd:	cmp bl,16
	jnc ptmldf
	call cvmox1
	jmp ptmlde
ptmldf:	sub bl,16       ;main volume
	jnz ptmldg
	call cnvvol
	xor ah,ah
	mov dl,0ch
	jmp ptmldc
ptmldg:	sub bl,2	;multi retrig
	jnc ptmldh
	mov ah,al
	xor al,al
	mov dl,30h
	jmp ptmldc
ptmldh:

;...commandos h-m

	xor dl,dl
	xor ax,ax
ptmldc:	call cvmod5
ptmlde:	pop dx
	pop bx
	pop cx
	sub di,bx
ptmld4:	shr dl,1
	jnc ptmld3
	lodsb
	inc al
	jz ptmld6
	dec al
	call cnvvol
ptmld6:	mov es:[di.bx.2],al     ;volume
	jmp ptmld3
ptmld7:	add di,6*32
	dec cx
	jnz ptmld3
	mov ds,gs:datseg
	inc edipat
	mov al,patanz
	cmp al,edipat
	jnz ptmld2
	jmp mtmld6
ptmld	endp

; DMFLD => laedt dmf (x-tracker)
dmfld	proc near
	load 42h,lodbuf			;*** header *************************
	cmp dword ptr lodbuf,"FMDD"
	stc
	jnz mdlsv0
	mov al,lodbuf+4
	cmp al,5
	jc mdlsv0
	cmp al,8+1
	cmc
	jc mdlsv0
	mov gs:ultvs,al
	mov si,offset lodbuf+0dh	;songname
	mov di,offset sngnam
	mov es,gs:datseg
	mov cx,30/2
	rep movsw
	xor ax,ax
	stosw
	mov cx,32
	sub di,cx
	call clrnul
	mov di,offset sngcom		;composer
	mov cx,20/2
	rep movsw
	mov cx,20
	sub di,cx
	call clrnul
	call clrmes
	call clrchn
	call clrpnm
	mov sngspd,3
	mov sngbpm,125

	load 9,lodbuf			;*** song-message *******************
	mov ax,word ptr lodbuf+4
	dec ax
	mov ds,gs:sbfseg
	mov di,ax
	load ax,0
	mov ax,di
	cmp ax,40*64
	jna dmfld1
	mov ax,40*64
dmfld1:	mov dl,40
	div dl		;al=anzahl zeilen
	or al,al
	jz dmfld3
	mov di,offset sngmes
	mov es,gs:datseg
	xor si,si
dmfld2:	mov cx,40/2
	rep movsw
	add di,76-40
	dec al
	jnz dmfld2
dmfld3:	mov ds,gs:datseg
	mov di,offset sngmes
	mov cx,64*76
	call clrnul

	load 12,lodbuf			;*** songlist ***********************
	mov ax,word ptr lodbuf+4
	sub ax,4
	mov bx,ax
	mov ax,word ptr lodbuf+10
	inc ax
	cmp ax,256
	jc dmfl41
	mov al,255
dmfl41:	mov snglen,al		;snglen
	mov al,lodbuf+8
	mov sngrep,al		;sngrep
	load bx,lodbuf
	mov si,offset lodbuf
	mov di,offset snglst
	movzx cx,snglen
dmfld4:	lodsw
	mov [di],al
	inc di
	loop dmfld4

	load 0bh,lodbuf			;*** pattern ************************
	mov ax,word ptr lodbuf+8
	cmp ax,256
	cmc
	jc mdlldb
	mov byte ptr xmpat,al
	or al,al
	jz dmfldk
	call far ptr f_deapat
	mov ch,lodbuf+10	;chnanz
	mov cl,32
	sub cl,ch
	mov di,offset sngchn
	mov al,16
	mov es,gs:datseg
dmfld5: stosb
	xor al,(111 xor 16)
	dec ch
	jnz dmfld5
	or cl,cl
	jz dmfld6
	mov al,128+64
	rep stosb
dmfld6:	load 8,lodbuf			;** pattern-loop
	mov ax,word ptr lodbuf
	mov gs:xmins,al		;trkanz
	shr ah,4
	mov gs:dmfbet,ah	;beat
	mov gs:dmfspd,1
	mov ax,word ptr lodbuf+2
	dec ax
	cmp ax,255
	jna dmfld7
	mov al,255
dmfld7:	call far ptr f_inspat	;posanz
	jc mdlldb
	mov di,word ptr lodbuf+4
	mov ds,gs:sbfseg
	load di,0		;datas laden
	mov es,gs:patseg
	xor si,si
	xor di,di
	xor bx,bx		;counters loeschen
	mov cl,33
dmfld8: dec bx
	mov [bx],byte ptr 0
	dec cl
	jnz dmfld8
	mov cx,gs:edipl1

dmfld9: push cx			;** pos-loop
	push di
	mov bp,-33
	mov cl,gs:xmins
	sub ds:[bp],byte ptr 1
	jnc dmfldb
	mov ds:[bp],byte ptr 0
	lodsb
	mov ah,al
	test ah,128
	jz dmflda
	lodsb
	mov ds:[bp],al
dmflda: and ah,63
	jz dmfldb
	lodsb
	mov gs:dmfglo,ax ;global-effect
dmfldb:	push cx			;** track-loop
	inc bp
	sub ds:[bp],byte ptr 1
	jnc dmfldc
	mov ds:[bp],byte ptr 0
	lodsb
	mov dl,al
	shl dl,1	;loop
	jnc dmfldd
	lodsb
	mov ds:[bp],al
dmfldd:	shl dl,1		;*** instrument
	jnc dmflde
	lodsb
	mov es:[di+1],al
dmflde:	shl dl,1		;*** note
	jnc dmfldg
	lodsb
	or al,al
	jz dmfldf
	cmp al,-1
	jz dmfldf
	and al,127
	add al,12
dmfldf:	mov es:[di],al
dmfldg:	shl dl,1		;*** volume
	jnc dmfldh
	lodsb
	mov es:[di+2],al
dmfldh: shl dl,1		;*** instrument-effect
	jnc dmfldi
	lodsw
	call dmfci
dmfldi:	shl dl,1		;*** note-effect
	jnc dmfldj
	lodsw
	call dmfcn
dmfldj:	shl dl,1		;*** volume-effect
	jnc dmfldc
	lodsw
	call dmfcv
dmfldc: add di,6		;*** next track
	pop cx
	dec cl
	jnz dmfldb
	pop di
	xor ax,ax
	xchg ax,gs:dmfglo	;*** global effect
	sub ah,1
	jc dmflc2
	jnz dmflc6
	mov gs:dmftik,al
	mov gs:dmftyp,0
	jmp dmflc7
dmflc6:	dec ah
	jnz dmflc8
	mov gs:dmfbpm,al
	mov gs:dmftyp,1
	jmp dmflc7
dmflc8:	dec ah
	jnz dmflc2
	shr al,4
	mov gs:dmfbet,al
dmflc7:	mov gs:dmfspd,1
dmflc2:	xor al,al		;*** speed setzen
	xchg al,gs:dmfspd
	sub al,1
	jc dmflc1
	cmp gs:dmftyp,0
	jz dmflc4
	mov al,gs:dmfbet	;in bpm
	or al,al
	jz dmflc4
	mul gs:dmfbpm
	xor dx,dx
	mov cx,8
	div cx
	cmp dx,4
	jc dmflc3
	inc ax
	jmp dmflc3
dmflc4:	mov ah,gs:dmftik	;in ticks
	shr ax,2
	inc ah
	mov cx,3*125/25
	mul cx
	mov cx,256*50/25
	div cx
	movzx dx,dh
	add ax,dx
dmflc3:	cmp ax,256
	jc dmflc5
	mov al,255
dmflc5: mov cl,gs:xmins		;al=bpm, einordnen
	push di
dmflc9:	test es:[di+3],byte ptr 0fh
	jnz dmflca
dmflcc:	or es:[di+3],byte ptr 7
	mov es:[di+4],al
	jmp dmflcd
dmflca:	test es:[di+3],byte ptr 0f0h
	jnz dmflcb
	or es:[di+3],byte ptr 70h
	mov es:[di+5],al
	jmp dmflcd
dmflcb:	add di,6
	dec cl
	jnz dmflc9
	pop di
	push di
	jmp dmflcc
dmflcd:	pop di
dmflc1:	add di,32*6		;next pos
	pop cx
	dec cx
	jnz dmfld9
	mov ds,gs:datseg
	dec byte ptr xmpat
	jnz dmfld6

dmfldk:	load 9,lodbuf                   ;*** sample-infos *******************
	call far ptr f_clrsm0
	mov al,lodbuf+8
	or al,al
	jz mdll71
	mov gs:xmsmp,al
	mov gs:xmins,al
	mov ax,word ptr lodbuf+4
	dec ax
	mov ds,gs:sbfseg
	load ax,0
	mov es,gs:datseg
	xor si,si
	mov bx,offset smpdat
dmfldl:	lodsb			;name
	or al,al
	jz dmfldm
	xor ah,ah
	mov cx,ax
	neg ax
	add ax,32
	mov di,bx
	add di,smpnam
	rep movsb
	mov cx,ax
	mov al," "
	rep stosb
	mov cx,32
	sub di,cx
	call clrnul
dmfldm:	lodsd
	mov es:[bx.smplen],eax	;len
	lodsd
	mov es:[bx.smprep],eax	;rep
	mov ecx,eax
	lodsd
	sub eax,ecx
	inc eax
	mov es:[bx.smprln],eax	;replen
	lodsw
	movzx eax,ax
	mov es:[bx.smpfre],eax	;frq
	lodsw
	mov es:[bx.smpvol],al	;vol (0=aus)
	test ah,128
	stc
	jnz mdlsv0
	test ah,1
	jnz dmfldn
	mov es:[bx.smprln],0	;loop on/off
dmfldn:	mov al,ah
	shr al,1
	and al,1
	and ah,0ch
	or al,ah
	mov es:[bx.smptyp],al	;typ
	cmp gs:ultvs,8
	jc dmfln1
	add si,8		;library skippen (bei v8)
dmfln1:	add si,6		;filler/crc32 skippen
	add bx,smpiln
	dec gs:xmins
	jnz dmfldl
	mov ds,gs:datseg

	load 8,lodbuf                   ;*** sample-datas *******************
	mov gs:sgnmsk,0
	mov smpnum,0
dmfldo:	load 4,lodbuf		;data-len
	call far ptr f_getlen
	jz dmfldp
	test [bx.smptyp],4
	jnz dmfldq
	call ldasm0		;** ungepackten sample laden
	jc mdlsvz
dmfldp:	inc smpnum
	dec gs:xmsmp
	jnz dmfldo
	jmp mdll71

dmfldq: mov [bx.smplen],0	;** gepackten sample laden
	mov gs:clslen,ecx	;len sample
	call far ptr f_csmlen
	jc mdlldb
	call s2icnv
	movzx bx,smpnum
	shl bx,2
	mov eax,[bx.smpofs]
	mov gs:dcziel,eax	;adr sample
	mov eax,dword ptr lodbuf
	mov gs:crnlen,eax
	mov si,65536-4		;si=crunch
	mov ch,1		;ch=bitcount
	mov ds,gs:sbfseg
	mov es,gs:sbfseg
	mov fs,gs:datseg

	call dmfmt		;baum erzeugen

	xor dh,dh		;dh=altes byte
dmfde0: mov ebp,gs:clslen
	cmp ebp,32768+1
	jc dmfde9
	mov ebp,32768
dmfde9: sub gs:clslen,ebp
	xor di,di
	mov gs:dcblen,bp

dmfde1: push bp
	xor dl,dl	;dl=maske
	call getbit
	sbb dl,0
	xor al,al	;al=nodepos
dmfde2: xor ah,ah
	mov bp,ax
	shl bp,2
	add bp,ax	;[bp+...]=node
	call getbit
	mov ax,word ptr fs:[bp.lodbuf.6000]
	jnc dmfde3
	mov ax,word ptr fs:[bp.lodbuf.6002]
dmfde3: mov bp,ax
	shl bp,2
	add bp,ax	;bp=auf neuer pos
	cmp word ptr fs:[bp.lodbuf.6000],0ffffh
	jnz dmfde2
	cmp word ptr fs:[bp.lodbuf.6002],0ffffh
	jnz dmfde2
	mov al,fs:[bp.lodbuf.6004]
	xor al,dl			;ah=delta
	add al,dh
	mov dh,al
	stosb
	pop bp
	dec bp
	jnz dmfde1

	pusha		;sample-teil speichern
	push ebx
	xor si,si
	movzx ecx,gs:dcblen
	mov edi,gs:dcziel
	add gs:dcziel,ecx
	call far ptr f_smpsto
	pop ebx
	popa
	cmp gs:clslen,0
	jnz dmfde0
	mov ds,gs:datseg
	jmp dmfldp

; DMFCI => al=cmdnum, ah=data, es:[di]=noteslot => convertiert inst-effect
dmfci	proc near
	sub al,1
	jc dmfci0
	jnz dmfci1
	mov es:[di],byte ptr -1	;stopper
dmfci0:	ret
dmfci1:	sub al,2
	mov cx,0e80h		;stop sample-loop
	jc dmfcv5
	mov ch,0d1h		;restart sample (note delay 1)
	jz dmfcv5
	sub al,2
	jc dmfcv5		;retrigger sample (1mal=not delay 1)
	mov cx,0e91h            ;retrigger sample
	jz dmfcv5
	dec al
	jnz dmfci0
	mov es:[di+5],ah	;set sample offset
	mov es:[di+3],byte ptr 0eh
	mov es:[di+4],byte ptr 0f0h
	ret
dmfci	endp

; DMFCN => al=cmdnum, ah=data, es:[di]=noteslot => convertiert note-effect
dmfcn	proc near
	sub al,1
	jc dmfcn0
	jnz dmfcn2
	shr ah,16		;finetune
	or ah,50h
dmfcn1:	mov ch,ah
	mov cl,0eh
	jmp dmfcv5
dmfcn2:	sub al,2
	jz dmfcn3
	jnc dmfcn5
	shr ah,7		;note-delay
	or ah,0d0h
	jmp dmfcn1
dmfcn3:	mov cl,5		;arpeggio
	mov ch,ah
dmfcn4:	and es:[di+3],byte ptr 0f0h
	or es:[di+3],cl
	mov es:[di+4],ch
dmfcn0:	ret
dmfcn5: mov cx,ax
	shr ch,1
	cmp al,4		;note slide up/down/portamento
	jc dmfcn4
	sub al,5
	jc dmfcn0		;scratch to note (#)
	cmp al,3
	mov cl,4		;vibrato
	mov ch,ah
	jc dmfcn4
	jz dmfcv9		;tremor
	dec al
	jnz dmfcn0
	shr ah,7		;note-cut
	or ah,0c0h
	jmp dmfcn1
dmfcn	endp

; DMFCV => al=cmdnum, ah=data, es:[di]=noteslot => convertiert vol-effect
dmfcv	proc near
	or al,al
	jz dmfcv0
	cmp al,3
dmfcv9:	mov cx,4*16+256*11h	;tremor (einfach 1-1)
	jz dmfcv2
	jnc dmfcv4
	shl al,4		;volume slide up/down
	cmp ah,16
	jnc dmfcv3
	or ah,0e0h
dmfcv1:	mov cx,ax
dmfcv2:	and es:[di+3],byte ptr 0fh
	or es:[di+3],cl
	mov es:[di+5],ch
	ret
dmfcv3:	shr ah,1
	jmp dmfcv1
dmfcv4:	mov cl,3*16		;tremolo (data uebernehmen)
	mov ch,ah
	sub al,7
	jc dmfcv2
	jnz dmfcv7
	mov cl,8		;panning
	mov ch,ah
	shr ch,1
dmfcv5: mov al,0f0h		;cx=cmd+dat => platz suchen und eintragen
	mov bx,4
	test es:[di+3],byte ptr 0fh
	jz dmfcv6
	mov al,0fh
	shl cl,4
	inc bx
dmfcv6:	and es:[di+3],al
	or es:[di+3],cl
	mov es:[di+bx],ch
dmfcv0:	ret
dmfcv7:	cmp al,3
	jnc dmfcv0
	shl al,4		;pan-slide
	mov cl,0eh
	mov ch,ah
	shr ch,2
	adc ch,0
	cmp ch,16
	jc dmfcv8
	mov ch,15
dmfcv8:	add ch,al
	jmp dmfcv5
dmfcv	endp

; DMFMT => erzeugt huffman-baum => lodbuf+6000(l2,r2,v1) = baum
dmfmt	proc near
	mov word ptr gs:dmflnd,0
	mov bp,offset lodbuf+5000	;bp=rekursive-stack
dmfmt1:	mov al,gs:dmfcnd
	xor ah,ah
	mov di,ax
	shl di,2
	add di,ax			;di=tree(nodecnt).value
	rept 7
	call getbit
	rcr al,1
	endm
	shr al,1
	mov fs:[di+lodbuf+6004],al	;tree(nodecnt).value=7bits
	xor al,al
	call getbit
	rcl al,1
	call getbit
	rcl al,1		;al(1)=left,al(0)=right
	mov ah,gs:dmflnd	;ah=actnode
	inc gs:dmfcnd
	mov dl,gs:dmfcnd
	mov gs:dmflnd,dl
	movzx dx,ah
	mov di,dx
	shl di,2
	add di,dx
	test al,2
	jz dmfmt2
	movzx dx,gs:dmflnd
	mov word ptr fs:[di+lodbuf+6000],dx
	mov fs:[bp],ax
	add bp,2
	jmp dmfmt1
dmfmt2: mov word ptr fs:[di+lodbuf+6000],0ffffh
dmfmt3:	movzx dx,ah
	mov di,dx
	shl di,2
	add di,dx
	test al,1
	jz dmfmt4
	movzx dx,gs:dmflnd
	mov word ptr fs:[di+lodbuf+6002],dx
	or al,128
	mov fs:[bp],ax
	add bp,2
	jmp dmfmt1
dmfmt4: mov word ptr fs:[di+lodbuf+6002],0ffffh
dmfmt5:	cmp bp,offset lodbuf+5000
	jnz dmfmt6
	ret
dmfmt6:	sub bp,2
	mov ax,fs:[bp]
	test al,128
	jz dmfmt3
	jmp dmfmt5
dmfmt	endp

dmfld	endp

; OKTLD => loadt okt (oktalizer)
oktld	proc near
	load 24,lodbuf
;...
	jmp mdll71	;(sndin0!)
oktld	endp

; DSMLD => laedt dsm (dynamic studio)
dsmld	proc near
	load 64,lodbuf
	mov si,offset lodbuf		;*** kennung ************************
	lodsd
	cmp eax,"D"+256*"S"+65536*"m"+1000000h*1ah
	stc
	jnz mdlsv0
	lodsb
	cmp al,20h
	stc
	jnz mdlsv0
	mov di,offset sngnam		;*** infos **************************
	mov es,gs:datseg        ;songname
	mov cx,20/2
	rep movsw
	mov eax,"    "
	stosd
	stosd
	stosd
	mov di,offset sngcom	;composer
	mov cx,20/2
	rep movsw
	lodsb
	mov gs:xmins,al		;chnanz
	lodsw
	mov gs:xmsmp,al		;smpanz
	mov snglen,ah		;snglen
	inc si
	lodsb
	cmp al,101
	jc dsmld1
	mov al,100
dsmld1:	mov ah,255
	mul ah
	mov dl,100
	div dl
	cmp al,1
	adc al,0
	mov sngvol,al		;mainvol
	movzx ax,lodbuf+45
	add al,snglen
	load ax,lodbuf
	mov di,offset sngchn	;pannings
	mov si,offset lodbuf
	movzx cx,gs:xmins
dsmld2:	lodsb
	shl al,3
	and al,127
	stosb
	loop dsmld2
	mov cx,32
	sub cl,gs:xmins
	mov al,128
	rep stosb
	mov di,offset snglst	;snglst
	movzx cx,snglen
	xor ah,ah
dsmld3: lodsb
	stosb
	cmp ah,al
	jnc dsmld4
	mov ah,al
dsmld4:	loop dsmld3
	mov al,ah
	inc al
	call far ptr f_respat	;patanz
	jnc dsmld5
	mov al,3
	ret
dsmld5:	mov al,patanz		;tracknamen ueberspringen
	mul gs:xmins
	shl ax,3
	mov dx,ax
	xor cx,cx
	mov ax,4201h
	mov bx,gs:fhandl
	int 21h

	call clrmes
	call clrchn
	call clrpnm

	call far ptr f_clrsm0           ;*** sample-infos *******************
	movzx ax,gs:xmsmp
	shl ax,5
	load ax,lodbuf
	mov bx,offset smpdat
	mov es,gs:datseg
	mov si,offset lodbuf
	movzx bp,gs:xmsmp
dsmld6:	mov di,bx       	;name
	add di,smpnam
	mov cx,22
	call messmp
	mov cx,22/2
	rep movsw
	mov ax,"  "
	mov cx,10/2
	rep stosw
	lodsb
	shr al,3
	dec al
	mov [bx.smptyp],al	;typ
	xor eax,eax
	lodsw
	mov [bx.smplen],eax
	lodsb
	and al,15       	;finetune
	add al,al
	movzx di,al
	mov ax,gs:[di.ftfreq]
	mov [bx.smpfre],eax
	lodsb
	call cnvvol
	mov [bx.smpvol],al	;vol
	lodsw
	mov [bx.smprep],eax	;rep
	lodsw
	cmp ax,3
	jnc dsmld7
	xor al,al
dsmld7:	mov [bx.smprln],eax	;replen
	inc si
	add bx,smpiln
	dec bp
	jnz dsmld6
	call sfnmak	;samplenamen in filenamen konvertiern

	mov edipat,0                    ;*** patterns ***********************
dsmld8: call far ptr f_setpat
	mov ah,gs:xmins
        xor al,al
	load ax,lodbuf
        mov si,offset lodbuf
        mov es,gs:patseg
	xor di,di
        mov cl,64
dsmld9: mov ch,gs:xmins
        push di
dsmlda: lodsw
	mov es:[di+1],al
	shr ah,1
	jz dsmldb
	add ah,12*2
dsmldb:	mov es:[di],ah
        lodsw
	mov bx,ax
	cmp bl,8
	jnz dsmldc
	cmp bh,16
	jnc dsmldd
dsmldc:	cmp bl,16
	jc dsmlde
	and bl,0fh
	jz dsmldd
	cmp bl,3
	jnc dsmldd
dsmlde:	pusha
	call cvmox1
	popa
dsmldd:	add di,6
	dec ch
        jnz dsmlda
        pop di
	add di,32*6
        dec cl
	jnz dsmld9
	mov al,patanz
	inc edipat
	cmp edipat,al
	jnz dsmld8

	jmp modldh                      ;*** samples ************************
dsmld	endp

; XMLD => laedt xm (fasttracker 2)
xmld	proc near
	load 60+20+256,lodbuf
	cmp dword ptr lodbuf,"etxE"	;*** kennung ************************
	stc
	jnz mdlsv0
	cmp dword ptr lodbuf+38,"tsaF"
	jnz xmld03
	cmp dword ptr lodbuf+42,"carT"
	jnz xmld03
	mov eax,"-MX "
	call setcom
	jmp xmld04
xmld03:	mov si,offset lodbuf+38
	mov di,offset sngcom
	mov es,gs:datseg
	mov cx,20/2
	rep movsw
xmld04:	call clrmes
	call clrpnm
	call clrchn
	mov di,offset sngnam		;*** infos **************************
	mov es,gs:datseg
	mov si,offset lodbuf+17	;song-name
	mov cx,20/4
	rep movsd
	mov eax,"    "
	stosd
	stosd
	stosd
	mov cx,20
	mov di,offset sngnam
	call clrnul
	add si,21
	lodsw
	cmp ax,0104h		;version
	mov al,1
	jc mdlsvz
	lodsd
	add eax,60		;header-laenge beruecksichtigen
	mov dx,ax
	shr eax,16
	mov cx,ax
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	jc mdlsv0
	mov sngvol,255
	lodsw
	mov snglen,al		;laenge
	lodsw
	mov sngrep,al		;repeat
	lodsw
	mov gs:xmchns,al
	shr al,1
	mov dx,ax
	mov di,offset sngchn	;kanaele
	mov cx,16
	mov ax,192*256+192
	rep stosw
	mov cx,dx
	sub di,32
	mov ax,256*64+64
	rep stosw
	lodsw
	mov xmpat,ax
	lodsw
	mov gs:xmins,al
	lodsw
	lodsw
	mov sngspd,al		;speed
	lodsw
	mov sngbpm,al		;bpm
	mov es,gs:datseg
	mov di,offset snglst	;songlist
	mov cx,255
	rep movsb
	mov si,offset snglst
	movzx cx,snglen
	or cl,cl
	jz xmld13
	xor ah,ah
xmld11:	lodsb
	cmp ah,al
	jnc xmld12
	mov ah,al
xmld12:	loop xmld11
	movzx ax,ah
	sub ax,xmpat
	mov xmpate,0
	jc xmld13
	inc ax
	mov xmpate,ax

xmld13:	mov edipat,0			;*** pattern ************************
	cmp xmpat,0
	jz xmldd1
	call far ptr f_deapat
xmld1:	load 9,lodbuf
	mov ax,word ptr lodbuf+5
	dec ax
	call far ptr f_inspat
	jc mdlldb
	mov ax,word ptr lodbuf+7
	or ax,ax
	jz xmldx2
	mov cx,word ptr lodbuf+5
	push cx
	mov ds,gs:sbfseg
	load ax,0
	pop cx
	mov es,gs:patseg
	xor di,di
	xor si,si
xmld3:	push cx
	push di
	movzx cx,gs:xmchns
	mov gs:cvmchn,0
xmld4:	push cx
	lodsb
	dec si
	test al,128
	mov ah,-1
	jz xmld5
	mov ah,al
	inc si
xmld5:	shr ah,1		;note
	jnc xmld8
	lodsb
	cmp al,97
	jc xmld7
	mov al,255
xmld7:	mov es:[di],al
xmld8:	shr ah,1		;instrument
	jnc xmld9
	lodsb
	mov es:[di+1],al
xmld9:  mov gs:xmvcmd,0
	shr ah,1		;volume
	jnc xmlda
	lodsb
	cmp al,10h
	jc xmlda
	cmp al,50h+1
	jnc xmldo
	sub al,10h
	mov bl,ah
	call cnvvol
	mov ah,bl
	mov es:[di+2],al
	jmp xmlda
xmldo:  push ax
	mov bl,al
	shr bl,4
	and al,15	;al=dat,bl=num
	shl al,2
	sub bl,6	;vol down
	mov ah,17
	jz xmldp
	dec ah		;vol up
	dec bl
	jz xmldp
	shr al,2
	or al,0f0h
	inc ah
	dec bl		;fine vol down
	jz xmldp
	dec ah		;fine vol up
	dec bl
	jz xmldp
	shl al,4
	mov ah,4	;vibrato-speed
	dec bl
	jz xmldp
	shr al,4	;vibrato
	dec bl
	jz xmldp
	shl al,3
	mov ah,8	;panning
	dec bl
	jz xmldp
	shr al,3
	mov bh,al
	shr al,1
	cmp al,1
	adc al,0
	or al,10h	;pan left
	mov ah,0eh
	dec bl
	jz xmldp
	add al,10h	;pan right
	dec bl
	jz xmldp
	mov al,bh	;tone porta
	shl al,4
	mov ah,3
xmldp:	mov gs:xmvcmd,ax
	pop ax
xmlda:  xor bx,bx
	shr ah,1		;command
	jnc xmldb
	lodsb
	mov bl,al
xmldb:	shr ah,1
	jnc xmldc
	lodsb
	mov bh,al
xmldc:	cmp bl,16
	jc xmldv
	mov al,bh
	xor ah,ah
	cmp bl,16	;main volume
	jnz xmldc4
	mov dl,0ch
	call cnvvol
	xor ah,ah
	jmp xmldw
xmldc4:	cmp bl,17	;main volslide
	jnz xmldc1
	mov bh,al
	and bh,15
	shr al,4
	sub bh,al
	mov al,0b0h
	jnc xmldc2
	neg bh
	mov al,0a0h
xmldc2: shl bh,2
	cmp bh,16
	jc xmldc3
	mov bh,15
xmldc3:	or al,bh
	mov dl,0eh
	jmp xmldw
xmldc1:	cmp bl,20	;key off
	jnz xmldy
	mov es:[di],byte ptr 255
	jmp xmldx
xmldy:	cmp bl,25	;panning slide
	jnz xmldz
	mov bh,al
	and bh,15
	shr al,4
	sub bh,al
	mov al,10h
	jnc xmld01
	neg bh
	mov al,20h
xmld01: shr bh,1
	cmp bh,1
	adc bh,0
	or al,bh
	mov dl,0eh
	jmp xmldw
xmldz:	cmp bl,27	;retrig
	jnz xmld02
	test al,0f0h
	jnz xmldz1
	or al,90h
	mov dl,0eh
	jmp xmldw
xmldz1:	xchg al,ah
	mov dl,30h
	jmp xmldw
xmld02:	cmp bl,29	;tremor
	xchg al,ah
	mov dl,50h
	jz xmldw
	xchg al,ah
	cmp bl,33	;x-commands
	jnz xmldx
	mov bl,al
	add al,al
	and al,0fh
	or al,0e0h
	mov dl,1	;extra fine slide
	shr bl,4
	dec bl
	jz xmldw
	inc dl
	dec bl
	jnz xmldx
xmldw:	call cvmod5
	jmp xmldx
xmldv:	call cvmox1
	cmp byte ptr es:[di+3],8
	jnz xmldx
	shr byte ptr es:[di+4],1
xmldx:	mov eax,es:[di+2]
	mov dword ptr gs:cnvbuf,eax
	mov ax,gs:xmvcmd
	mov dl,ah
	call cnvule
	mov eax,dword ptr gs:cnvbuf
	mov es:[di+2],eax
	add di,6
	pop cx
	inc gs:cvmchn
	dec cx
	jnz xmld4
	pop di
	add di,32*6
	pop cx
	dec cx
	jnz xmld3
	mov ds,gs:datseg
xmldx2:	movzx ax,edipat
	inc ax
	cmp ax,xmpat
	jz xmldd1
	cmp ax,256
	jz xmldx1
	inc edipat
	jmp xmld1

xmldx1: load 9,lodbuf
	mov ax,word ptr lodbuf+7
	mov ds,gs:sbfseg
	load ax,0
	mov ds,gs:datseg
xmldd1: mov ax,xmpate
	or ax,ax
	jz xmld14
	dec xmpate
	mov al,63
	call far ptr f_inspat
	jnc xmldd1

xmld14:	mov smpnum,0                    ;*** instruments ********************
	mov insnum,0
	call far ptr f_clrsm0
	cmp gs:xmins,0
	jz mdll71
xmldd:  mov bp,29
	load bp,lodbuf
	mov si,offset lodbuf+4
	mov cx,22
	call messmp
	mov es,gs:datseg
	mov ax,word ptr lodbuf
	sub ax,bp
	jz xmli1
	add bp,ax
	load ax,lodbuf+29
xmli1:	mov al,lodbuf+27
	or al,al
	jz xmli9
	mov gs:xmsmp,al
	mul lodbuf+29
	add bp,offset lodbuf
	load ax,bp	;bp=smpdat,lodbuf+29=insdat
	call xmli11			;instrument-daten uebertragen

	mov si,bp			;samples laden
	mov cl,gs:xmsmp		;si=dat,cx=anz
xmls1:	push cx
	push si
	call xmls11		;sampledaten uebetragen, sample laden
	pop si
	pop cx
	jc mdlsvz
	add si,word ptr lodbuf+29
	inc smpnum
	cmp smpnum,-1
	jz mdlsv0
	dec cl
	jnz xmls1

	call xmls21		;vols und pans uebertragen

xmli9:	inc insnum
	mov al,gs:xmins
	cmp al,insnum
	jnz xmldd

	jmp farla1

; XMLI11 => lodbuf+4=name, +33=instdatas => instrument-daten uebertragen
xmli11:	mov si,offset lodbuf+4
	mov es,gs:insseg
	mov ah,insnum
	xor al,al
	mov di,ax
	mov cx,22+256*10
	call namcop			;name
	mov ax,word ptr lodbuf+239	;fadeout
	mov es:[di.insfad],ax
	mov al,lodbuf+238		;vib speed
	mov es:[di.insvsp],al
	mov al,lodbuf+237		;vib depth
	add al,al
	mov es:[di.insvde],al
	mov al,lodbuf+236		;vib sweep
	mov es:[di.insvsw],al
	mov al,lodbuf+235		;vib form
	mov es:[di.insvfo],al
	push di				;envelopes
	push es
	push bp
	xor dl,dl		;volenv convert
	call x2env
	mov di,offset envdat
	mov bp,insenv
	call sienv
	push ax
	mov dl,1                ;panenv convert
	call x2env
	mov di,offset enpdat
	mov bp,insenp
	call sienv
	pop bx		;al=enpnum,bl=envnum
	pop bp
	pop es
	pop di
	or al,64
	shl al,1
	shr lodbuf+234,1
	rcr al,1
	or bl,64
	shl bl,1
	shr lodbuf+233,1
	rcr bl,1
	mov es:[di.insenv],bl
	mov es:[di.insenp],al
	test bl,128
	jnz xmli41
	mov es:[di.insfad],0ffffh
xmli41:	mov si,di			;parameter in alle samples kopieren
	add di,insiln
	mov cx,15*insiln/2
xmli4:	mov ax,es:[si]
	add si,2
	stosw
	loop xmli4
	sub di,(16+1)*insiln		;playranges setzen
	mov si,offset lodbuf+33	;si=nottab,di=smpdat
	xor cx,cx
xmli7:  add di,insiln
	mov dl,[si]		;dl=akt.xmsmpnum,cl=notpos,ch=mdlsmppos
xmli5:  inc si
	inc cl
	cmp cl,96
	jnc xmli6
	cmp dl,[si]
	jz xmli5
;cl=end+1,dl=smpnum
xmli6:	mov al,cl
	dec al
	mov es:[di.insrng],al	;rangeend
	mov al,smpnum
	add al,dl
	inc al
	mov es:[di.inssmp],al	;smpnum
	inc ch
	cmp ch,16
	jnc xmli8
	cmp cl,96
	jc xmli7
xmli8:	mov es:[di.insrng],119
	ret

; XMLS11 => smpnum=sample, si=smpdat => sample laden => cf=0 alles klaro
xmls11:	mov es,gs:datseg
	call far ptr f_smpadr
	lodsd
	mov [bx.smplen],eax	;laenge
	lodsd
	mov [bx.smprep],eax	;repeat
	lodsd
	mov [bx.smprln],eax	;replen
	lodsb
	call cnvvol
	mov [bx.smpvol],al	;volume
	lodsb			;finetune
	mov gs:xmfine,al
	lodsb
	xor ah,ah
	test al,16	;8/16 bit
	jz xmlde
	inc ah
xmlde:	test al,2	;un/bi-loop
	jz xmldf
	add ah,2
	jmp xmldg
xmldf:	test al,1	;loop on/off
	jnz xmldg
	mov [bx.smprep],0
	mov [bx.smprln],0
xmldg:	mov [bx.smptyp],ah
	lodsb			;panning
	shr al,1
	mov [bx.smpnam+31],al	;zwischen merken
	lodsb			;relative note number
	call far ptr clcfrq     ;frequency ausrechnen
	mov [bx.smpfre],eax
	inc si
	mov di,bx
	add di,smpnam		;name
	mov cx,22/2
	rep movsw
	mov eax,"    "
	stosd
	stosd
	stosb
	sub di,31
	mov cx,22
	call clrnul
	mov gs:xmlast,0
	mov gs:sgnjmp,offset xmldh
	mov gs:ldajmp,offset lodsm4
	mov gs:xmakt,1
	call ldasm0
	mov gs:xmakt,0
	mov gs:ldajmp,offset lodsm0
	ret

; XMLS21 => insnum=instrument => vols und pans uebertragen
xmls21:	mov ah,insnum
	mov al,32
	mov si,ax
	mov fs,gs:insseg	;fs:si=inst
	mov cx,16
xmls2:	mov al,smpiln
	mul fs:[si.inssmp]
	sub ax,smpiln
	jc xmls22
	add ax,offset smpdat
	mov bx,ax
	mov al,[bx.smpvol]
	mov fs:[si.insvol],al
	mov al," "
	xchg al,[bx.smpnam+31]
	mov fs:[si.inspan],al
	add si,insiln
	loop xmls2
xmls22:	ret

xmld	endp

; X2ENV => dl=vol/pan (0/1) => envelope convertieren
x2env	proc near
	mov di,offset xmhlst
	mov es,gs:datseg		;ziel loeschen
	mov cx,enviln/2
	xor ax,ax
	rep stosw
	sub di,enviln
	push di
	mov si,offset lodbuf+129	;si=xmenvtab, cl=pntanz
	mov cx,word ptr lodbuf+225
	or dl,dl
	jz x2env1
	add si,48
	mov cl,ch
x2env1:	mov ah,[si+2]	;ersten punkt holen
	xor bp,bp
	mov al,1
	call x2env5
	dec cl
x2env2:	add si,4
	mov ax,[si]
	sub ax,[si-4]
	jnc x2en21
	mov ax,1
x2en21:	add bp,ax
	cmp bp,255-12
	jc x2env3
	sub bp,ax
	mov al,1
	cmp bp,255-12
	jnc x2env3
	mov ax,255-12
	sub ax,bp
	mov bp,255-12
x2env3: mov ah,[si+2]
	call x2env5
	dec cl
	jnz x2env2
	pop di
	mov si,offset lodbuf+227
	mov cx,word ptr lodbuf+233
	or dl,dl
	jz x2env4
	add si,3
	mov cl,ch
x2env4:	mov ax,[si+1]
	and al,15
	shl ah,4
	or al,ah
	mov [di.envlop],al
	mov al,[si]
	and cl,6
	shl cl,3
	or al,cl
	mov [di.envsus],al
	ret
x2env5:	cmp ah,64
	jc x2env6
	mov ah,63
x2env6:	stosw
	ret
x2env	endp

; MESSMP => si=quelle, cx=laenge
messmp	proc near
	pusha
	push es
	mov di,msmzgr
        mov bx,di
        cmp bx,offset sngmes+64*76+38
        jnc messm3
        push ds
        pop es
messm1:	lodsb
	or al,al
	jz messm2
	stosb
	loop messm1
messm2: add bx,76
        cmp bx,offset sngmes+64*76
        jnz messm3
	mov bx,offset sngmes+38
messm3: mov msmzgr,bx
	pop es
	popa
	ret
messmp	endp

; SIENV => [xmhlst]=env, di=envdat, bp=insofs
;	=> identische env suchen oder neue einrichten
;	=> al=num (0 wenn nichts frei)
sienv	proc near
	mov si,offset xmhlst
sienv2:	xor al,al
	mov es,gs:datseg
sienv1:	mov cx,enviln/2
	push si
	push di
	repz cmpsw
	pop di
	pop si
	jz sienv0
	add di,enviln
	inc al
	cmp al,64
	jc sienv1
	sub di,enviln*64
	push di
	push si
	call far ptr f_suenv
	pop si
	pop di
	inc al
	jz sienv0
	dec al
	movzx cx,al
	shl cx,5
	add di,cx
	mov es,gs:datseg
	mov cx,enviln/2
	rep movsw
sienv0:	ret
sienv	endp

;==== S P E I C H E R - R O U T I N E N =====================================

; MDLSV => speichert sound als MDL-file in geoeffnete datei => cf=0 alles ok
mdlsv   proc near
	mov dword ptr lodbuf,"LDMD"     ;*** "DMDL" v1.1 kennung ************
	mov lodbuf+4,11h
	save 5,lodbuf

	mov word ptr lodbuf,"NI"        ;*** "IN" infoblock *****************
	mov si,offset sngnam
	xor edi,edi
	mov di,offset lodbuf+6
	mov es,gs:datseg
	movzx cx,snglen
	add cx,91
	rep movsb
	mov si,offset chnnam
	movzx cx,gs:usechn
	add cx,cx
	rep movsd
	sub di,offset lodbuf+6
	mov dword ptr lodbuf+2,edi
	add di,6
	save di,lodbuf

	mov word ptr lodbuf,"EM"	;*** "ME" message *******************
	mov si,offset sngmes+64*76-1
	mov dl,64
mdls00:	mov cl,76
mdls01:	cmp [si],byte ptr 32
	jnz mdls03
	dec si
	dec cl
	jnz mdls01
	dec dl
	jnz mdls00
	jmp mdls02
mdls03:	mov si,offset sngmes
	mov di,offset lodbuf+6
	mov es,gs:datseg
mdls04: mov bp,si
	add si,76-1
	mov cx,76
mdls05: cmp [si],byte ptr 32
	jnz mdls06
	dec si
	loop mdls05
	jmp mdls07
mdls06:	mov si,bp
	rep movsb
mdls07:	mov si,bp
	add si,76
	mov al,13
	stosb
	dec dl
	jnz mdls04
	mov [di],byte ptr 0
	sub di,offset lodbuf+6-1
	movzx eax,di
	mov dword ptr lodbuf+2,eax
	add ax,6
	save ax,lodbuf

mdls02:	mov word ptr lodbuf,"AP"        ;*** "PA" pattern *******************
	movzx eax,patanz
	mov byte ptr lodbuf+6,al
	shl ax,5
	mov gs:mstrmx,ax
	mov fs,gs:sbfseg        ;fs:0=tracks(pos,sum),fs:32768=pats(trknum)
	mov gs:mstrnm,0
	xor ax,ax               ;ax=num aktueller track

mdlsv9: push ax

	call far ptr f_settrk		;track holen
	mov es,gs:patse1
	mov di,32*6
	mov bp,offset lodbuf+8
	mov cx,256*6/2
	xor ax,ax
mdls91:	mov ds:[bp],ax
	add bp,2
	loop mdls91
	mov cx,gs:edipl1
	xor eax,eax
	mov bp,offset lodbuf+8
mdlsva: movzx ebx,word ptr es:[si]
	mov ds:[bp],bx
	add eax,ebx
	movzx ebx,word ptr es:[si+2]
	mov ds:[bp+2],bx
	add eax,ebx
	movzx ebx,word ptr es:[si+4]
	mov ds:[bp+4],bx
	add eax,ebx
	add bp,6
	add si,di
	loop mdlsva

	or eax,eax
	mov cx,ax
	jz mdlsvd       		;leerer track -> track "0" nehmen

	mov cx,gs:mstrnm		;quersummen vergleichen
	xor si,si
	or cx,cx
	jz mdlsvc
mdlsvb: cmp ax,fs:[si+2]
	jz mdlsvf
mdlsvi: add si,4
	loop mdlsvb

mdlsvc: mov fs:[si+2],ax 		;neuer track -> eintragen
	pop ax
	inc gs:mstrnm
	mov fs:[si],ax
	inc ax
	mov cx,gs:mstrnm
	jmp mdlsve
mdlsvd: pop ax
	inc ax

;bp=anz versch.tracks,ax=num naechster track,cx=track fuer pattern
mdlsve: mov di,ax
	add di,di
	mov fs:[di+32768-2+16384],cx
	cmp ax,gs:mstrmx
	jnz mdlsv9
	jmp mdlsvj      ;tabellen fertig

mdlsvf:	push si         ;ax=qsum,si=tracktab an pos,angeblich gleich
	push ax
	push cx
	mov ax,fs:[si]
	call far ptr f_settrk   ;angeblich gleichen track einblenden
	mov es,gs:patse1	;ds:si=track2
	mov di,si		;es:di=track1
	mov si,offset lodbuf+8
	mov cx,gs:edipl1
	mov bx,32*6-6
mdlsvg: cmpsd
	jnz mdlsvh
	cmpsw
	jnz mdlsvh
	add di,bx
	loop mdlsvg
	pop cx
	pop cx          ;gleich => track nehmen
	pop cx
	shr cx,2
	inc cx
	jmp mdlsvd
mdlsvh: pop cx
	pop ax          ;nicht gleich, weiter machen
	pop si
	jmp mdlsvi

mdlsvj:	mov di,32768		;pattern info-block neu einrichten
	mov si,offset patnam
	mov bp,49152
	mov es,gs:sbfseg
	movzx cx,patanz	;ch=num,cl=cnt
mdlsp1: mov bx,bp
	add bx,32*2-2
	mov al,32
mdlsp2:	cmp es:[bx],word ptr 0
	jnz mdlsp3
	sub bx,2
	dec al
	jnz mdlsp2
mdlsp3:	stosb		;chnanz eintragen
	mov dl,al
	movzx bx,ch
	mov al,[bx.patlen]
	stosb		;patlen eintragen
	mov bx,cx
	mov cx,16/2
	rep movsw	;patnam eintragen
	mov cx,bx
	or dl,dl
	jz mdlsp5
	mov bx,bp
mdlsp4:	mov ax,es:[bx]
	stosw		;trknum eintragen
	add bx,2
	dec dl
	jnz mdlsp4
mdlsp5:	add bp,64
	inc ch
	dec cl
	jnz mdlsp1
	add di,1-32768	;di=datlen
	movzx edi,di
	mov dword ptr lodbuf+2,edi
	save 7,lodbuf
	dec di
	mov ds,gs:sbfseg
	save di,32768
	mov ds,gs:datseg

	save 8,lodbuf                   ;*** "TR" tracks ********************
	mov cx,gs:mstrnm        ;cx=track-counter
	mov gs:mstrln,0
	or cx,cx
	jz mdlsvw
	xor bp,bp               ;fs:bp=trcktab
mdlsvk: push cx
	push bp
	mov ax,fs:[bp]
	xor dl,dl
	call far ptr f_settrk
	mov es,gs:patse1	;es:si=track

	mov ch,gs:edipln
	mov al,32*6
	mul ch
	mov bx,ax
mdlsk1:	cmp dword ptr es:[si.bx],0
	jnz mdlsk2
	cmp word ptr es:[si.bx+4],0
	jnz mdlsk2
	sub bx,32*6
	sub ch,1
	jnc mdlsk1		;ch=letzte belegte pos
	jmp mdlsu1

mdlsk2:	mov di,offset lodbuf+2 	;ds:di=ziel, di-(lodbuf+2)=ziellen
	xor cl,cl		;cl=notpos
mdlsvl: mov eax,es:[si]		;eax,bx=6bytes
	mov bx,es:[si+4]
	or eax,eax              ;fall 0 => leerstellen packen
	jnz mdlsvo
	or bx,bx
	jnz mdlsvo
	xor dx,dx
mdlsvm: cmp es:[si],eax
	jnz mdlsvn
	cmp es:[si+4],bx
	jnz mdlsvn
	add si,32*6
	inc dl
	inc cl
	jz mdlsvn
	cmp dl,64
	jz mdlsvn
	cmp cl,ch
	jna mdlsvm
mdlsvn: dec dl
	shl dl,2
	or dl,dh
	mov [di],dl
	inc di
	jmp mdlsvv
mdlsvo: or cl,cl                ;fall 1 => mehrere identische hintereinander
	jz mdlsvt
	cmp eax,es:[si-32*6]
	jnz mdlsvp
	cmp bx,es:[si-32*6+4]
	mov dx,100h
	jz mdlsvm
mdlsvp: mov dl,cl               ;fall 2 => identisch mit anderer position
	mov bp,si
mdlsvq: dec dl
	sub bp,32*6
	cmp dl,64
	jnc mdlsvq
	cmp eax,es:[bp]
	jnz mdlsvr
	cmp bx,es:[bp+4]
	jz mdlsvs
mdlsvr: or dl,dl
	jnz mdlsvq
	jmp mdlsvt
mdlsvs: shl dl,2
	or dl,2
	mov [di],dl
	inc di
	jmp mdlsvu
mdlsvt: xor dx,dx               ;fall 3 => neue note
	mov bp,di
	inc bp
	chknul al
	chknul ah
	shr eax,16
	chknul al
	chknul ah
	chknul bl
	chknul bh
	or dh,3
	mov [di],dh
	mov di,bp
mdlsvu: add si,32*6
	inc cl
mdlsvv: or cl,cl
	jz mdlsu1
	cmp cl,ch
	jna mdlsvl
mdlsu1:	sub di,offset lodbuf
	and edi,65535
	add gs:mstrln,edi
	sub di,2
	mov word ptr lodbuf,di
	add di,2
	pop gs:mstrmx
	pop gs:mstrad
	save di,lodbuf          ;track speichern
	mov bp,gs:mstrmx
	mov cx,gs:mstrad
	add bp,4
	dec cx
	jnz mdlsvk

mdlsvw: mov edx,gs:mstrln       ;trackkopf speichern
	add edx,8
	neg edx
	mov ecx,edx
	shr ecx,16
	mov ax,4202h
	mov bx,gs:fhandl
	int 21h                 ;zum kopf seeken
	jc mdlsv0
	mov word ptr lodbuf,"RT"
	mov eax,gs:mstrln
	add eax,2
	mov dword ptr lodbuf+2,eax
	mov ax,gs:mstrnm
	mov word ptr lodbuf+6,ax
	save 8,lodbuf           ;kopf sichern
	xor cx,cx
	xor dx,dx
	mov ax,4202h
	int 21h                 ;zum ende seeken
	jc mdlsv0

	mov word ptr lodbuf,"II"	;*** "II" instruments ***************
	mov ds,gs:insseg
	xor si,si
	mov es,gs:sbfseg
	xor di,di
	mov dx,256		;dh=num,dl=inscnt
mdlsi5:	call mdlsi1
	add si,256
	inc dh
	jnz mdlsi5
	movzx edi,di
	inc edi
	mov ds,gs:datseg
	mov dword ptr lodbuf+2,edi
	mov lodbuf+6,dl
	save 7,lodbuf
	dec edi
	mov ds,gs:sbfseg
	save di,0
	mov ds,gs:datseg

	mov word ptr lodbuf,"EV"	;*** "VE" volume-envelopes **********
	mov bp,insenv
	mov si,offset envdat
	call mdlse
	save di,lodbuf

	mov word ptr lodbuf,"EP"	;*** "PE" panning-envelopes *********
	mov bp,insenp
	mov si,offset enpdat
	call mdlse
	save di,lodbuf

	mov word ptr lodbuf,"EF"	;*** "FE" panning-envelopes *********
	mov bp,insenf
	mov si,offset enfdat
	call mdlse
	save di,lodbuf

	mov word ptr lodbuf,"SI"        ;*** "IS" sampleinfos ***************
	mov bx,offset (smpdat+smplen)
	xor ecx,ecx
	mov ax,255
mdlsv1: cmp [bx],ecx
	jz mdlsv2
	inc ah
mdlsv2: add bx,smpiln
	dec al
	jnz mdlsv1
	mov byte ptr lodbuf+6,ah
	push ax
	mov al,smpiln+1
	mul ah
	inc ax
	movzx eax,ax
	mov dword ptr lodbuf+2,eax
	pop gs:mstrmx
	save 7,lodbuf
	mov ax,gs:mstrmx
	or ah,ah
	jz mdlsv7
	mov si,offset smpdat
	mov es,gs:sbfseg
	xor di,di
	xor al,al
mdlsv3: inc al
	cmp [si.smplen],0
	jnz mdlsv4
	add si,smpiln
	jmp mdlsv3
mdlsv4: stosb
	mov cx,smpiln
	rep movsb
	dec ah
	jnz mdlsv3
	mov ds,gs:sbfseg
	save di,0
	mov ds,gs:datseg

mdlsv7: mov word ptr lodbuf,"AS"        ;*** "SA" samples *******************
	mov mssaln,0
	mov ax,4201h	;len-pos merken
	mov bx,gs:fhandl
	xor cx,cx
	xor dx,dx
	int 21h
	jc mdlsv0
	add ax,2
	adc dx,0
	mov word ptr mssaps+0,ax
	mov word ptr mssaps+2,dx
	save 6,lodbuf
	xor al,al
mdlsv8: push ax
	call savsmp
	pushf
	add mssaln,ecx
	popf
	pop ax
	jc mdlsv0
	inc al
	cmp al,255
	jnz mdlsv8
mdlsse:	mov ax,4200h	;len-pos anfahren
	mov bx,gs:fhandl
	mov dx,word ptr mssaps+0
	mov cx,word ptr mssaps+2
	int 21h
	jc mdlsv0
	mov dx,offset mssaln	;len speichern
	mov cx,4
	mov ah,40h
	int 21h
	jc mdlsv0
	mov ax,4202h	;zurueck ans ende
	xor cx,cx
	xor dx,dx
	int 21h

mdlsv0: mov al,2
mdlsvz: mov ds,gs:datseg
	push ax
	pushf
        call far ptr f_setpat
	popf
	pop ax
	ret

mdlsi1:	cmp [si.inssmp+32],0
	jz mdlsi4
	push si
	inc dl
	mov es:[di],dh
	inc di
	mov bp,di
	inc di
	mov cx,32/2
	rep movsw
	mov bl,16
mdlsi2:	cmp [si.inssmp],0
	jz mdlsi3
	mov cx,insiln/2
	rep movsw
	dec bl
	jnz mdlsi2
mdlsi3:	neg bl
	add bl,16
	mov es:[bp],bl
	pop si
mdlsi4:	ret

; MDLSE => bp=envofs,si=envdat => vol/pan-envelope speichern
mdlse:	push si
	call far ptr f_suenv
	pop si			;si=envtab
mdlse0:	mov di,offset lodbuf+7	;di=savebuffer
	mov bp,offset flgtab	;bp=flagtabelle
	mov fs,gs:dt1seg
	mov es,gs:datseg
	xor dx,dx		;dl=num,dh=anz
mdlse1:	cmp fs:[bp],byte ptr 1
	jnz mdlse2
	mov [di],dl
	inc dh
	push si
	inc di
	mov cx,enviln/2
	rep movsw
	pop si
mdlse2:	add si,enviln
	inc bp
	inc dl
	cmp dl,64
	jc mdlse1
	mov lodbuf+6,dh
	sub di,offset lodbuf
	movzx eax,di
	sub ax,6
	mov dword ptr lodbuf+2,eax
	ret

mdlsv   endp

; SAVSMP => al=smpnum(ab 0) => speichert smp in fhandl-datei
;	 => ecx=laenge der gespeicherten daten, cf=0 alles ok
savsmp  proc near
	movzx si,al
	mov ah,smpiln
	mul ah
	add ax,offset smpdat
	mov bx,ax
	mov ecx,[bx.smplen]     ;ecx=len
	mov gs:sasaln,ecx
	or ecx,ecx
	jz savsm3
	shl si,2
	mov esi,[si.smpofs]     ;esi=adr
	mov al,[bx.smptyp]
	shr al,2
	and al,03h
	mov bx,gs:sbfseg
	mov es,bx
	mov ds,bx
	jnz savsm4

savsm1: push ecx		;*** methode 0 -> ungepackt *****************
	push esi
	cmp ecx,65536
	jc savsm2
	mov cx,65535
savsm2: push cx
	sub di,di
	call far ptr f_smplod
	pop cx
	sub dx,dx
	mov bx,gs:fhandl
	mov ah,40h
	int 21h
	pop esi
	pop ecx
	jc savsm3
	add esi,65535
	sub ecx,65535
	ja savsm1
	clc
savsm3: mov ds,gs:datseg
	mov ecx,gs:sasaln
	ret

savsm4:	mov gs:csslen,ecx	;*** methode 1 und 2 -> gepackt *************
	mov gs:cssadr,esi
	and al,2
	xor al,3
	mov gs:crn16b,al
	mov ax,4201h
	mov bx,gs:fhandl
	sub cx,cx
	sub dx,dx
	int 21h
	jc savsm3
	mov word ptr gs:csspos+0,ax	;position merken fuer crunch-laenge
	mov word ptr gs:csspos+2,dx
	mov ah,40h
	mov cx,4
	int 21h
	jc savsm3
	mov di,32768            ;ds:di=crunch
	mov ch,32               ;ebp=bits,ch=bitzaehler
	sub ah,ah               ;ah=letztes byte
	mov gs:sasaln,0

scrun1: push ax			;sample-daten holen
	push cx
	push dx
	push di
	push ebp
	mov ecx,gs:csslen
	cmp ecx,1
	jc scru12
	cmp ecx,32768+1
	jc scru11
	mov ecx,32768
scru11: sub gs:csslen,ecx
	mov esi,gs:cssadr
	add gs:cssadr,ecx
	push cx
	sub di,di
	call far ptr f_smplod
	pop bx
	sub si,si
scru12: pop ebp
	pop di
	pop dx
	pop cx
	pop ax
	jc scrunb

scrun7: lodsb
	xor gs:crn16b,1
	jnz scru71
	mov dl,al               ;bei 16 bit low-byte nicht crunchen
	mov cl,8
	jmp scru61
scru71: mov dl,al               ;naechstes byte holen
	sub al,ah
	mov ah,dl
	sub dx,dx
	cmp al,128
	jc scrun2
	xor al,-1
scrun2: cmc
	rcr dh,1
	cmp al,8        ;00-07 => 1xxx
	jnc scrun3
	rcr dh,4
	shl al,5
	or dh,al
	mov cl,5
	jmp scrun6
scrun3: rcr dh,1
	sub al,8
	mov cl,7
scrun4: cmp al,16       ;>07 => 0..01xxxx
	jc scrun5
	rcr dx,1
	sub al,16
	inc cl
	jmp scrun4
scrun5: rcr dx,5
	shl al,4
	or dh,al
;dx=bits von links,cl=anzahl
scrun6: neg cl
	add cl,16
	shr dx,cl       ;dx= xxxx10..0h (ganz nach rechts geschoben)
	neg cl
	add cl,16
scru61: cmp ch,cl
	jc scrun8
	shrd ebp,edx,cl
	sub ch,cl
scrun9: dec bx
	jnz scrun7
	jmp scrun1
scrun8: sub cl,ch
	xchg cl,ch      ;cl=anz, die reinpassen, ch=rest
	shrd ebp,edx,cl
	shr dx,cl
	mov [di],ebp
	add di,4
	jz scruna       ;crnbuf voll, sichern
scrunc: mov cl,ch
	shrd ebp,edx,cl
	mov ch,32
	sub ch,cl
	jmp scrun9

scruna: pusha
	mov ah,40h
	mov bx,gs:fhandl
	mov cx,32768
	mov dx,cx
	add gs:sasaln,32768
	int 21h
	popa
	jc savsm3
	mov di,32768
	jmp scrunc

scrunb: mov cl,ch       ;rest von crn speichern
	shr ebp,cl
	mov [di],ebp
	add di,4
	mov dx,32768
	sub di,dx
	movzx ecx,di
	add gs:sasaln,ecx
	mov ah,40h
	mov bx,gs:fhandl
	int 21h
	jc savsm3
	mov ax,4200h
	mov cx,word ptr gs:csspos+2
	mov dx,word ptr gs:csspos+0
	int 21h
	jc savsm3
	mov ah,40h			;laenge speichern
	mov ds,gs:codseg
	mov dx,offset sasaln
	mov cx,4
	int 21h
	jc savsm3
	mov ax,4202h			;wieder ans ende
	sub cx,cx
	sub dx,dx
	int 21h
	add gs:sasaln,4
	jmp savsm3

savsmp  endp

sviff3:	shr cx,1
sviff4:	lodsw
	xchg al,ah
	mov [si-2],ax
	loop sviff4
	ret

;==== S A M P - / I N S T - L O A D E R =====================================

; ISTLD => laedt ist (digitrakker)
istld	proc near
	mov al,insnum		;inst loeschen
        call far ptr f_inclr

	load 5,lodbuf                   ;*** "DIST" kennung *****************
	cmp dword ptr lodbuf,"TSID"
	stc
	jnz lderr1
	mov al,lodbuf+4
	shr al,4
	cmp al,1
	cmc
	jc lderr1

	mov bp,offset idtist		;bloecke suchen
	mov gs:idanz,idaist
	call blkpos
	jc lderr1

	mov ecx,gs:[idadr+4]		;*** "VE" volume-envelopes **********
	or ecx,ecx
	jz istld1
	sub ecx,4
	call blseek
	jc lderr1
	load 4,lodbuf
	mov ax,word ptr lodbuf
	load ax,lodbuf
	mov bx,offset envdat
	mov bp,insenv
	mov di,offset xmhlst
	call istle

istld1:	mov ecx,gs:[idadr+8]		;*** "PE" panning-envelopes *********
	or ecx,ecx
	jz istld2
	sub ecx,4
	call blseek
	jc lderr1
	load 4,lodbuf
	mov ax,word ptr lodbuf
	load ax,lodbuf
	mov bx,offset enpdat
	mov bp,insenp
	mov di,offset xmhlst+32
	call istle

istld2:	mov ecx,gs:[idadr+0]		;*** "II" instrument-infos **********
	or ecx,ecx
	jz istld3
	sub ecx,4
	call blseek
	jc lderr1
	load 7,lodbuf
	mov cx,word ptr lodbuf
	sub cx,3
	mov ah,insnum
	sub al,al
	mov di,ax
	mov ds,gs:insseg
	load cx,di
	mov ds,gs:datseg

	mov dx,63+256*(128+64)		;env-nummern korrigieren
	mov si,offset xmhlst
	mov al,insenv+32
	call istle0
	mov si,offset xmhlst+32
	mov al,insenp+32
	call istle0

istld3:	mov ecx,gs:[idadr+12]		;*** "IS" sampleinfos ***************
	or ecx,ecx
	jz lderr0
	sub ecx,4
	call blseek
	jc lderr1
	load 4,lodbuf
	mov ax,word ptr lodbuf
	load ax,lodbuf
	mov dl,lodbuf
	mov si,offset lodbuf+1
	mov di,offset xmhlst
	mov bx,offset smpdat-smpiln
	mov es,gs:datseg
	sub ah,ah
istld4: lodsb
	mov [di],al
	inc di
	mov cx,smpiln
istld5: inc ah
	jz lderr1
	add bx,cx
	cmp [bx.smplen],0
	jnz istld5
	mov [di],ah
	inc di
	push di
	mov di,bx
	rep movsb
	pop di
	dec dl
	jnz istld4

	mov cl,lodbuf                   ;smp-nummern korrigieren
	mov si,offset xmhlst
	mov al,inssmp+32
	mov dx,255
	call istle4

	mov ecx,gs:[idadr+16]           ;*** "SA" samples *******************
	or ecx,ecx
	jz lderr0
	call blseek
	jc lderr0
	mov gs:sgnmsk,0
	mov cl,lodbuf
	mov si,offset xmhlst+1
istld7: push cx
	lodsw
	push si
	dec al
	mov smpnum,al
        call far ptr f_getlen
	jz istld8
	mov [bx.smplen],0
        call far ptr f_csmlen
	jc istld8
	call lodsmp
istld8: pop si
	pop cx
	jc lderr1
	dec cl
	jnz istld7
	sub al,al
	ret

; ISTLE => di=uebersetzbuf, bp=envofs, bx=envdat => vol/pan-envs uebernehmen
istle:	mov cl,lodbuf           ;env kopieren
	or cl,cl
	jz lderr0
	mov si,offset lodbuf+1
istle1:	lodsb
	mov [di],al
	inc di
	push bx
	push cx
	push si
	push di
	push bp
	mov di,bx
	call sienv2
	pop bp
	pop di
	pop si
	pop cx
	pop bx
	add si,enviln
	mov [di],al
	inc di
	dec cl
	jnz istle1
	ret

; ISTLE0 => dx=maske, si=uebersetzbuf, al=envofs+32 => env-nummern korrigieren
istle0:	mov cl,16
istle4:	mov ah,insnum		;env-nummern korrigieren
	mov di,ax
	mov es,gs:insseg
istle2: mov al,es:[di]
	and al,dl
	push si
	mov ch,16
istle5:	cmp al,[si]
	jz istle6
	add si,2
	dec ch
	jnz istle5
istle6:	mov al,[si+1]
	pop si
	and es:[di],dh
	or es:[di],al
	add di,insiln
	dec cl
	jnz istle2
	ret
istld	endp

; XILD => laedt xi (fasttracker 2)
xild	proc near
	mov al,insnum		;inst loeschen
        call far ptr f_inclr
	mov cx,12ah
	mov dx,offset lodbuf	;inst-infos laden
	mov ah,3fh
	mov bx,gs:fhandl
	int 21h
	jc lderr1
	mov es,gs:datseg
	mov si,offset lodbuf+15h
	mov di,offset lodbuf+4
	mov cx,22/2
	rep movsw
	mov si,offset lodbuf+42h
	mov di,offset lodbuf+33
	mov cx,230/2
	rep movsw
	mov al,lodbuf+128h	;samp-infos laden
	or al,al
	jz lderr0
	mov gs:xmsmp,al
	mov ah,40
	mul ah
	mov cx,ax
	mov dx,offset lodbuf+12ah
	mov bp,dx
	mov ah,3fh
	int 21h
	jc lderr1
	mov smpnum,0
	call xmli11		;inst-infos uebertragen

	call xild11		;freie sample suchen und merken
	jc lderr2
	mov ah,insnum		;samples zuordnen
	mov al,32+inssmp
	mov di,ax
	mov es,gs:insseg
	sub bh,bh
	mov cl,16
xild3:	mov bl,es:[di]
	sub bl,1
	jc xild4
	mov al,[bx.dirpbf]
	mov es:[di],al
	add di,insiln
	dec cl
	jnz xild3

xild4:	mov cl,gs:xmsmp		;samps laden
	mov si,bp
	mov di,offset dirpbf
xild5:	mov al,[di]
	inc di
	dec al
	mov smpnum,al
	push cx
	push di
	push si
	call xmls11		;infos holen und laden
	pop si
	pop di
	pop cx
	jc lderr1
	add si,40
	dec cl
	jnz xild5
	call xmls21		;vols und pans uebertragen
	sub al,al
	ret

; XILD11 => gs:xmsmp-freie samples suchen und in dirpbf (1-255) merken
xild11:	mov si,offset smpdat+smplen
	mov cl,gs:xmsmp
	mov di,offset dirpbf
	mov smpnum,0
xild1:	cmp [si],dword ptr 0	;freie samps suchen und merken
	jz xild2
xild6:	cmp smpnum,254
	jz lderr2
	add si,smpiln
	inc smpnum
	jmp xild1
xild2:  mov al,smpnum
	inc al
	mov [di],al
	inc di
	dec cl
	jnz xild6
	ret
xild	endp

; NAMCOP => cl=qlen, ch=zlen-qlen, ds:si=q, es:di=z => namen bis 0 kopieren
namcop:	lodsb
	or al,al
	jz namco1
	stosb
	dec cl
	jnz namcop
namco1: add cl,ch
	sub ch,ch
	mov al," "
	rep stosb
	ret

; LDSCS => si=kopf, bp=smpdat => scream-trakker sample laden => cf=1 al=error
ldscs	proc near
	mov es,gs:datseg
	call flecnv		;file
	add si,7
	lodsd
	xchg ds:[bp.smplen],eax ;laenge,repeat,replen
	mov gs:ldslen,eax
	lodsd
	mov ds:[bp.smprep],eax
	mov ebx,eax
	lodsd
	sub eax,ebx
	mov ds:[bp.smprln],eax
	lodsb
	call cnvvol
	mov ds:[bp.smpvol],al   ;volume
	test [si+2],byte ptr 1
	jnz ldscs1
	mov ds:[bp.smprln],0    ;loop on/off
ldscs1: mov eax,[si+3]
	mov ds:[bp.smpfre],eax  ;frequenz
	add si,19
	mov di,bp
	add di,smpnam           ;name
	mov cx,28/4
	rep movsd
	mov [di],dword ptr "    "
	sub di,28
	mov cx,32
	call clrnul
	movzx ecx,word ptr lodbuf+1038 ;smpdatas ansteuern
	shl ecx,4
	mov dx,cx
	shr ecx,16
	mov ax,4200h
	mov bx,gs:fhandl
	int 21h
	mov al,2
	jc ldscs2
	call ldasm0
ldscs2:	ret
ldscs	endp

lderr1:	mov al,1
	stc
lderr0:	ret
lderr2:	mov al,2
	stc
	ret

; S2ICNV => convert smp-datas nach ins, geht von leer-ins aus
s2icnv	proc near
	cmp gs:xmakt,1
	jz s2icn1
	call far ptr f_smpadr
	mov ah,smpnum
	mov insnum,ah
	xor al,al
	mov di,ax
	mov es,gs:insseg
	mov si,bx
	add si,smpnam		;name
	mov cx,32/2
	rep movsw
	inc ah
	mov es:[di.inssmp],ah	;nummer
	mov al,[bx.smpvol]	;volume
	or al,al
	jnz s2icn2
	dec al
	and es:[di.insenv],255-64
s2icn2:	mov es:[di.insvol],al
	mov es:[di.insrng],119	;play-range
s2icn1:	call far ptr f_pinstr
	ret
s2icnv	endp

; CLCFRQ => al=note, cs:xmfine=finetune => eax=frequency
clcfrq	proc near
	mov gs,cs:codseg1
	add al,96
	xor ah,ah
	mov cl,12
	div cl		;octave=al, note=ah
	mov cl,al
	sub cl,8
	mov al,gs:xmfine
	or al,al
	jns xmlds
	add al,128
	sub ah,1
	jnc xmlds
	add ah,12
	dec cl		;cl=oct, al=fine, ah=note
xmlds:	mov gs:xmfine,al
	mov ebp,8363
	or cl,cl
	js xmldq
	shl ebp,cl	;octave setzen (rauf)
	jmp xmldr
xmldq:	neg cl
	shr ebp,cl	;octave setzen (runter)
xmldr:	shl ah,2
	movzx di,ah
	mov eax,gs:[di.notxmf]
	mul ebp
	shrd eax,edx,16
	movzx di,gs:xmfine
	shl di,2
	mov ebp,gs:[di.finxmf]
	mul ebp
	shrd eax,edx,16
	retf
clcfrq	endp

f_setimd: retf

;============================================================================

prgend: ;absolut letzter label!!

CODE1	ends
	end start
