
        .386P

Segment                 DriverHeader PARA Public 'Code' Use16
                        Assume CS:Driver, DS:Nothing

;***** Driver Header *******

include drhead.inc

EndS

Segment                 Driver PARA Public 'Code' Use16
                        Assume CS:Driver, DS:Nothing

ORG 0
StartDriver:

;**************************

include vtable.inc

;********  Required ProcedureTable *************

include reqproc.inc

;************** Local variables ****************

SLAVECHANNELSIZE        EQU     128
MixSpeed                =       44100

IWReinitMsg     DB      "Interwave reinitialised", 0

IWID            DB      "AMD Interwave, Revision "
RevisionLetter  DB      " ", 13
                DB      "Port ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0

IWID2           DB      "AMD Interwave, Revision "
RevisionLetter2 DB      " ", 13
                DB      "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, ", 0FDh, "Dk RAM", 0

IWFreeMsg       DB      "FreeIW  ", 0FDh, "Dk", 0

IWVolumeTable  Label   Word
        DW      00000h, 0A0C0h, 0ABE0h, 0B250h, 0B6F0h, 0BA80h, 0BD70h, 0BFE0h
	DW      0C200h, 0C3F0h, 0C5A0h, 0C720h, 0C880h, 0C9D0h, 0CB00h, 0CC10h
	DW      0CD20h, 0CE10h, 0CF00h, 0CFE0h, 0D0B0h, 0D180h, 0D230h, 0D2F0h
	DW      0D3A0h, 0D440h, 0D4E0h, 0D580h, 0D610h, 0D6A0h, 0D730h, 0D7B0h
	DW      0D830h, 0D8B0h, 0D930h, 0D9A0h, 0DA20h, 0DA90h, 0DAF0h, 0DB60h
	DW      0DBC0h, 0DC30h, 0DC90h, 0DCF0h, 0DD50h, 0DDB0h, 0DE00h, 0DE60h
	DW      0DEB0h, 0DF00h, 0DF60h, 0DFB0h, 0E000h, 0E050h, 0E090h, 0E0E0h
	DW      0E130h, 0E170h, 0E1C0h, 0E200h, 0E240h, 0E290h, 0E2D0h, 0E310h
	DW      0E350h, 0E390h, 0E3D0h, 0E410h, 0E440h, 0E480h, 0E4C0h, 0E4F0h
	DW      0E530h, 0E560h, 0E5A0h, 0E5D0h, 0E610h, 0E640h, 0E670h, 0E6B0h
	DW      0E6E0h, 0E710h, 0E740h, 0E770h, 0E7A0h, 0E7D0h, 0E800h, 0E830h
	DW      0E860h, 0E890h, 0E8C0h, 0E8F0h, 0E920h, 0E940h, 0E970h, 0E9A0h
	DW      0E9D0h, 0E9F0h, 0EA20h, 0EA40h, 0EA70h, 0EAA0h, 0EAC0h, 0EAF0h
	DW      0EB10h, 0EB40h, 0EB60h, 0EB80h, 0EBB0h, 0EBD0h, 0EBF0h, 0EC20h
	DW      0EC40h, 0EC60h, 0EC90h, 0ECB0h, 0ECD0h, 0ECF0h, 0ED10h, 0ED40h
	DW      0ED60h, 0ED80h, 0EDA0h, 0EDC0h, 0EDE0h, 0EE00h, 0EE20h, 0EE40h
        DW      0EE60h

OffsetTable             Label   Word
        DW      0FFF0h, 03000h, 02800h, 02350h, 02000h, 01D60h, 01B50h, 01980h
        DW      01800h, 016A0h, 01560h, 01450h, 01350h, 01260h, 01180h, 010B0h
        DW      01000h, 00F40h, 00EA0h, 00E00h, 00D60h, 00CD0h, 00C50h, 00BC0h
        DW      00B50h, 00AD0h, 00A60h, 009F0h, 00980h, 00920h, 008B0h, 00850h
        DW      00800h, 007A0h, 00740h, 006F0h, 006A0h, 00650h, 00600h, 005B0h
        DW      00560h, 00520h, 004D0h, 00490h, 00450h, 00410h, 003C0h, 00390h
        DW      00350h, 00310h, 002D0h, 00290h, 00260h, 00220h, 001F0h, 001B0h
        DW      00180h, 00150h, 00120h, 000F0h, 000B0h, 00080h, 00050h, 00020h
        DW      00000h


IWMemory                DW      0               ; kb of memory on IW
IWRegisterSelect        DW      0
IWVoiceSelect           DW      0
IWUpdateTimer           DW      0
IWUpdateCount           DW      0
IWMemoryFree            DD      0
IWOutputPort            DW      0
IWUpdateFlag            DB      0
IWMemorySegmented       DB      0

IWLMCFI                 DW      0
IWBankTable             DB      0, 0, 0, 0

IWBank1                 DD      0
IWBank2                 DD      0
IWBank3                 DD      0
IWBank4                 DD      0

OldIRQHandler           DD      0

Convert16To8Bit         DB      0
                        DB      0
Compress                DB      0
                        DB      0
Stereo                  DB      0

NewIWLMCFI              DW      0

IWDataTable             DD      100 Dup (0FFFFFFFFh)
Revision                DB      0

BankConfigs             Label   ; 12 configs..
;        DB      64, 64, 64, 64          ; 12
;        DB      64, 64, 0, 0            ; 11
        DB      64, 0, 0, 0             ; 10
        DB      16, 16, 16, 16          ; 9
        DB      16, 16, 0, 0            ; 8
        DB      16, 0, 0, 0             ; 7
        DB      4, 4, 16, 16            ; 6
        DB      4, 4, 16, 0             ; 5
        DB      4, 16, 16, 16           ; 4
        DB      4, 16, 0, 0             ; 3
        DB      4, 4, 4, 4              ; 2
        DB      4, 4, 0, 0             ; 1
        DB      4, 0, 0, 0              ; 0


IRQData                 Label   Word
        DW      20h,  1111111111111110b ; IRQ 0
        DW      24h,  1111111111111101b ; IRQ 1
        DW      28h,  1111110111111011b ; IRQ 2
        DW      2Ch,  1111111111110111b ; IRQ 3
        DW      30h,  1111111111101111b ; IRQ 4
        DW      34h,  1111111111011111b ; IRQ 5
        DW      38h,  1111111110111111b ; IRQ 6
        DW      3Ch,  1111111101111111b ; IRQ 7
        DW      1C0h, 1111111011111011b ; IRQ 8
        DW      1C4h, 1111110111111011b ; IRQ 9
        DW      1C8h, 1111101111111011b ; IRQ 10
        DW      1CCh, 1111011111111011b ; IRQ 11
        DW      1D0h, 1110111111111011b ; IRQ 12
        DW      1D4h, 1101111111111011b ; IRQ 13
        DW      1D8h, 1011111111111011b ; IRQ 14
        DW      1DCh, 0111111111111011b ; IRQ 15

IMR     DW      0

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

IWScreenList           Label
                        DW      6
                        DW      Near Ptr IdleFunctionList
                        DW      Near Ptr GlobalKeyLink

                        DW      Near Ptr FullScreenBox  ; 0
                        DW      Near Ptr ScreenHeader
                        DW      Near Ptr FillHeader
                        DW      Near Ptr GravisHeaderLine

                        DW      SampleText              ; 4

                        DW      ConvertSampleText
                        DW      ConvertDisabledButton   ; 6
                        DW      ConvertEnabledButton

                        DW      SampleSizeText          ; 8
                        DW      SampleSize0Button       ; 9
                        DW      SampleSize1Button
                        DW      SampleSize2Button

                        DW      DriverText

                        DW      0

GravisHeaderLine        DW      10
                        DB      "Interwave Driver", 0

DriverText              DW      1
                        DB      38, 48
                        DB      21h
                        DB      "Interwave Driver 1.1 for Impulse Tracker", 0

SampleText              DW      1
                        DB      3, 13
                        DB      20h
                        DB      "Sample resizing options", 0

ConvertSampleText       DW      1
                        DB      5, 15
                        DB      20h
                        DB      "Reduce 16 bit samples to 8 bit", 0

ConvertDisabledButton   DW      2
                        DW      0FFFFh, 7, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetConvert
DriverSegment1          DW      0
                        DW      0
                        DW      Offset SetConvert
DriverSegment2          DW      0
                        DB      7, 17, 20, 19, 8
                        DB      0
                        DB      "  Disabled", 0

ConvertEnabledButton    DW      2
                        DW      6, 9, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetConvert
DriverSegment3          DW      0
                        DW      1
                        DW      Offset SetConvert
DriverSegment4          DW      0
                        DB      7, 20, 20, 22, 8
                        DB      0
                        DB      "  Enabled", 0

SampleSizeText          DW      1
                        DB      5, 24
                        DB      20h
                        DB      "Sample size", 0

SampleSize0Button       DW      2
                        DW      7, 10, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment5          DW      0
                        DW      0
                        DW      Offset SetCompress
DriverSegment6          DW      0
                        DB      7, 26, 20, 28, 8
                        DB      0
                        DB      "  Original", 0

SampleSize1Button       DW      2
                        DW      9, 11, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment7          DW      0
                        DW      1
                        DW      Offset SetCompress
DriverSegment8          DW      0
                        DB      7, 29, 20, 31, 8
                        DB      0
                        DB      "  Half", 0

SampleSize2Button       DW      2
                        DW      10, 0FFFFh, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment9          DW      0
                        DW      2
                        DW      Offset SetCompress
DriverSegment10         DW      0
                        DB      7, 32, 20, 34, 8
                        DB      0
                        DB      "  Quarter", 0


GlobalKeyLink           DB      7
GlobalKeyLink2          DD      0

IdleFunctionList        DD      0
                        DD      0

FillHeader              DW      8
FillHeader2             DD      0

FullScreenBox           DW      0
                        DB      0, 0, 79, 49
                        DB      4

ScreenHeader            DW      8
ScreenHeader2           DD      0


RelocationTable         Label
        DW      Offset DriverSegment1
        DW      Offset DriverSegment2
        DW      Offset DriverSegment3
        DW      Offset DriverSegment4
        DW      Offset DriverSegment5
        DW      Offset DriverSegment6
        DW      Offset DriverSegment7
        DW      Offset DriverSegment8
        DW      Offset DriverSegment9
        DW      Offset DriverSegment10
        DW      0FFFFh

;*********** Local functions *******************
;
; TestIW - Checks for the presence of a IW by detecting amount of memory.
; LoadIWSample - Loads a byte to IW memory, AL = value
; LoadIWSamples - Loads ECX bytes from DS:SI to IW memory
;
;***********************************************

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

Proc            DetectMemory

                Push    DS
                        Assume DS:Driver

                Push    CS
                Pop     DS

                Mov     IWMemory, 0

                Mov     DX, IWRegisterSelect
                Mov     AL, 52h
                Out     DX, AL
                Inc     DX
                In      AX, DX
                Mov     IWLMCFI, AX
                And     AX, 0FFF0h
                Or      AX, 0Ch                 ; Allow full 16MB addressing

                Mov     NewIWLMCFI, AX

                Out     DX, AX

                Mov     CX, 256
                Xor     EDI, EDI

DetectMemory1:                          ; DX = BasePort+103h
                Call    IWSetPosition

                Xor     AL, AL
                Call    LoadIWSample    ; Write a 0

                Add     EDI, 10000h
                Loop    DetectMemory1

                Mov     EBX, 3          ; 4 banks, 3, 2, 1 and 0

DetectMemory2:
                Mov     EDI, EBX
                ShL     EDI, 22         ; DI = Bank * 4MB
                Call    IWSetPosition

                Mov     AL, 0AAh
                Mov     DX, IWOutputPort
                Out     DX, AL
                Mov     AL, 055h
                Out     DX, AL
                Call    IWSetPosition

                Mov     DX, IWOutputPort

                In      AL, DX          ; Bank doesn't exist?
                Cmp     AL, 0AAh
                JNE     DetectMemory3

                In      AL, DX
                Cmp     AL, 055h
                JNE     DetectMemory3

                Mov     CX, 64          ; Max of 4MB in 1 bank...

DetectMemoryInnerLoop1:
                Inc     [IWBankTable+BX]
                Inc     IWMemory

                Add     EDI, 10000h
                Call    IWSetPosition

                Mov     DX, IWOutputPort
                In      AL, DX
                Cmp     AL, 0AAh
                JE      DetectMemory3

                Loop    DetectMemoryInnerLoop1

DetectMemory3:
                Dec     BX
                JNS     DetectMemory2

                                ; OK.. have checked each bank.. now to init.
                Mov     BL, 10
                Mov     SI, Offset BankConfigs
                Mov     EAX, DWord Ptr IWBankTable

DetectMemory4:
                Cmp     EAX, [SI]
                JE      DetectMemory5

                Add     SI, 4
                Dec     BL
                JNS     DetectMemory4

                Mov     IWMemorySegmented, 1
                Jmp     DetectMemory6

DetectMemory5:                  ; Set LMCI
                Mov     DX, IWRegisterSelect
                Mov     AL, 52h
                Out     DX, AL
                Mov     AX, IWLMCFI

                And     AX, 0FFF0h
                Or      AL, BL

                Mov     NewIWLMCFI, AX

                Inc     DX
                Out     DX, AX

DetectMemory6:
                ShL     IWMemory, 6
                JZ      DetectMemory7

                Pop     DS
                Ret

DetectMemory7:
                Pop     DS
                Pop     AX              ; Add SP, 2

                StC
                RetF

EndP            DetectMemory
                Assume DS:Nothing

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

Proc            ResetIW                        ; AX = baseport.

                Push    AX
                Push    CX
                Push    DX

                Mov     DX, AX
                Add     DX, 103h        ; DX = IGIDXR

                Comment ~

                Mov     AL, 4Ch
                Out     DX, AL
                Add     DL, 2
                Xor     AL, AL
                Out     DX, AL

                Push    DX
                Mov     DX, 300h
                Mov     CX, 20
ResetIW4:
                In      AL, DX
                Loop    ResetIW4
                Pop     DX

                Mov     AL, 1
                Out     DX, AL

                Push    DX
                Mov     DX, 300h
                Mov     CX, 20
ResetIW3:
                In      AL, DX
                Loop    ResetIW3
                Pop     DX

                Sub     DL, 2

                ~

                Mov     AL, 19h         ; Write SGMI
                Out     DX, AL

                Add     DL, 2

                Mov     AL, 1
                Out     DX, AL          ; Enhanced mode enabled.
                Sub     DL, 2

                Mov     AL, 99h         ; Read SGMI
                Out     DX, AL
                Add     DL, 2
                In      AL, DX
                Sub     DL, 2

                Cmp     AL, 1
                JNE     ResetIW1

                Mov     AL, 53h         ; LMCI
                Out     DX, AL

                Add     DL, 2
                Mov     AL, 1
                Out     DX, AL          ; Auto increment, DRAM, 8-bit, NoInvert
                Sub     DL, 2

                ClC
                Jmp     ResetIW2

ResetIW1:
                StC

ResetIW2:
                Pop     DX
                Pop     CX
                Pop     AX

                Ret

EndP            ResetIW

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

Proc            TestIW


                Call    ResetIW
                JC      TestIW3

                Push    AX

                Mov     IWMemory, 0

                Mov     DX, AX
                Add     DX, 103h                ; DX = Select Register

                Mov     CX, 256                 ; Max amount is 16MB of memory
                Xor     BX, BX                  ; BX = no of 64k chunks.

TestIW1:
                ClI

                Mov     AL, 44h                 ; IW DRAM High, 8 bit
                Out     DX, AL

                Add     DL, 2
                Mov     AX, BX                  ; BX = IW DRAM High
                Out     DX, AL
                Sub     DL, 2                   ; DX = Select Register

                Mov     AL, 43h                 ; IW DRAM Low, 16 bit
                Out     DX, AL

                Inc     DX                      ; DX = Baseport+104h
                Xor     AX, AX
                Out     DX, AX                  ; Address 0

                StI

                Add     DL, 3                   ; DX = Baseport+107h (DRAM I/O)

                Mov     AL, 55h
                Out     DX, AL                  ; Write value 55h
                Mov     AL, 0AAh
                Out     DX, AL                  ; Write value 0AAh
                Mov     AL, CL
                Out     DX, AL                  ; Write value

                Sub     DL, 3                   ; DX = Baseport+104h
                Xor     AX, AX
                Out     DX, AX                  ; Address 0

                Add     DL, 3                   ; DX = Baseport+107h
                In      AL, DX                  ; Read value..
                Cmp     AL, 55h
                JNE     TestIW2

                In      AL, DX                  ; Read value..
                Cmp     AL, 0AAh
                JNE     TestIW2

                In      AL, DX                  ; Read value..
                Cmp     AL, CL
                JNE     TestIW2

                Inc     BX
                Sub     DL, 4                   ; DX = Baseport+103h
                Loop    TestIW1

TestIW2:
                Pop     AX

                And     BX, BX
                JZ      TestIW3

                ShL     BX, 6
                Mov     IWMemory, BX
                ClC
                Ret

TestIW3:
                StC
                Ret

EndP            TestIW

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

Proc            IWSetPosition           ; EDI = position

                ClI
                Mov     DX, CS:IWRegisterSelect
                Mov     AL, 44h
                Out     DX, AL

                Add     DL, 2
                SHLD    EAX, EDI, 16
;                Mov     EAX, EDI
;                ShR     EAX, 16
                Out     DX, AL
                Sub     DL, 2                   ; Select register again.

                Mov     AL, 43h                 ; Address Low, 16 bit
                Out     DX, AL
                Inc     DX                      ; DX = 3x4h

                Mov     AX, DI                  ; Memory location high
                Out     DX, AX                  ; Memory location done.

                StI
                Ret

EndP            IWSetPosition

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

Proc            LoadIWSample           ; AL = value

                Mov     DX, CS:IWOutputPort
                Out     DX, AL

                Ret

EndP            LoadIWSample

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

Proc            LoadIWSamples          ; Given DS:SI, ECX = count
                                       ; EBP = step value.

                Mov     DX, CS:IWOutputPort

LoadIWSamples2:
                Mov     AL, [SI]
                Add     SI, BP
                JC      LoadIWSamples4

LoadIWSamples3:
                Out     DX, AL

                LoopD   LoadIWSamples2
                Ret

LoadIWSamples4:
                Add     ESI, 10000h
                Int     3
                Jmp     LoadIWSamples3

EndP            LoadIWSamples

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

Proc            Load16IWSamples        ; Given DS:SI, ECX = count
                                       ; EBP = step value.

                Add     BP, BP
                Dec     BP
                Mov     BX, 1
                Xor     BP, BX
                Xor     BX, BP

                Mov     DX, CS:IWOutputPort

Load16IWSamples1:
                Xor     BX, BP
                Mov     AL, [SI]
                Add     SI, BX
                JC      Load16IWSamples4

Load16IWSamples3:
                Out     DX, AL

                Dec     ECX
                JNZ     Load16IWSamples1
                Ret

Load16IWSamples4:
                Add     ESI, 10000h
                Int     3
                Jmp     Load16IWSamples3

EndP            Load16IWSamples

;*********** Public functions ******************

; ÄÄ DetectCard ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Returns carry set if error, else carry clear. Has to setup internal vars
; (eg. appropriate IRQ/DMA whatever).
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            DetectIW Far

                Cmp     BasePort, 0FFFFh
                JE      DetectIW1

                Mov     AX, BasePort
                Call    TestIW
                JNC     DetectIW3

                Ret

DetectIW1:
                Mov     AX, 210h

DetectIW2:
                Call    TestIW
                JNC     DetectIW3

                Add     AL, 10h
                Cmp     AL, 60h
                JBE     DetectIW2

                StC
                Ret

DetectIW3:
                Mov     BasePort, AX
                Add     AX, 102h
                Mov     IWVoiceSelect, AX
                Inc     AX
                Mov     IWRegisterSelect, AX
                Add     AL, 4
                Mov     IWOutputPort, AX

                Call    DetectMemory

                Mov     EAX, 'Jeff'

                ClC
                Ret

EndP            DetectIW

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

Proc            IWIRQOnlyHandler

                PushAD
                Push    DS
                Push    ES

                Mov     AL, 20h

                Cmp     CS:IRQ, 8
                JB      IWIRQOnlyHandler1

                Out     0A0h, AL

IWIRQOnlyHandler1:
                Out     20h, AL

                Mov     DX, CS:BasePort
                Add     DL, 6
                In      AL, DX
                And     AL, 8
                JZ      IWIRQOnlyHandler2

                Mov     DX, CS:IWRegisterSelect
                Mov     AL, 45h
                Out     DX, AL
                Mov     AL, 0
                Add     DL, 2
                Out     DX, AL
                Mov     AL, 8
                Out     DX, AL
                Sub     DL, 2
                
                ClD

                Call    SaveEMSPageFrame
                Call    Update
                Call    SetIWRegisters
                Call    RestoreEMSPageFrame

IWIRQOnlyHandler2:
                Pop     ES
                Pop     DS
                PopAD

                IRet

EndP            IWIRQOnlyHandler

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

Proc            IWIRQHandler                   ; IRQ Handler has to
                                                ; 1) Update IW registers
                                                ; 2) Update song position
                Push    AX
                Push    DS

                Mov     AX, IWUpdateTimer
                Add     IWUpdateCount, AX
                JC      IWIRQHandler1

                Mov     AL, 20h
                Out     20h, AL
                Jmp     IWIRQHandler2

IWIRQHandler1:
                PushF
                Call    [OldIRQHandler]

IWIRQHandler2:
                Xor     IWUpdateFlag, 1
                JZ      IWIRQHandlerEnd

                PushAD
                Push    ES

                ClD

                Call    SaveEMSPageFrame
                Call    Update          ; Returns DS:SI, CX
                Call    SetIWRegisters
                Call    RestoreEMSPageFrame

                Pop     ES
                PopAD

IWIRQHandlerEnd:
                Pop     DS
                Pop     AX
                IRet

EndP            IWIRQHandler

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

Proc            SetIWVolume            ; BX = new volume

                                        ; To do:
                                        ;  1) Set ramp start
                                        ;  2) Set ramp end
                                        ;  3) Set current volume
                                        ;  4) Start ramp
                                        ;  5) Save new volume.

                Push    BX
                Push    CX

                Mov     AL, 0Dh
                Out     DX, AL

                Mov     AL, 3           ; Stop Ramp!
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Add     BX, BX
                Mov     CX, [CS:IWVolumeTable+BX] ; CX = new volume
                Mov     BX, [SI+2]
                Add     BX, BX
                Mov     BX, [CS:IWVolumeTable+BX] ; BX = old volume

                Cmp     BX, CX
                JNE     SetIWVolume2

                Mov     AL, 89h
                Out     DX, AL
                Inc     DX
                In      AX, DX
                Dec     DX

                Mov     BX, AX          ; BX = old volume

SetIWVolume2:

                Push    BX                      ; Old volume on stack

                Xor     AH, AH          ; Ramp up
                Cmp     CX, BX
                JE      SetIWVolume4
                JA      SetIWVolume1

                XChg    BX, CX
                Mov     AH, 40h         ; Ramp down

SetIWVolume1:
                Mov     AL, 6           ; Ramp rate
                Out     DX, AL

                Mov     AL, 32          ; Ramp rate
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 7           ; Ramp start
                Out     DX, AL

                Mov     AL, BH
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 8           ; Ramp end
                Out     DX, AL

                Mov     AL, CH
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 9
                Out     DX, AL

                Pop     BX              ; BX = old volume
                XChg    BX, AX

                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 0Dh         ; Ramp control
                Out     DX, AL

                Mov     AL, BH
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

SetIWVolume5:
                Pop     CX
                Pop     BX

                Mov     [SI+2], BX

                Ret

SetIWVolume4:
;                Mov     AL, 0Dh         ; Volume Ramp.
;                Out     DX, AL
;
;                Mov     AL, 3
;                Add     DL, 2
;                Out     DX, AL
;                Sub     DL, 2

                Mov     AL, 9
                Out     DX, AL

                Pop     AX              ; AX = old volume

                Inc     DX
                Out     DX, AX
                Dec     DX

                Jmp     SetIWVolume5

EndP            SetIWVolume

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

Proc            IWGetAddress           ; Given EAX

                Push    CX

                Mov     CL, CS:Compress
                ShR     EAX, CL

                Pop     CX
                Add     EAX, [CS:IWDataTable+BX]
                ShL     EAX, 9
                And     EAX, 7FFFFFFFh

                Ret

EndP            IWGetAddress

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

Proc            SetIWRegisters         ; Given DS:SI, CX

                Mov     ES, CS:SongDataArea

                Push    CX
                Push    SI

                Xor     AX, AX

GetOffsetLoop:
                Push    AX
                Push    CX

                Mov     DX, IWVoiceSelect
                Out     DX, AL                  ; OK.. now to play with this
                                                ; voice.
                Inc     DL                      ; DX = select rego

                Mov     BX, [SI]
                Test    BH, 2
                JZ      GetOffsetLoop2

                Mov     BX, 200h
                Mov     [SI], BX

GetOffsetLoop2:
                Test    BL, 1                   ; Channel not on!
                JZ      GetOffsetLoop1
                Test    BH, 1
                JZ      GetOffsetLoop3          ; Prev 1.

                Xor     BX, BX
                Call    SetIWVolume

                Jmp     GetOffsetLoop1

GetOffsetLoop3:
                Mov     EAX, [SI+4Ch]
                Mov     [SI+2Ch], EAX

                Mov     AL, 8Ah
                Out     DX, AL

                Inc     DX
                In      AX, DX
                Dec     DX

                And     AH, 7Fh
                ShL     EAX, 16         ; Load high part of EAX

                Mov     AL, 8Bh
                Out     DX, AL
                Inc     DX
                In      AX, DX
                        ; EAX = 000OOOOO OOOOOOOO OOOOOOOF FFFFFFFF
                        ; Need: 00000000 0000OOOO OOOOOOOO OOOOOOOO

                ShR     EAX, 9

                MovZX   EBX, Byte Ptr [SI+36h]
                Mov     EBX, [CS:IWDataTable+EBX*4]
                And     EBX, 03FFFFFh
                Sub     EAX, EBX
                Push    CX

                Mov     CL, CS:Compress
                ShL     EAX, CL

                Pop     CX
                Mov     [SI+4Ch], EAX

GetOffsetLoop1:
                Add     SI, SLAVECHANNELSIZE

                Pop     CX
                Pop     AX

                Inc     AX
                Dec     CX
                JNZ     GetOffsetLoop

                Pop     SI
                Pop     CX

                Xor     AX, AX

SetIWRegisters1:
                Push    AX
                Push    CX

                Mov     DX, IWVoiceSelect
                Out     DX, AL                  ; OK.. now to play with this
                                                ; voice.
                Mov     CX, [SI]                ; CX = flags.
                Inc     DL                      ; DX = select rego

                Test    CH, 1
                JZ      SetIWRegisters21

                Mov     AL, [SI+36]
                Cmp     AL, [SI+4]
                JE      SetIWRegisters21

                Xor     AL, AL
                Out     DX, AL

                Mov     AL, 3
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

SetIWRegisters21:
                Test    CL, 32                  ; Frequency change
                JZ      SetIWRegisters7

                Push    DX

                Mov     EAX, [SI+10h]          ; EAX = freq.

                Push    CX
                Mov     CL, CS:Compress
                ShR     EAX, CL
                Pop     CX

                Xor     EDX, EDX
                Mov     EBX, MixSpeed

                Div     EBX                    ; EAX = I portion.

                Test    EAX, Not 63
                JNZ     SetIWRegisters6

                Push    EAX

                Xor     EAX, EAX
                Div     EBX

                Pop     EBX             ; EBX:EAX = IIII FFFF etc.

                SHRD    EAX, EBX, 6

                        ; Have:      IIIIIIII IIIIIIII FFFFFFFF FFFFFFFF
                        ; Req:       IIIIIIFF FFFFFFF0

                Pop     DX
                Mov     AL, 1
                Out     DX, AL

                ShR     EAX, 16
                AdC     AX, 0
                SBB     AX, 0                   ; Just in case!

                Inc     DX
                Out     DX, AX
                Dec     DX

                Jmp     SetIWRegisters7

SetIWRegisters6:
                Mov     CH, 2                   ; Signify to turn off channel
                Pop     DX

SetIWRegisters7:
                MovZX   BX, Byte Ptr [SI+36h]   ; BX = sample number.
                Cmp     BL, 99
                JA      SetIWRegisters20

                ShL     BX, 2                   ; IWDataTable+BX = position

                Cmp     DWord Ptr [CS:IWDataTable+BX], 0FFFFFFFFh
                JNE     SetIWRegisters10

SetIWRegisters20:
                Mov     CH, 2
                Jmp     SetIWRegisters9

SetIWRegisters10:
                Test    CH, 5                   ; Loop changed?!??!?
                JZ      SetIWRegisters8

                Mov     AL, 3                   ; Starting location low.
                Out     DX, AL

                Mov     EAX, [SI+40h]
                Call    IWGetAddress

                                ; Reqd: .OOOOOOO OOOOOOOO OOOOOOOI III.....

                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 2                   ; Starting location high
                Out     DX, AL

                ShR     EAX, 16
                Inc     DX
                Out     DX, AX
                Dec     DX

                                                ; Ending location...
                Mov     AL, 5                   ; Ending location low
                Out     DX, AL

                Mov     EAX, [SI+44h]
                Call    IWGetAddress

                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 4                   ; Ending location high
                Out     DX, AL

                SHR     EAX, 16
                Inc     DX
                Out     DX, AX
                Dec     DX

SetIWRegisters8:
                Test    CH, 1                   ; Do Current position?
                JZ      SetIWRegisters9

                Xor     AL, AL
                Out     DX, AL

                Mov     AL, 3
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 9
                Out     DX, AL
                Xor     AX, AX
                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 10h
                Out     DX, AL
                Add     DL, 2
                Mov     AL, Byte Ptr [CS:IWDataTable+BX+2]
                ShR     AL, 6
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 0Bh         ; Current location LOW
                Out     DX, AL

                Mov     EAX, [SI+4Ch]
                Mov     [SI+2Ch], EAX

                        ; EAX   = OOOOOOOO OOOOOOOO OOOOOOOO OOOOOOOO
                        ; Req:    xOOOOOOO OOOOOOOO OOOOOOOF FFFFFFFF
                Call    IWGetAddress

                Mov     DI, AX

                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 0Ah         ; Current location HIGH
                Out     DX, AL

                SHR     EAX, 16
                Inc     DX
                Out     DX, AX
                Dec     DX

                Mov     AL, 0Bh
                Out     DX, AL

                Mov     AX, DI
                Inc     DX
                Out     DX, AX
                Dec     DX

SetIWRegisters9:
                Test    CL, 64                  ; New volume??
                JZ      SetIWPan

SetIWRegisters23:
                Xor     BX, BX
                Test    CH, 8
                JNZ     SetIWRegistersMuted

                Mov     BL, Byte Ptr [SI+20h]   ; BL = volume, 0->128

SetIWRegistersMuted:
                Call    SetIWVolume

SetIWPan:
                Test    CH, 128                 ; New pan??
                JZ      SetIWRegisters5

                Xor     BH, BH

                Test    CS:Stereo, 1
                JZ      SetIWRegisters3

                Mov     BL, [SI+37h]
                Cmp     BL, 100
                JNE     SetIWRegisters4

SetIWRegisters3:
                Mov     BL, 32                  ; Surround goes to mono :(

SetIWRegisters4:
                Add     BX, BX                  ; BX = offset into IWTable

                Test    CH, 1
                JZ      IWSetPan1

                Mov     AL, 0Ch         ; Right offset
                Out     DX, AL
                Inc     DX
                Mov     AX, [CS:OffsetTable+BX]
                Out     DX, AX
                Dec     DX

                Neg     BX

                Mov     AL, 13h         ; Left offset final
                Out     DX, AL
                Inc     DX
                Mov     AX, [CS:OffsetTable+128+BX]
                Out     DX, AX
                Dec     DX

                Neg     BX

IWSetPan1:
                Mov     AL, 1Bh         ; Right offset final
                Out     DX, AL
                Inc     DX
                Mov     AX, [CS:OffsetTable+BX]
                Out     DX, AX
                Dec     DX

                Neg     BX

                Mov     AL, 1Ch         ; Left offset final
                Out     DX, AL
                Inc     DX
                Mov     AX, [CS:OffsetTable+128+BX]
                Out     DX, AX
                Dec     DX

SetIWRegisters5:
                                                ; Now for control register.
                                                ; If CH | 2, then turn rego OFF
                                                ; If CH | 5, then turn rego ON
                                                ; If CL | 1, then check channel
                Test    CH, 2
                JNZ     SetIWRegisters11

                Test    CH, 5
                JNZ     SetIWRegisters12

                Test    CL, 1
                JZ      SetIWRegisters13

                Mov     AL, 80h                 ; Read voice control
                Out     DX, AL

                Add     DL, 2
                In      AL, DX
                Sub     DL, 2

                Test    AL, 1
                JZ      SetIWRegisters13

                Xor     BX, BX
                Call    SetIWVolume

                Jmp     SetIWRegisters14

SetIWRegisters11:                               ; Turn off.
                Mov     Byte Ptr [SI+4], 0FFh

                Xor     BX, BX
                Call    SetIWVolume

                Xor     AL, AL
                Out     DX, AL
                Mov     AL, 2
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 15h
                Out     DX, AL

                Add     DL, 2           ; Synthesizer Mode select
                Mov     AL, 34          ; Offset enable, enable voice
                Out     DX, AL
                Sub     DL, 2


SetIWRegisters14:
                Test    CL, 1
                JZ      SetIWRegisters13

                Xor     CX, CX                  ; Turn off channel
                Test    Byte Ptr [SI+3Ah], 80h
                JNZ     SetIWRegisters13

                Mov     BX, [SI+38h]
                And     Byte Ptr [BX], Not 4    ; Signify channel off

                Jmp     SetIWRegisters13

SetIWRegisters12:                              ; Turn on
                Mov     AL, [SI+36]
                Mov     [SI+4], AL

                Mov     AL, 15h
                Out     DX, AL

                Add     DL, 2           ; Synthesizer Mode select
                Mov     AL, 32          ; Offset enable, enable voice
                Out     DX, AL
                Sub     DL, 2

                Xor     AL, AL
                Out     DX, AL

                Mov     AL, [SI+0Ah]

                Cmp     CS:Convert16To8Bit, 0
                JNZ     SetIWRegistersNo16Bit

                Mov     AH, [SI+18h]            ; 16 bit?
                Add     AH, AH
                Or      AL, AH

SetIWRegistersNo16Bit:
                Test    CL, 1
                JNZ     SetIWRegisters15

                Mov     AL, 2
                Xor     CX, CX

SetIWRegisters15:
                Add     DL, 2
                Out     DX, AL

SetIWRegisters13:
                And     CX, 0111100010011111b   ; Turns off:
                                                ; 1) Freq & vol recalc
                                                ; 2) New note/note stop/loop cha

                Mov     [SI], CX

                Add     SI, SLAVECHANNELSIZE

                Pop     CX
                Pop     AX

                Inc     AX
                Dec     CX
                JNZ     SetIWRegisters1

                Ret


EndP            SetIWRegisters

;ÄÄ InitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Sets up any memory required for output
; Initiates output
;
; Parameters: AX = Number of Channels
;
; If sucessful, returns:
;   Carry flag clear
;   DS:SI = pointer to text to display
;      AX = parameter 1 in text
;      BX = parameter 2 in text
;      CX = parameter 3 in text
;      DX = parameter 4 in text
;      DI = parameter 5 in text
;
; If unsucessful, returns:
;   Carry flag set
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            InitSound Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     ECX, IdleUpdateInfoLine
                Mov     EDX, GlobalKeyList
                Mov     IdleFunctionList, ECX
                Mov     GlobalKeyLink2, EDX

                Mov     ECX, FillHeaderFunction
                Mov     EDX, DrawHeaderFunction
                Mov     FillHeader2, ECX
                Mov     ScreenHeader2, EDX

                Mov     SI, Offset RelocationTable

Relocation1:
                LodsW
                Cmp     AX, 0FFFFh
                JE      RelocationEnd

                Mov     BX, AX
                Mov     [BX], CS
                Jmp     Relocation1

RelocationEnd:                          ; OK... disable the IW Line In
                                        ; & Enable Line Out
                                ; SetupMIDI
                Mov     DX, BasePort
                Inc     DH
                Mov     AL, 0FFh
                Out     DX, AL
                Mov     AL, 0FCh
                Out     DX, AL

                                ; Setup the rest of it.
                Mov     DX, BasePort
                Mov     AL, 1
                Out     DX, AL

                Mov     DX, IWRegisterSelect
                Mov     AL, 0Eh
                Out     DX, AL          ; DX = BasePort+103h

                Add     DL, 2           ; DX = BasePort+105h
                Mov     AL, 0CDh
                Out     DX, AL          ; Full mixing rate

                Mov     CX, 32
                Sub     DL, 3

IWResetVoice1:
                Mov     AL, CL
                Dec     AL
                Out     DX, AL

                Inc     DX              ; DX = BasePort + 103h
                Xor     AL, AL          ; Voice control register, 8 bit
                Out     DX, AL

                Add     DL, 2
                Mov     AL, 3
                Out     DX, AL          ; Stop voice
                Sub     DL, 2

                Mov     AL, 0Dh         ; Volume Ramp.
                Out     DX, AL

                Mov     AL, 3
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 6           ; Ramp rate
                Out     DX, AL

                Mov     AL, 32          ; Ramp rate
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 9           ; Volume register, 16 bit
                Out     DX, AL

                Inc     DX
                Xor     AX, AX
                Out     DX, AX          ; No volume
                Dec     DX

                Mov     AL, 15h
                Out     DX, AL

                Add     DL, 2           ; Synthesizer Mode select
                Mov     AL, 32          ; Offset enable, enable voice
                Out     DX, AL

                ClI
                Sub     DL, 3           ; DX = BasePort + 102h = Voice select.

                Loop    IWResetVoice1

                Inc     DL
                Mov     AL, 5Bh
                Out     DX, AL
                Add     DL, 2
                In      AL, DX
                Sub     DL, 2
                Shr     AL, 4           ; AL = revision number

                Add     AL, 'A'
                Mov     Revision, AL
;                Cmp     AL, 'C'
;                JE      InitSound_IW2

;                Mov     OffsetTable, Offset IWOffsetTable2

InitSound_IW2:
                Cmp     CS:IRQ, 0FFFFh
                JE      InitSound_IW1

                Mov     AX, BasePort
                Call    ResetIW

                In      AL, 0A1h
                Mov     AH, AL
                In      AL, 21h
                Mov     IMR, AX

                                ; Set IRQ
                Mov     BX, IRQ
                ShL     BX, 2           ; BX points to offset in IRQData

                Xor     DI, DI
                Mov     ES, DI
                Mov     DI, [BX+IRQData]

                And     AX, [BX+IRQData+2]

                Out     21h, AL
                Mov     AL, AH
                Out     0A1h, AL

                Mov     AX, CS
                ShL     EAX, 16
                Mov     AX, Offset IWIRQOnlyHandler

                XChg    [ES:DI], EAX
                Mov     OldIRQHandler, EAX

                StI

                Mov     DX, BasePort
                Mov     AL, 9
                Out     DX, AL

                Call    GetTempo
                Call    SetTempo
                Call    ResetMemory

                Mov     AL, Revision
                Mov     RevisionLetter2, AL

                Mov     AX, BasePort
                Mov     BX, IRQ
                Mov     CX, IWMemory

                Mov     SI, Offset IWID2

                ClC
                Ret

InitSound_IW1:
                Mov     AL, 4Ch
                Out     DX, AL
                Add     DL, 2
                Mov     AL, 3
                Out     DX, AL

                Mov     AL, 34h         ; Program IRQ 0. LSB&MSB, Rate gen
                Out     43h, AL

                Call    GetTempo
                Call    SetTempo
                Call    ResetMemory

                Mov     DX, BasePort
                Mov     AL, 1
                Out     DX, AL

                Xor     AX, AX
                Mov     ES, AX          ; ES = 0

                Mov     AX, CS
                ShL     EAX, 16
                Mov     AX, Offset IWIRQHandler

                ClI

                XChg    DWord Ptr [ES:20h], EAX         ; Clock tick
                Mov     OldIRQHandler, EAX

                StI

                Mov     AL, Revision
                Mov     RevisionLetter, AL

                Mov     AX, BasePort
                Mov     BX, IWMemory
                Mov     SI, Offset IWID

                ClC
                Ret

EndP            InitSound
                Assume DS:Nothing

;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Stops sound output, releases any memory used by driver
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            ReInitSound Far

                Push    CS
                Pop     DS
                Mov     SI, Offset IWReinitMsg
                Mov     BX, 40
                Call    SetInfoLine

                Mov     BX, CS:IRQ
                Cmp     BX, 0FFFFh
                JE      ReInitSound1

                Mov     AX, CS:IMR
                Out     21h, AL
                Mov     AL, AH
                Out     0A1h, AL

                ShL     BX, 2
                Xor     DI, DI
                Mov     ES, DI
                Mov     DI, [CS:BX+IRQData]
                Mov     EAX, CS:OldIRQHandler

                Mov     [ES:DI], EAX

                Jmp     ReInitSound2

ReInitSound1:
                Mov     AL, 34h
                Out     43h, AL

                Xor     AX, AX
                Out     40h, AL
                Out     40h, AL

                Mov     ES, AX
                Mov     EAX, OldIRQHandler
                Mov     [ES:20h], EAX

ReInitSound2:
                Mov     DX, IWRegisterSelect
                Mov     AL, 52h
                Out     DX, AL
                Inc     DX
                Mov     AX, NewIWLMCFI
                Out     DX, AX

                Jmp     RelocationEnd

EndP            ReInitSound

;ÄÄ UnInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Stops sound output, releases any memory used by driver
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            UnInitSound Far

                Mov     AX, BasePort
                Call    ResetIW

                Mov     DX, BasePort
                Inc     DH
                Mov     AL, 0FFh
                Out     DX, AL          ; Stop MIDI

                Mov     CX, 32
                Mov     DX, CS:IWVoiceSelect

IWResetVoice2:
                Mov     AL, CL
                Dec     AL
                Out     DX, AL

                Inc     DX              ; DX = BasePort + 103h
                Xor     AL, AL          ; Voice control register, 8 bit
                Out     DX, AL

                Add     DL, 2
                Mov     AL, 3
                Out     DX, AL          ; Stop voice
                Sub     DL, 2

                Mov     AL, 0Dh         ; Volume Ramp.
                Out     DX, AL

                Mov     AL, 3
                Add     DL, 2
                Out     DX, AL
                Sub     DL, 2

                Mov     AL, 9           ; Volume register, 16 bit
                Out     DX, AL

                Inc     DX
                Xor     AX, AX
                Out     DX, AX          ; No volume
                Dec     DX

                Mov     AL, 15h
                Out     DX, AL

                Add     DL, 2
                Mov     AL, 2
                Out     DX, AL          ; Deactivate voice

                ClI
                Sub     DL, 3           ; DX = BasePort + 102h = Voice select.

                Loop    IWResetVoice2

;                Inc     DL
;                Mov     AL, 4Ch
;                Out     DX, AL
;                Xor     AL, AL
;                Add     DL, 2
;                Out     DX, AL

                Mov     BX, CS:IRQ
                Cmp     BX, 0FFFFh
                JE      UnInitSound1

                Mov     AX, CS:IMR
                Out     21h, AL
                Mov     AL, AH
                Out     0A1h, AL

                ShL     BX, 2
                Xor     DI, DI
                Mov     ES, DI
                Mov     DI, [CS:BX+IRQData]
                Mov     EAX, CS:OldIRQHandler

                Mov     [ES:DI], EAX

                Jmp     UnInitSound2

UnInitSound1:
                Mov     AL, 34h
                Out     43h, AL

                Xor     AX, AX
                Out     40h, AL
                Out     40h, AL

                Mov     ES, AX
                Mov     EAX, OldIRQHandler
                Mov     [ES:20h], EAX

UnInitSound2:
                Mov     DX, IWRegisterSelect
                Mov     AL, 52h
                Out     DX, AL
                Mov     AX, IWLMCFI
                Inc     DX
                Out     DX, AX

                Ret

EndP            UnInitSound

;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; This procedure is called as often as possible by IT.EXE
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            Poll Far

                ClI

Poll1:
                Call    [CS:UARTBufferEmpty]
                JNC     MIDIEnd

                Mov     DX, [CS:BasePort]
                Inc     DH
                In      AL, DX
                Test    AL, 1
                JZ      MIDIEnd

                Inc     DX
                In      AL, DX
                Cmp     AL, 0F0h
                JAE     MIDIEnd

                Call    [CS:UARTSend]
                Jmp     Poll1

MIDIEnd:
                StI

                Ret

EndP            Poll

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

Proc            UARTOut

                Push    DX
                Push    AX

                Mov     DX, [CS:BasePort]
                Inc     DH

UARTOut1:
                In      AL, DX
                Test    AL, 2
                JZ      UARTOut1

                Pop     AX
                Inc     DX

                Out     DX, AL

                Pop     DX

                Ret

EndP            UARTOut

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

InterpretState  DB      0

Proc            SendUARTOut Far ; Local interpreter activated with 0F0h 0F0h.

                Mov     AH, CS:InterpretState
                Cmp     AH, 2
                JB      SendUARTOut1

; In interpreter.
                JE      SendUARTOut3

; Have InterpretType, now get parameter, then return to normal.

                Mov     CS:InterpretState, 0

SendUARTOut4:
                Ret

SendUARTOut3:
                Jmp     SendUARTOutStateInc

SendUARTOut1:
                Cmp     AL, 0F0h
                JNE     SendUARTOut2

SendUARTOutStateInc:
                Inc     CS:InterpretState
                Ret

SendUARTOut2:
                Test    AH, AH
                JZ      SendUARTOutEnd

                Push    AX
                Mov     AL, 0F0h
                Call    UARTOut
                Pop     AX
                Mov     CS:InterpretState, 0

SendUARTOutEnd:
                Call    UARTOut
                Ret

EndP            SendUARTOut

;ÄÄ SetTempo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: BX = tempo
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            SetTempo Far    ; BX = tempo...

                Push    AX
                Push    BX
                Push    DX

                Cmp     CS:IRQ, 0FFFFh
                JE      SetTempo1

                ShL     BX, 8
                Mov     DX, 1Eh
                Mov     AX, 8480h
                Div     BX
                Neg     AL

                Mov     AH, AL

                Mov     DX, CS:IWRegisterSelect

                Mov     AL, 47h
                Out     DX, AL
                Add     DL, 2
                Mov     AL, AH
                Out     DX, AL          ; Set Timer control register 2
                Sub     DL, 2

                Mov     AL, 45h
                Out     DX, AL
                Add     DL, 2
                Mov     AL, 8
                Out     DX, AL
;                Sub     DL, 2

                Mov     DX, CS:BasePort
                Add     DL, 8
                Mov     AL, 4
                Out     DX, AL

                Inc     DL
                Mov     AL, 2
                Out     DX, AL

                Jmp     SetTempo2

SetTempo1:
                                        ; Frames per second = 2 * (0.4*Tempo)
                Mov     AX, 0C214h
                Mov     DX, 16h         ; Ticks = (1193181/(2*0.4))/Tempo
                Div     BX

                                        ; AX contains counter.
                Mov     IWUpdateTimer, AX

                Out     40h, AL         ; Timer IRQ.
                Mov     AL, AH
                Out     40h, AL

SetTempo2:
                Pop     DX
                Pop     BX
                Pop     AX
                Ret

EndP            SetTempo

;ÄÄ SetMixVolume ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = MixVolume
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            SetMixVolume Far

                Ret

EndP            SetMixVolume

;ÄÄ SetStereo ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AL = Stereo on/off, 0 = off.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            SetStereo Far

                Mov     CS:Stereo, AL
                Ret

EndP            SetStereo

;ÄÄ LoadSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = sample to load
;             DS:SI points to sample header
;             ES:0 points to first sample
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadSample Far

                PushAD
                Push    DS
                Push    ES
                Push    FS

                Mov     FS, CS:SongDataArea
                Mov     BP, AX
                Dec     BP
                Add     BP, BP
                Mov     BP, [FS:64912+BP]

                Xor     CX, CX                  ; From the start of the sample..
                Call    GetSampleLocation       ; Returns DS:ESI, ECX = length
                JC      Music_IWLoadSampleEnd

                Mov     BL, [FS:BP+12h]
                Test    BL, 16
                JZ      Music_IWLoadSample12

                Cmp     ECX, [FS:BP+38h]
                JBE     Music_IWLoadSample12

                Mov     ECX, [FS:BP+38h]
                Test    BL, 32
                JZ      Music_IWLoadSample12

                Cmp     ECX, [FS:BP+44h]
                JAE     Music_IWLoadSample12

                Mov     ECX, [FS:BP+44h]

Music_IWLoadSample12:
                Mov     EBX, ECX
                Mov     CL, CS:Compress
                Mov     EDX, 1
                ShR     EBX, CL
                ShL     EDX, CL                 ; EDX = step value.

                Mov     ECX, EBX

                                                ; Now find location to put it in

                Dec     AX                      ; AX = sample number
                Push    AX                      ; AX = sample number (0 based)

                And     EAX, 0FFh
                Mov     DWord Ptr [CS:IWDataTable+4*EAX], 0FFFFFFFFh

                Add     ECX, 2

                Cmp     IWMemorySegmented, 0
                JNE     Music_IWLoadSegmented1

                Mov     EAX, IWMemoryFree

                Test    Byte Ptr [FS:BP+12h], 2          ; 16 bit??
                JZ      Music_IWLoadSamples13

                Cmp     CS:Convert16To8Bit, 0
                JNZ     Music_IWLoadSamples5

                Sub     EAX, 1
                JC      Music_IWLoadSampleWarning
                And     EAX, Not 1                      ; For alignment
                Add     ECX, ECX
                Jmp     Music_IWLoadSamples13

Music_IWLoadSamples5:
                Inc     ESI
                Add     EDX, EDX                        ; Step value.

Music_IWLoadSamples13:
                Cmp     ECX, EAX
                JBE     Music_IWLoadSample2

                                                ; Warning msg here.
Music_IWLoadSampleWarning:
                Pop     AX
                ClC
                Jmp     Music_IWLoadSampleEnd

Music_IWLoadSample3:
                StC

Music_IWLoadSampleEnd:
                Pop     FS
                Pop     ES
                Pop     DS
                PopAD

                Ret

Music_IWLoadSegmented1:
                Test    Byte Ptr [FS:BP+12h], 2          ; 16 bit??
                JZ      Music_IWLoadSegmented3

                Cmp     CS:Convert16To8Bit, 0
                JNZ     Music_IWLoadSegmented2

                Add     ECX, ECX

                                                ; Check each of 4 banks...
                Xor     BX, BX

Music_Load16BitSegment1:
                Mov     EAX, [IWBank1+BX]
                And     EAX, Not 1                      ; For alignment
                Cmp     ECX, EAX
                JBE     Music_LoadSegment2

Music_Load16BitSegment2:
                Add     BX, 4
                Cmp     BX, 16
                JB      Music_Load16BitSegment1
                Jmp     Music_IWLoadSampleWarning

Music_LoadSegment2:
                Sub     EAX, ECX
                Mov     [IWBank1+BX], EAX
                ShL     EBX, 20
                Add     EBX, EAX
                Jmp     LoadIWSampleChain

Music_IWLoadSegmented2:
                Inc     ESI
                Add     EDX, EDX                        ; Step value.

Music_IWLoadSegmented3:
                Xor     BX, BX

Music_Load8BitSegment1:
                Mov     EAX, [IWBank1+BX]
                Cmp     ECX, EAX
                JBE     Music_LoadSegment2

                Add     BX, 4
                Cmp     BX, 16
                JB      Music_Load8BitSegment1
                Jmp     Music_IWLoadSampleWarning

Music_IWLoadSample2:                           ; EAX = number of bytes free.
                                                ; DS:SI = sample.
                                                ; ECX = number of bytes of memory
                                                ; ES:DI = num bytes free ptr
                                                ; BP = sample number.

                                ; Location = MaxMem - DX:AX
                                ;          = -(DX:AX - IWBanks*4:0)
                MovZX   EBX, CS:IWMemory
                ShL     EBX, 10
                                                ; BX = bytes avail.
                Sub     EBX, EAX
                Sub     EAX, ECX
                Mov     IWMemoryFree, EAX

LoadIWSampleChain:
                Pop     DI                      ; DI = sample number

                ShL     DI, 2

                Cmp     CS:Convert16To8Bit, 0
                JNZ     LoadIWForced8Bit

                Test    Byte Ptr [FS:BP+12h], 2
                JNZ     Music_IWLoad16BitSample

LoadIWForced8Bit:
                Push    EBX
                Inc     EBX
                Mov     [CS:IWDataTable+DI], EBX       ; Store pointer

                Mov     ES, CS:SongDataArea
                Pop     EDI                     ; EDI = location in IW mem

                Sub     ECX, 2
                                                ; EDI = location in IW mem
                                                ; DS:SI = sample data
                                                ; ECX = length.
                                                ; EDX = step value.
                ClI

                Push    BP

                Mov     EBP, EDX

                Call    IWSetPosition

                Mov     AL, [DS:SI+BP]
                Call    LoadIWSample
                Call    LoadIWSamples

                Mov     BH, AL

                Pop     BP

                Mov     AL, [FS:BP+12h]
                Test    AL, 16
                JZ      Music_IWLoadSample10

                Mov     ESI, [FS:BP+34h]
                Test    AL, 64
                JZ      Music_IWLoadSample11

                Mov     ESI, [FS:BP+38h]
                Sub     ESI, 2
                AdC     ESI, 0

                Mov     EAX, Not 0
                Mov     CL, CS:Compress
                ShL     EAX, CL
                And     ESI, EAX

Music_IWLoadSample11:
                Test    Byte Ptr [FS:BP+12h], 2
                JZ      Music_IWLoadSample6

                Add     ESI, ESI
                Inc     SI

Music_IWLoadSample6:
                Int     3

                Mov     BH, [SI]

Music_IWLoadSample10:
                Mov     AL, BH
                Call    LoadIWSample

                StI
                Jmp     Music_IWLoadSample3    ; Return.. no error.

Music_IWLoad16BitSample:
                Push    EBX

                ShR     EBX, 1
                Inc     BX
                Mov     [CS:IWDataTable+DI], EBX

                Mov     ES, CS:SongDataArea
                Pop     EDI                     ; EDI = location in IW mem

                Sub     ECX, 4
                ClI

                Push    BP

                Mov     EBP, EDX

                Call    IWSetPosition

                Mov     AX, [DS:ESI+EBP*2]
                Call    LoadIWSample
                Mov     AL, AH
                Call    LoadIWSample

                Call    Load16IWSamples

                Pop     BP

                Xor     BX, BX

                Mov     AL, [FS:BP+12h]
                Test    AL, 16
                JZ      Music_IWLoad16BitSample11B

                Mov     ESI, [FS:BP+34h]

                Test    AL, 64
                JZ      Music_IWLoad16BitSample11

                Mov     ESI, [FS:BP+38h]
                Sub     ESI, 2
                JNC     Music_IWLoad16BitSample11

                Xor     ESI, ESI

Music_IWLoad16BitSample11:
                Mov     EAX, Not 0
                Mov     CL, CS:Compress
                ShL     EAX, CL
                And     ESI, EAX

                Add     ESI, ESI
                Int     3

                Mov     BX, [SI]

Music_IWLoad16BitSample11B:
                Mov     AX, BX
                Call    LoadIWSample
                Mov     AL, AH
                Call    LoadIWSample

                StI
                Jmp     Music_IWLoadSample3    ; Return.. no error.


EndP            LoadSample

;ÄÄ ReleaseSample ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Parameters: AX = sample to release, 0 based
;             DS:SI points to sample header
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            ReleaseSample Far

                LEA     DI, [EAX*4+Offset IWDataTable]
                                                ; Now to release the last
                                                ; sample from IW memory if
                                                ; able to.

                Mov     EBP, [CS:DI]            ; EBP = sample pointer.
                Cmp     EBP, 0FFFFFFFFh
                JE      ReleaseSample3

ReleaseSample4:
                MovZX   EAX, CS:IWMemory
                SHL     EAX, 10

 ; If (MaxMem-(sample location in bank + sample length + 2)) = memory remaining,
 ; then release memory.

                Mov     ECX, [SI+30h]
                Mov     DL, [SI+12h]
                Test    DL, 16
                JZ      ReleaseSample7

                Cmp     ECX, [SI+38h]
                JBE     ReleaseSample7

                Mov     ECX, [SI+38h]

                Test    DL, 32
                JZ      ReleaseSample7

                Cmp     ECX, [SI+44h]
                JAE     ReleaseSample7

                Mov     ECX, [SI+44h]

ReleaseSample7:
                Push    EBX
                Mov     EBX, ECX
                Mov     CL, CS:Compress
                ShR     EBX, CL
                Mov     ECX, EBX
                Pop     EBX

                Inc     ECX
                Mov     EDI, 1

                Test    DL, 2
                JZ      ReleaseSample8Bit

                Cmp     CS:Convert16To8Bit, 0
                JNZ     ReleaseSample8Bit

                Add     ECX, ECX
                Inc     DI

                                                ; EBP = pointer for 16 bit
                                                ; need to convert back:
                Add     EBP, EBP

ReleaseSample8Bit:
                Cmp     IWMemorySegmented, 0
                JNE     ReleaseSampleSegmented1

                Sub     EAX, EBP
                Sub     EAX, ECX

                Cmp     EAX, IWMemoryFree
                JNE     ReleaseSample3

                Add     ECX, EDI
                Add     IWMemoryFree, ECX

                Ret

ReleaseSampleSegmented1:                ; EBP = sample pointer
                                        ; if EBP-EDI = mem remaining in
                                        ; segment, then add ECX+EDI...
                Xor     AX, AX
                Sub     EBP, EDI
                Add     ECX, EDI
                Mov     EDI, EBP

                And     EBP, 3FFFFFh

                ShR     EDI, 22
                And     DI, 3
                Mov     EAX, [IWBank1+EDI*4]
                Cmp     EAX, EBP
                JNE     ReleaseSample3

                Add     [IWBank1+EDI*4], ECX

ReleaseSample3:
                Ret

EndP            ReleaseSample

;ÄÄ ResetMemory ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;  Frees all on-board memory
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            ResetMemory Far

                Push    EAX
                Push    CX
                Push    ES
                Push    DI

                MovZX   EAX, IWMemory           ; Number of kbytes
                ShL     EAX, 10                 ; Translate to bytes

                Cmp     IWMemorySegmented, 0
                JE      ResetMemory1

                Xor     AH, AH
                Mov     AL, [IWBankTable]
                ShL     EAX, 16
                Mov     IWBank1, EAX

                Xor     AH, AH
                Mov     AL, [IWBankTable+1]
                ShL     EAX, 16
                Mov     IWBank2, EAX

                Xor     AH, AH
                Mov     AL, [IWBankTable+2]
                ShL     EAX, 16
                Mov     IWBank3, EAX

                Xor     AH, AH
                Mov     AL, [IWBankTable+3]
                ShL     EAX, 16
                Mov     IWBank4, EAX

                Jmp     ResetMemory2

ResetMemory1:
                Sub     EAX, 64                 ; Safety bytes.
                Mov     IWMemoryFree, EAX

ResetMemory2:
                Push    CS
                Pop     ES
                Mov     DI, Offset IWDataTable
                Mov     CX, 200
                Mov     AX, 0FFFFh
                Rep     StosW

                Pop     DI
                Pop     ES
                Pop     CX
                Pop     EAX

                Ret

EndP            ResetMemory

;ÄÄ GetStatus ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;  Returns text to show on status line, AX = display parameter
;  Carry set if not to show anything.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            GetStatus Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     EAX, IWMemoryFree
                Cmp     IWMemorySegmented, 0
                JE      GetStatus1

                Mov     EAX, IWBank1
                Add     EAX, IWBank2
                Add     EAX, IWBank3
                Add     EAX, IWBank4

GetStatus1:
                Mov     SI, Offset IWFreeMsg
                ShR     EAX, 10

                ClC

                Ret

EndP            GetStatus
                Assume DS:Nothing

;ÄÄ SoundCardScreen ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;  Function to have driver interactive part of program
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            SoundCardScreen Far

                Mov     AX, 5
                Mov     SI, 1
                Mov     CX, CS
                Mov     DX, Offset IWScreenList

                ClC
                Ret

EndP            SoundCardScreen

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

Proc            SetVariable Far

                Ret

EndP            SetVariable

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

Proc            GetVariable Far

                Ret

EndP            GetVariable

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

Proc            SetConvert Far

                Mov     AX, [SI+22]
                Mov     CS:Convert16To8Bit, AL
                Call    Music_LoadAllSamples

                Mov     AX, 1
                Ret

EndP            SetConvert

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

Proc            GetConvert Far

                Push    CS
                Pop     ES
                Mov     DI, Offset Convert16To8Bit
                Ret

EndP            GetConvert

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

Proc            SetCompress Far

                Mov     AX, [SI+22]
                Mov     CS:Compress, AL
                Call    Music_LoadAllSamples

                Mov     AX, 1
                Ret

EndP            SetCompress

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

Proc            GetCompress Far

                Push    CS
                Pop     ES
                Mov     DI, Offset Compress

                Ret

EndP            GetCompress

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

EndDriver:

;********  Provided Constants Table *************

MaxNumberOfChannels     DW      32      ; Maximum number of channels the
                                        ; driver can handle.
StopAfterPlay           DW      0
DefaultChannels         DW      32

DriverFlags             DW      1       ; MIDI Out suported
                        DW      4 Dup (0)

;********  Provided Procedure Table *************

ProvidedTableStart:
        DW      Offset DetectIW

        DW      Offset InitSound        ; Playing related
        DW      Offset ReinitSound
        DW      Offset UninitSound

        DW      Offset Poll

        DW      Offset SetTempo         ; Sound variable related
        DW      Offset SetMixVolume
        DW      Offset SetStereo

        DW      Offset LoadSample       ; Sample related
        DW      Offset ReleaseSample
        DW      Offset ResetMemory
        DW      Offset GetStatus        ; Returns string to show on status line

        DW      Offset SoundCardScreen  ; Sound card 'screen'

        DW      Offset GetVariable      ; For interface
        DW      Offset SetVariable

        DW      Offset SendUARTOut          ; MIDI output!

ProvidedTableEnd:
        DW      32-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0)

EndS

End

               *********************** Notes *******************

                        UltraSound Output Structure

       0   1   2   3   4   5   6   7   8   9
     ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂ
0000:³(Flags)³LastVol                        ³
     ÃÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÂÄÄÄÂÄÄÄÅÄÄÄÂÄÄÄÅ


