;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Load Instrument module
;
; Instrument in .ITI format has to be placed at DS:64000
; Sample headers have to be placed at DS:0
;
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadITInstrument

                Mov     DX, 64000
                Mov     CX, 554         ; Length of instrument header
                Mov     AH, 3Fh
                Int     21h

                Cmp     Word Ptr [DS:64000+1Ch], 200h
                JAE     LoadITInstrument1

                Mov     SI, DX
                Call    ConvertOldInstrument

LoadITInstrument1:
                Mov     AX, [DS:64000+1Eh]      ; AX = number of samples
                Mov     DX, 80
                Mul     DX                      ; Clears DX, AX = size in bytes
                Mov     CX, AX

;                Xor     DX, DX
;                Mov     CX, DI
                JCXZ    LoadITInstrument2

                Mov     AH, 3Fh
                Int     21h             ; All sample headers are loaded too.
                                        ; Step 2 done.

LoadITInstrument2:
                Ret

EndP            LoadITInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

InstrumentNameOffset    DW      0
XISampleOffset          DD      0

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadXIInstrument        ; Must preserve DS, BX

                Push    DS
                Pop     ES

                Mov     DX, 63000
                Mov     CX, 298         ; Length of instrument header
                Mov     AH, 3Fh
                Int     21h

                Mov     AX, [DS:63000+296]      ; NoS
                Mov     CS:NumInstrumentSamples, AX
                Mov     CS:InstrumentNameOffset, 63000+21
                Mov     CS:XISampleOffset, 298

                                        ; Now to transfer data across
                                        ; to 64000 in ITI format
LoadXIChain:
                Mov     DI, 64000
                Mov     EAX, 'IPMI'     ; Header
                StosD

                Xor     AX, AX
                Mov     CX, 8
                Rep     StosW           ; Filename, NNA, DCA, DCT

                Mov     AX, [DS:63000+272]
                Add     AX, 15
                ShR     AX, 5
                Cmp     AX, 256
                JB      LoadXIInstrumentFdOut

                Mov     AX, 256

LoadXIInstrumentFdOut:
                StosW                           ; Fadeout

                Mov     AX, 60*256
                StosW                           ; PPC and PPS
                Mov     AX, 128+32*256
                StosW                           ; GBV and DfP
                Xor     AX, AX
                StosW
                StosW
                Mov     AX, CS:NumInstrumentSamples
                StosW
                Xor     AX, AX

                Mov     SI, CS:InstrumentNameOffset
                Mov     CX, 22/2
                Rep     MovsW
                Mov     CX, 5
                Rep     StosW                   ; Clear up end of inst name

                ; Translation table
                Mov     CX, 12                  ; First 12 entries empty
                Xor     AX, AX

LoadXIInstrument1:
                StosW
                Inc     AX
                Loop    LoadXIInstrument1

                Mov     SI, 63000+66
                Mov     CX, 96

LoadXIInstrument2:
                Mov     AH, [SI]
                Inc     AH
                StosW

                Inc     AX
                Inc     SI
                Loop    LoadXIInstrument2

                Mov     CX, 12                  ; Last 12 entries empty
                Xor     AH, AH

LoadXIInstrument3:
                StosW
                Inc     AX
                Loop    LoadXIInstrument3

                                                ; Now for volume envelope
                Mov     AL, [DS:63000+266]      ; Flags
                Mov     CL, AL
                Mov     AH, AL
                And     AX, 402h
                ShR     AH, 1
                ShL     AL, 1
                Or      AL, AH
                And     CL, 1
                Or      AL, CL

                Mov     AH, [DS:63000+258]      ; No of vol env nodes
                Cmp     AH, 12
                JB      NumXIVolNodes1

                Mov     AH, 12

NumXIVolNodes1:
                StosW
                Mov     AX, [DS:63000+261]      ; Vol loop start+end
                StosW
                Mov     AL, [DS:63000+260]      ; Vol Sustain point
                Mov     AH, AL
                StosW

                                ; OK. now process volume env points
                Mov     CX, 12

LoadXIInstrument4:
                Mov     AL, [SI+2]
                Cmp     AL, 64
                JB      LoadXICheckVolBound1

                Mov     AL, 64

LoadXICheckVolBound1:
                StosB
                MovsW
                LodsW
                Loop    LoadXIInstrument4

                Mov     CX, 13*3+1
                Xor     AX, AX
                Rep     StosB

                        ; Now for panning envelope

LoadXIInstrument5:
                Mov     AL, [DS:63000+267]      ; Flags
                Mov     CL, AL
                Mov     AH, AL
                And     AX, 402h
                ShR     AH, 1
                ShL     AL, 1
                Or      AL, AH
                And     CL, 1
                Or      AL, CL

                Mov     AH, [DS:63000+259]      ; No of pan env nodes
                Cmp     AH, 12
                JB      NumXIPanNodes1

                Mov     AH, 12

NumXIPanNodes1:
                StosW
                Mov     AX, [DS:63000+264]      ; Pan loop start+end
                StosW
                Mov     AL, [DS:63000+263]      ; Pan Sustain point
                Mov     AH, AL
                StosW

                                ; OK. now process panning env points
                Mov     CX, 12
                Xor     AH, AH

LoadXIInstrument6:
                Mov     AL, [SI+2]
                Cmp     AL, 64
                JB      LoadXICheckPanBound

                Mov     AL, 64

LoadXICheckPanBound:
                Sub     AL, 32
                StosB
                MovsW
                LodsW                   ; Add SI, 2
                Loop    LoadXIInstrument6

                Mov     CX, 13*3+1
                Xor     AX, AX
                Rep     StosB

                ; Now for pitch envelope
                Mov     AX, 2*256       ; 2 node points
                StosW
                Xor     AX, AX
                StosW
                StosW

                        ; First node is 0, 0, second node is 0, 99
                StosW
                StosW
                Mov     AX, 99
                StosW

                Mov     CX, 75-6
                Xor     AX, AX
                Rep     StosB

                Cmp     Byte Ptr [DS:64000+131h], 2
                JAE     LoadXIInstrumentVolEnvelopeCheck1

                Mov     Byte Ptr [DS:64000+131h], 2
                Mov     Word Ptr [DS:64000+136h], 64
                Mov     Word Ptr [DS:64000+138h], 64*256
                Mov     Word Ptr [DS:64000+13Ah], 100

LoadXIInstrumentVolEnvelopeCheck1:

                Cmp     Byte Ptr [DS:64000+183h], 2
                JAE     LoadXIInstrumentPanEnvelopeCheck1

                Mov     Byte Ptr [DS:64000+183h], 2
                Xor     AX, AX
                Mov     [DS:64000+188h], AX
                Mov     [DS:64000+18Ah], AX
                Mov     Word Ptr [DS:64000+18Ch], 100

LoadXIInstrumentPanEnvelopeCheck1:

                                ; OK. instrument done.
                                ; Now have to load samples
                        ; Bytes to load = 40*NoS
                Mov     AX, 40
                Mul     Word Ptr [DS:64000+1Eh]
                Mov     CX, AX

                Mov     DX, 62000
                Mov     AH, 3Fh
                Int     21h

                Mov     EDX, CS:XISampleOffset          ; EDX = offset in file
                Add     DX, CX

                Xor     DI, DI
                Mov     SI, 62000
                Mov     CX, [DS:64000+1Eh]

LoadXISample1:
                Push    CX

                Mov     EAX, 'SPMI'
                StosD
                Xor     AX, AX
                Mov     CX, 6
                Rep     StosW
                Mov     AX, 64*256
                StosW
                                ; Flg
LoadXISample2:
                Mov     AH, [SI+12]     ; Default volume
                Mov     AL, 0
                Cmp     DWord Ptr [SI], 0       ; Length = 0?
                JE      LoadXISample4

                Mov     AL, 1

                Mov     CL, [SI+14]
                Test    CL, 10h
                JZ      LoadXISample3

                Or      AL, 2   ; 16-bit sample

LoadXISample3:
                And     CL, 3
                JZ      LoadXISample4   ; No loop
                                        ; CL = 1 or 2
                Cmp     DWord Ptr [SI+8], 1
                JBE     LoadXISample4

                Or      AL, 10h         ; Loop
                Dec     CX
                ShL     CL, 6
                Or      AL, CL

LoadXISample4:
                StosW

                Push    SI
                                        ; Copy sample name
                Add     SI, 18
                Mov     CX, 22/2
                Rep     MovsW
                Xor     AX, AX
                StosW
                StosW

                Pop     SI
                                        ; Conversion flags, default pan
                Mov     AL, 5
                Mov     AH, [SI+15]     ; Pan
                ShR     AH, 2
                AdC     AH, 80h
                StosW

                Mov     EAX, [SI]
                Call    LoadXISample5
                Mov     EAX, [SI+4]
                Call    LoadXISample5
                Mov     EAX, [SI+4]
                Add     EAX, [SI+8]
                Call    LoadXISample5

                                        ; C5speed..
                Push    ES
                Push    DI

                Call    Music_GetPitchTable     ; Returns ES:DI
                Mov     AL, [SI+16]     ; Relative note number
                Add     AL, 60          ; AL = note multiplier
                And     AX, 0FFh
                ShL     AX, 2
                Add     DI, AX
                Mov     ECX, [ES:DI]

                Mov     AL, [SI+13]     ; Finetune, -128->+127
                SAR     AL, 4           ; Finetune = -8->+7
                And     AX, 0Fh
                Add     AX, AX
                Mov     DI, AX
                MovZX   EAX, [CS:FineTuneTable+DI]

                Pop     DI
                Pop     ES

                Push    EDX

                Mul     ECX
                ShRD    EAX, EDX, 16
                Pop     EDX
                StosD                   ; C5freq

                Xor     AX, AX
                StosW
                StosW
                StosW
                StosW

                Mov     EAX, EDX
                Add     EDX, [SI]
                StosD
                Xor     AX, AX
                StosW
                StosW

                Pop     CX
                Add     SI, 40
                Loop    LoadXISample1

                Ret

LoadXISample5:
                Cmp     EAX, 4177910
                JB      LoadXISample6

                Mov     EAX, 4177910
LoadXISample6:
                Test    Byte Ptr [SI+14], 10h
                JZ      LoadXISample7

                ShR     EAX, 1

LoadXISample7:
                StosD
                RetN

EndP            LoadXIInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadInITInstrument

                Mov     AH, 3Fh
                Mov     CX, 2000
                Mov     DX, 62000
                Int     21h             ; Read header into 62000

                Mov     AX, 4200h
                Mov     CX, Word Ptr [CS:LoadInstrumentOffset+2]
                Mov     DX, Word Ptr [CS:LoadInstrumentOffset]
                Int     21h             ; Goto location

                Mov     AH, 3Fh         ; Load instrument data
                Mov     CX, 554
                Mov     DX, 64000
                Int     21h

                Cmp     Word Ptr [DS:62000+2Ah], 200h
                JAE     LoadInITInstrument1

                Mov     SI, 64000
                Call    ConvertOldInstrument

LoadInITInstrument1:                    ; Convert Note table and load
                                        ; Sample headers.
                Mov     SI, 64000+41h
                Xor     CX, CX

LoadInITInstrument2:
                Mov     DI, [SI]
                And     DI, 0FFh                ; DI = sample number
                JZ      LoadInITInstrument3
                Cmp     DI, [DS:62000+24h]      ; Sample exists?
                JA      LoadInITInstrument3
                Cmp     Byte Ptr [CS:InstrumentTable+DI], 0
                JNE     LoadInITInstrument3

                Inc     CX                      ; CL = sample number
                Mov     [CS:InstrumentTable+DI], CL

                Push    SI
                Push    CX

                Add     DI, [DS:62000+22h]
                ShL     DI, 2
                Add     DI, [DS:62000+20h]
                Add     DI, 62000+0C0h-4        ; Samples are 0 based, not 1

                Mov     AX, 4200h               ; Move to offset of sample
                Mov     CX, [DI+2]
                Mov     DX, [DI]
                Int     21h

                Pop     AX
                Push    AX

                Dec     AX
                Mov     CX, 80
                Mul     CX
                Mov     DX, AX

                Mov     AH, 3Fh
                Int     21h                     ; Load sample header.

                Pop     CX
                Pop     SI

LoadInITInstrument3:
                Add     SI, 2
                Cmp     SI, 64000+41h+120*2
                JB      LoadInITInstrument2

                Mov     [DS:64000+1Eh], CX

                                                ; Process translation table
                Mov     SI, 64000+41h

LoadInITInstrument4:
                Mov     DI, [SI]
                And     DI, 0FFh
                Mov     AL, [CS:InstrumentTable+DI]
                Mov     [SI], AL

                Add     SI, 2
                Cmp     SI, 64000+41h+120*2
                JB      LoadInITInstrument4

                Mov     DI, Offset InstrumentTable
                Xor     AX, AX
                Mov     CX, 50
                Rep     StosW

                Ret

EndP            LoadInITInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadInXMInstrument

                Mov     AX, 4200h
                Mov     CX, Word Ptr [CS:LoadInstrumentOffset+2]
                Mov     DX, Word Ptr [CS:LoadInstrumentOffset]
                Int     21h             ; Goto location

                Mov     AH, 3Fh
                Mov     CX, 4
                Mov     DX, 63000
                Int     21h

                Mov     AH, 3Fh
                Mov     CX, [DS:63000]
                Sub     CX, 4
                Mov     DX, 63033+4
                Int     21h

                Mov     AX, [DS:63033+27]
                Mov     CS:NumInstrumentSamples, AX
                Mov     CS:InstrumentNameOffset, 63033+4

                Mov     AX, 4201h
                Xor     CX, CX
                Xor     DX, DX
                Int     21h                     ; DX:AX = fileoffset

                Mov     Word Ptr [CS:XISampleOffset], AX
                Mov     Word Ptr [CS:XISampleOffset+2], DX

                Push    DS
                Pop     ES

                Jmp     LoadXIChain

EndP            LoadInXMInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            TransferInstrumentName

                Mov     AX, 48
                Mul     CS:NumInstruments
                Inc     CS:NumInstruments

                Mov     DI, AX

                Push    DS

                Push    CS
                Pop     DS

                Mov     AL, CL
                StosB
                Mov     SI, Offset InInstrumentFileName
                Mov     CX, 14
                Rep     MovsB
                Mov     EAX, LoadInstrumentOffset
                Mov     [ES:DI+44-15], EAX

                Pop     DS

                Ret

EndP            TransferInstrumentName

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

; 'InstrumentTable' scratchpad

LoadInstrumentOffset    DD      0
NumInstrumentSamples    DW      0

Proc            LoadITInModuleInstrument

                Mov     AH, 3Fh
                Mov     CX, 2000
                Mov     DX, 63000
                Int     21h

                Xor     BP, BP

                Push    ES

                Push    CS                      ; Clear InstrumentTable
                Pop     ES

                Mov     DI, Offset InstrumentTable
                Mov     CX, 100
                Xor     AL, AL
                Rep     StosB

                Pop     ES

LoadITInModuleInstrument1:
                Cmp     BP, [DS:63000+22h]      ; InsNum
                JB      LoadITInmoduleInstrument2

                Ret

LoadITInModuleInstrument2:
                Mov     SI, BP
                ShL     SI, 2

                Inc     BP

                Add     SI, [DS:63000+20h]
                Add     SI, 63000+0C0h

                Mov     AX, 4200h               ; Move file pointer.
                Mov     CX, [SI+2]
                Mov     DX, [SI]

                Mov     Word Ptr [CS:LoadInstrumentOffset], DX
                Mov     Word Ptr [CS:LoadInstrumentOffset+2], CX

                Int     21h

                Mov     AH, 3Fh
                Mov     CX, 554
                Mov     DX, 62000
                Int     21h

                Mov     SI, 62000+41h

LoadITInModuleInstrument3:
                LodsW
                And     AX, 0FFh
                Mov     DI, AX

                Cmp     AL, 100
                JAE     LoadITInModuleInstrument5

                Mov     [CS:InstrumentTable+DI], 1

LoadITInModuleInstrument5:
                Cmp     SI, 62000+41h+120*2
                JB      LoadITInModuleInstrument3

                                                ; Now to count samples
                                                ; and clear table.
                Mov     DI, 99
                Xor     DX, DX                  ; DX = number of samples.

LoadITInModuleInstrument4:
                Cmp     Byte Ptr [CS:InstrumentTable+DI], 1
                JNE     LoadITInModuleInstrument6

                Inc     DX
                Mov     Byte Ptr [CS:InstrumentTable+DI], 0

LoadITInModuleInstrument6:
                Dec     DI
                JNZ     LoadITInModuleInstrument4

                Test    DX, DX
                JZ      LoadITInModuleInstrument1

                Push    DX

                Mov     CL, 5                   ; In-Module .IT Instrument
                Call    TransferInstrumentName

                Mov     SI, 62000+20h
                Mov     CX, 25
                Rep     MovsB

                Pop     AX
                StosW
                Xor     AX, AX
                StosW

                Jmp     LoadITInModuleInstrument1

EndP            LoadITInModuleInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadXMInModuleInstrument

                Call    LoadXMHeader    ; Reads to first instrument

                Xor     BP, BP

LoadXMInModuleInstrument1:
                Cmp     BP, [DS:64000+72]
                JB      LoadXMInModuleInstrument2

                Ret

LoadXMInModuleInstrument2:
                Inc     BP

                Mov     AX, 4201h
                Xor     CX, CX
                Xor     DX, DX
                Int     21h             ; Get current file location

                Mov     Word Ptr [CS:LoadInstrumentOffset], AX
                Mov     Word Ptr [CS:LoadInstrumentOffset+2], DX

                Mov     AH, 3Fh
                Mov     CX, 4
                Mov     DX, 63000
                Int     21h             ; Read instrument size field

                Mov     AH, 3Fh
                Mov     CX, [DS:63000]
                Sub     CX, 4
                Mov     DX, 63004
                Int     21h

                Mov     AX, [DS:63000+27]       ; Number of samples
                Test    AX, AX
                JZ      LoadXMInModuleInstrument1

                Mov     CX, 40
                Mul     CX
                Mov     CX, AX
                Mov     AH, 3Fh
                Mov     DX, 62000
                Int     21h                     ; OK sample headers read
                                                ; into DS:62000

                Mov     CL, 6                   ; In-Module .XM Instrument
                Call    TransferInstrumentName

                Mov     SI, 63004
                Mov     CX, 22
                Rep     MovsB
                Xor     AX, AX
                StosB
                StosW

                Mov     AX, [DS:63000+27]
                Mov     CX, AX
                StosW
                Xor     AX, AX
                StosW

                Xor     EDX, EDX
                Mov     SI, 62000

LoadXMInModuleInstrument3:
                Add     EDX, [SI]
                Add     SI, 40

                Dec     CX
                JNZ     LoadXMInModuleInstrument3

                SHLD    ECX, EDX, 16
                Mov     AX, 4201h
                Int     21h
                                        ; Advance file pointers..
                Jmp     LoadXMInModuleInstrument1

EndP            LoadXMInModuleInstrument

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
