
        .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

        Comment ~

Index = BasePort + 802h

      15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
    ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
    ³ .............................. ³ Register  ³  Channel Number   ³
    ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ


        ~

OldIRQHandler   DD      0
AWEMemory       DD      0
AWEMemoryUsed   DD      0
AWEUpdateCount  DW      0

AWEUpdateTimer  DW      0

LoadSampleFuncF DW      0
LoadSampleFuncB DW      0

AWEDataTable    DD      5*100 Dup (0)   ; Start, Startloop, Endloop, Size
MIDIPort        DW      0
MIDIBuffer      DB      256 Dup (0)
MIDIBufferHead  DB      0
MIDIBufferTail  DB      0

DMABuffer       DW      0

SB16BasePort    DW      0
MixerPort       DW      0
Step            DW      1
AWEUpdateFlag   DB      0
Compress        DB      0
                DB      0

SBIRQMode       DB      0
BlockLength     DW      100
BlockLength2    DW      100

AWE32Msg        DB      "Sound Blaster AWE 32 detected", 13
                DB      "Address ", 0FDh, "Xh, ", 0FDh, "Dk Memory", 0

AWE32Msg2       DB      "Sound Blaster AWE 32 detected", 13
                DB      "Port ", 0FDh, "Xh, IRQ ", 0FDh, "D, DMA ", 0FDh, "D", 0

AWE32Status     DB      "FreeAWE ", 0FDh, "Dk", 0

AWE32ReinitMsg  DB      "Sound Blaster AWE 32 reinitialised", 0
Stereo          DB      0
Forced          DB      0
DriverName      DB      "ITAWE32.DRV", 0

FrequencyError  DB      "AWE Hardware frequency limit exceeded -> Note terminated", 0

IRQFlag         DB      0FFh

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

        CPF             EQU             0
        PTRX            EQU             20h
        CVCF            EQU             40h
        VTFT            EQU             60h
        PSST            EQU             0C0h
        CSL             EQU             0E0h

        CCCA            EQU             100h
        HWCF4           EQU             129h
        HWCF5           EQU             12Ah
        HWCF6           EQU             12Dh
        SMALR           EQU             134h
        SMARR           EQU             135h
        SMALW           EQU             136h
        SMARW           EQU             137h
        SMLD            EQU             43Ah
        SMRD            EQU             23Ah
        WC              EQU             23Bh
        HWCF1           EQU             43Dh
        HWCF2           EQU             43Eh
        CFG2            EQU             43Eh
        HWCF3           EQU             43Fh
        INIT1           EQU             440h
        INIT2           EQU             240h
        INIT3           EQU             460h
        INIT4           EQU             260h
        ENVVOL          EQU             480h
        DCYSUSV         EQU             4A0h
        ENVVAL          EQU             4C0h
        DCYSUS          EQU             4E0h
        SUSDCY          EQU             4E0h
        ATKHLDV         EQU             280h
        LFO1VAL         EQU             2A0h
        ATKHLD          EQU             2C0h
        HLDATK          EQU             2C0h
        LFO2VAL         EQU             2E0h
        IP              EQU             300h
        IFATN           EQU             320h
        PEFE            EQU             340h
        FMMOD           EQU             360h
        TREMFRQ         EQU             380h
        FM2FRQ2         EQU             3A0h

ALIGN 4

InitTable1      Label
        DW      003FFh, 0030h,  007FFh, 0130h, 00BFFh, 0230h,  00FFFh, 0330h
        DW      013FFh, 0430h,  017FFh, 0530h, 01BFFh, 0630h,  01FFFh, 0730h
        DW      023FFh, 0830h,  027FFh, 0930h, 02BFFh, 0A30h,  02FFFh, 0B30h
        DW      033FFh, 0C30h,  037FFh, 0D30h, 03BFFh, 0E30h,  03FFFh, 0F30h

        DW      043FFh, 0030h,  047FFh, 0130h, 04BFFh, 0230h,  04FFFh, 0330h
        DW      053FFh, 0430h,  057FFh, 0530h, 05BFFh, 0630h,  05FFFh, 0730h
        DW      063FFh, 0830h,  067FFh, 0930h, 06BFFh, 0A30h,  06FFFh, 0B30h
        DW      073FFh, 0C30h,  077FFh, 0D30h, 07BFFh, 0E30h,  07FFFh, 0F30h

        DW      083FFh, 0030h,  087FFh, 0130h, 08BFFh, 0230h,  08FFFh, 0330h
        DW      093FFh, 0430h,  097FFh, 0530h, 09BFFh, 0630h,  09FFFh, 0730h
        DW      0A3FFh, 0830h,  0A7FFh, 0930h, 0ABFFh, 0A30h,  0AFFFh, 0B30h
        DW      0B3FFh, 0C30h,  0B7FFh, 0D30h, 0BBFFh, 0E30h,  0BFFFh, 0F30h

        DW      0C3FFh, 0030h,  0C7FFh, 0130h, 0CBFFh, 0230h,  0CFFFh, 0330h
        DW      0D3FFh, 0430h,  0D7FFh, 0530h, 0DBFFh, 0630h,  0DFFFh, 0730h
        DW      0E3FFh, 0830h,  0E7FFh, 0930h, 0EBFFh, 0A30h,  0EFFFh, 0B30h
        DW      0F3FFh, 0C30h,  0F7FFh, 0D30h, 0FBFFh, 0E30h,  0FFFFh, 0F30h

InitTable2      Label
        DW      003FFh, 8030h,  007FFh, 8130h, 00BFFh, 8230h,  00FFFh, 8330h
        DW      013FFh, 8430h,  017FFh, 8530h, 01BFFh, 8630h,  01FFFh, 8730h
        DW      023FFh, 8830h,  027FFh, 8930h, 02BFFh, 8A30h,  02FFFh, 8B30h
        DW      033FFh, 8C30h,  037FFh, 8D30h, 03BFFh, 8E30h,  03FFFh, 8F30h

        DW      043FFh, 8030h,  047FFh, 8130h, 04BFFh, 8230h,  04FFFh, 8330h
        DW      053FFh, 8430h,  057FFh, 8530h, 05BFFh, 8630h,  05FFFh, 8730h
        DW      063FFh, 8830h,  067FFh, 8930h, 06BFFh, 8A30h,  06FFFh, 8B30h
        DW      073FFh, 8C30h,  077FFh, 8D30h, 07BFFh, 8E30h,  07FFFh, 8F30h

        DW      083FFh, 8030h,  087FFh, 8130h, 08BFFh, 8230h,  08FFFh, 8330h
        DW      093FFh, 8430h,  097FFh, 8530h, 09BFFh, 8630h,  09FFFh, 8730h
        DW      0A3FFh, 8830h,  0A7FFh, 8930h, 0ABFFh, 8A30h,  0AFFFh, 8B30h
        DW      0B3FFh, 8C30h,  0B7FFh, 8D30h, 0BBFFh, 8E30h,  0BFFFh, 8F30h

        DW      0C3FFh, 8030h,  0C7FFh, 8130h, 0CBFFh, 8230h,  0CFFFh, 8330h
        DW      0D3FFh, 8430h,  0D7FFh, 8530h, 0DBFFh, 8630h,  0DFFFh, 8730h
        DW      0E3FFh, 8830h,  0E7FFh, 8930h, 0EBFFh, 8A30h,  0EFFFh, 8B30h
        DW      0F3FFh, 8C30h,  0F7FFh, 8D30h, 0FBFFh, 8E30h,  0FFFFh, 8F30h

InitTable3      Label
        DW      0C10h,  8470h,  14FEh, 0B488h, 167Fh,  0A470h, 18E7h,  84B5h
        DW      1B6Eh,  842Ah,  1F1Dh, 852Ah,  0DA3h,  9F7Ch,  167Eh, 0F254h
        DW      0,      842Ah,  1,     852Ah,  18E6h,  9BAAh,  1B6Dh, 0F234h
        DW      229Fh,  8429h,  2746h, 8529h,  1F1Ch,  96E7h,  229Eh, 0F224h

        DW      0DA4h,  8429h,  2C29h, 8529h,  2745h,  97F6h,  2C28h, 0F254h
        DW      383Bh,  8428h,  320Fh, 8528h,  320Eh,  9F02h,  1341h, 0F264h
        DW      3EB6h,  8428h,  3EB9h, 8528h,  383Ah,  9FA9h,  3EB5h, 0F294h
        DW      3EB7h,  8474h,  3EBAh, 8575h,  3EB8h,  0C4C3h, 3EBBh, 0C5C3h

        DW      00000,  0A404h, 00001, 0A504h, 141Fh,  8671h,  14FDh,  8287h
        DW      3EBCh,  0E610h, 3EC8h, 8C7Bh,  31Ah,   87E6h,  3EC8h,  86F7h
        DW      3EC0h,  821Eh,  3EBEh, 0D208h, 3EBDh,  821Fh,  3ECAh,  8386h
        DW      3EC1h,  8C03h,  3EC9h, 831Eh,  3ECAh,  8C4Ch,  3EBFh,  8C55h

        DW      3EC9h,  0C208h, 3EC4h, 0BC84h, 3EC8h,  8EADh,  3EC8h,  0D308h
        DW      3EC2h,  8F7Eh,  3ECBh,  821Eh, 3ECBh,  0D208h, 3EC5h,  831Fh
        DW      3EC6h,  0C308h, 3EC3h, 0B2FFh, 3EC9h,  8265h,  3EC9h,  831Eh
        DW      1342h,  0D308h, 3EC7h, 0B3FFh, 0,      8365h,  1420h,  9570h

InitTable4      Label
        DW      0C10h,  8470h,  14FEh, 0B488h, 167Fh,  0A470h, 18E7h,  84B5h
        DW      1B6Eh,  842Ah,  1F1Dh, 852Ah,  0DA3h,  0F7Ch,  167Eh,  7254h
        DW      0,      842Ah,  1,     852Ah,  18E6h,  0BAAh,  1B6Dh,  7234h
        DW      229Fh,  8429h,  2746h, 8529h,  1F1Ch,  6E7h,   229Eh,  7224h

        DW      0DA4h,  8429h,  2C29h, 8529h,  2745h,  07F6h,  2C28h,  7254h
        DW      383Bh,  8428h,  320Fh, 8528h,  320Eh,  0F02h,  1341h,  7264h
        DW      3EB6h,  8428h,  3EB9h, 8528h,  383Ah,  0FA9h,  3EB5h,  7294h
        DW      3EB7h,  8474h,  3EBAh, 8575h,  3EB8h,  44C3h,  3EBBh,  45C3h

        DW      00000,  0A404h, 00001, 0A504h, 141Fh,  0671h,  14FDh,  287h
        DW      3EBCh,  0E610h, 3EC8h, 0C7Bh,  31Ah,   7E6h,   3EC8h,  86F7h
        DW      3EC0h,  821Eh,  3EBEh, 0D208h, 3EBDh,  021Fh,  3ECAh,  386h
        DW      3EC1h,  0C03h,  3EC9h, 31Eh,   3ECAh,  8C4Ch,  3EBFh,  0C55h

        DW      3EC9h,  0C208h, 3EC4h, 0BC84h, 3EC8h,  0EADh,  3EC8h,  0D308h
        DW      3EC2h,  8F7Eh,  3ECBh, 021Eh,  3ECBh,  0D208h, 3EC5h,  31Fh
        DW      3EC6h,  0C308h, 3EC3h, 32FFh,  3EC9h,  0265h,  3EC9h,  831Eh
        DW      1342h,  0D308h, 3EC7h, 33FFh,  0,      8365h,  1420h,  9570h

AWEVolumeTable  Label   Byte    ; Value = -log(vol/256)*(20/.375)
                                ;       = -log(vol/256)*(160/3)

        DB      255, 128, 112, 103, 96, 91, 87, 83      ; 0->7
        DB      80, 78, 75, 73, 71, 69, 67, 66          ; 8->15
        DB      64, 63, 61, 60, 59, 58, 57, 56          ; 16->23
        DB      55, 54, 53, 52, 51, 50, 50, 49          ; 24->31
        DB      48, 47, 47, 46, 45, 45, 44, 44          ; 32->39
        DB      43, 42, 42, 41, 41, 40, 40, 39          ; 40->47
        DB      39, 38, 38, 37, 37, 36, 36, 36          ; 48->55
        DB      35, 35, 34, 34, 34, 33, 33, 32          ; 56->63
        DB      32, 32, 31, 31, 31, 30, 30, 30          ; 64->71
        DB      29, 29, 29, 28, 28, 28, 28, 27          ; 72->79
        DB      27, 27, 26, 26, 26, 26, 25, 25          ; 80->87
        DB      25, 25, 24, 24, 24, 23, 23, 23          ; 88->95
        DB      23, 22, 22, 22, 22, 22, 21, 21          ; 96->103
        DB      21, 21, 20, 20, 20, 20, 20, 19          ; 104->111
        DB      19, 19, 19, 19, 18, 18, 18, 18          ; 112->119
        DB      18, 17, 17, 17, 17, 17, 16, 16          ; 120->127
        DB      16                                      ; 128

        Comment ~               ; Value = -log(vol/128)*(20/.375)
                                ;       = -log(vol/128)*(160/3)
                ; This is mathematically the correct table, but it seems too
                ; loud, and it overloads on playback.

        DB      255, 112, 96, 87, 80, 75, 71, 67        ; 0->7
        DB      64, 61, 59, 57, 55, 53, 51, 50          ; 8->15
        DB      48, 47, 45, 44, 43, 42, 41, 40          ; 16->23
        DB      39, 38, 37, 36, 35, 34, 34, 33          ; 24->31
        DB      32, 31, 31, 30, 29, 29, 28, 28          ; 32->39
        DB      27, 26, 26, 25, 25, 24, 24, 23          ; 40->47
        DB      23, 22, 22, 21, 21, 20, 20, 20          ; 48->55
        DB      19, 19, 18, 18, 18, 17, 17, 16          ; 56->63
        DB      16, 16, 15, 15, 15, 14, 14, 14          ; 64->71
        DB      13, 13, 13, 13, 12, 12, 12, 11          ; 72->79
        DB      11, 11, 10, 10, 10, 9,  9,  9           ; 80->87
        DB      9,  8,  8,  8,  8,  7,  7,  7           ; 88->95
        DB      7,  6,  6,  6,  6,  5,  5,  5           ; 96->103
        DB      5,  4,  4,  4,  4,  4,  4,  3           ; 104->111
        DB      3,  3,  3,  2,  2,  2,  2,  2           ; 112->119
        DB      1,  1,  1,  1,  1,  1,  1,  1           ; 120->127
        DB      0

                ~

GUSScreenList           Label
                        DW      7
                        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      Near Ptr MixerText
                        DW      Near Ptr VolumeBox1
                        DW      Near Ptr VolumeBox2

                        DW      Near Ptr MasterVolumeLeft       ; 7
                        DW      Near Ptr MasterVolumeRight
                        DW      Near Ptr TrebleVolumeLeft
                        DW      Near Ptr TrebleVolumeRight
                        DW      Near Ptr BassVolumeLeft
                        DW      Near Ptr BassVolumeRight        ; 12

                        DW      Near Ptr SampleText

                        DW      Near Ptr SampleSize0Button       ; 14
                        DW      Near Ptr SampleSize1Button
                        DW      Near Ptr SampleSize2Button
                        DW      Near Ptr SampleSize3Button      ; 17

                        DW      Near Ptr EffectText
                        DW      Near Ptr EffectBox

                        DW      Near Ptr ChorusThumbBar         ; 20
                        DW      Near Ptr ReverbThumbBar

                        DW      DriverText

                        DW      0

GravisHeaderLine        DW      10
                        DB      "Sound Blaster AWE 32 Driver", 0

DriverText              DW      1
                        DB      27, 48
                        DB      21h
                        DB      "Sound Blaster AWE 32 Driver 1.5 for Impulse Tracker", 0

MixerText               DW      1
                        DB      3, 13
                        DB      20h
                        DB      "Mixer options", 13
                        DB      13
                        DB      "  Master Volume Left", 13
                        DB      "  Master Volume Right", 13
                        DB      13
                        DB      13
                        DB      "  Treble Left", 13
                        DB      "  Treble Right", 13
                        DB      "  Bass Left", 13
                        DB      "  Bass Right", 13
                        DB      0

VolumeBox1              DW      0
                        DB      24, 14, 30, 17
                        DB      25

VolumeBox2              DW      0
                        DB      17, 18, 21, 23
                        DB      25

MasterVolumeLeft        DW      9
                        DB      25, 15
                        DW      0, 31
                        DW      9, 0
                        DW      0FFFFh, 8, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

MasterVolumeRight       DW      9
                        DB      25, 16
                        DW      0, 31
                        DW      9, 1
                        DW      7, 9, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

TrebleVolumeLeft        DW      9
                        DB      18, 19
                        DW      0, 15
                        DW      9, 2
                        DW      8, 10, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

TrebleVolumeRight       DW      9
                        DB      18, 20
                        DW      0, 15
                        DW      9, 3
                        DW      9, 11, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

BassVolumeLeft          DW      9
                        DB      18, 21
                        DW      0, 15
                        DW      9, 4
                        DW      10, 12, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

BassVolumeRight         DW      9
                        DB      18, 22
                        DW      0, 15
                        DW      9, 5
                        DW      11, 14, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

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

SampleSize0Button       DW      2
                        DW      12, 15, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment1          DW      0
                        DW      0
                        DW      Offset SetCompress
DriverSegment2          DW      0
                        DB      7, 27, 20, 29, 8
                        DB      0
                        DB      "  Original", 0

SampleSize1Button       DW      2
                        DW      14, 16, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment3          DW      0
                        DW      1
                        DW      Offset SetCompress
DriverSegment4          DW      0
                        DB      7, 30, 20, 32, 8
                        DB      0
                        DB      "  Half", 0

SampleSize2Button       DW      2
                        DW      15, 17, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment5          DW      0
                        DW      2
                        DW      Offset SetCompress
DriverSegment6          DW      0
                        DB      7, 33, 20, 35, 8
                        DB      0
                        DB      "  Quarter", 0

SampleSize3Button       DW      2
                        DW      16, 20, 0FFFFh, 0FFFFh
                        DW      0
                        DW      0, 0
                        DW      6
                        DW      Offset GetCompress
DriverSegment7          DW      0
                        DW      3
                        DW      Offset SetCompress
DriverSegment8          DW      0
                        DB      7, 36, 20, 38, 8
                        DB      0
                        DB      "  Eighth", 0

EffectText              DW      1
                        DB      3, 40
                        DB      20h
                        DB      "Effect options", 13
                        DB      13
                        DB      "  Chorus", 13
                        DB      "  Reverb", 0


EffectBox               DW      0
                        DB      12, 41, 30, 44
                        DB      25

ChorusThumbBar          DW      9
                        DB      13, 42
                        DW      0, 127
                        DW      9, 6
                        DW      17, 21, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh

ReverbThumbBar          DW      9
                        DB      13, 43
                        DW      0, 127
                        DW      9, 7
                        DW      20, 0FFFFh, 0FFFFh, 0FFFFh
                        DW      0FFFFh, 0FFFFh



VolumeTable             DB      6 Dup (0)
CONFIGURATIONOFFSET     EQU     $+128
CONFIGSIZE              EQU     2
Chorus                  DB      10, 64

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

ALIGN 16
FPSave                  DB      128 Dup (0)

AWEParameters   DB      64 Dup (0FFh), 64 Dup (0)

include dma.inc

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

Proc            SBOut           ; AL = data
                                ; DX = 2xCh

                Push    AX

SBOut1:
                In      AL, DX
                Test    AL, AL
                JS      SBOut1

                Pop     AX
                Out     DX, AL

                Ret

EndP            SBOut

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

Proc            UARTOut

                Push    CX
                Push    DX
                Mov     DX, CS:MIDIPort
                Test    DX, DX
                JZ      UARTOutEnd

                Push    AX
                Xor     CX, CX
                Inc     DX

UARTOut1:
                In      AL, DX
                Test    AL, 40h
                LoopNZ  UARTOut1

                Pop     AX
                JNZ     UARTOutEnd

                Dec     DX
                Out     DX, AL

UARTOutEnd:
                Pop     DX
                Pop     CX

                Ret

EndP            UARTOut

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


InterpretState  DB      0
InterpretType   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.

                Push    BX

                Mov     BL, CS:InterpretType    ; Want BX = InterpretType*64+Channel
                                                ;
                ShL     BX, 6
                Add     BL, [DI+20h]
                And     BX, 127
                Mov     [CS:AWEParameters+BX], AL

                Pop     BX

                Mov     CS:InterpretState, 0

                Test    SI, SI
                JZ      SendUARTOut4

                Or      Byte Ptr [SI], 64

SendUARTOut4:
                Ret

SendUARTOut3:
                Mov     InterpretType, AL
                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:
                Cmp     AL, 0FCh
                JE      ResetFilters
                Cmp     AL, 0FAh
                JE      ResetFilters

                Cmp     AL, 0FFh
                JNE     SendUARTOutNoClear

ResetFilters:
                PushA
                Push    ES

                Push    CS
                Pop     ES

                Mov     DI, Offset AWEParameters
                Mov     CX, 32
                Or      AX, -1
                Rep     StosW
                Mov     CX, 32
                Inc     AX
                Rep     StosW

                Pop     ES
                PopA

SendUARTOutNoClear:
                Call    UARTOut
                Ret

EndP            SendUARTOut

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

Proc            DetectUART              ; Given DX = Port

;        outportb(BasePort+1, 0xFF);
;        while(InputUART() != 0xFE);
;        outportb(BasePort+1, 0x3F);
;        while(InputUART() != 0xFE);

                ClI

                Inc     DX
                Mov     AL, 0FFh        ; reset
                Out     DX, AL
                Xor     CX, CX

DetectUART1:
                In      AL, DX
                Test    AL, 80h
                LoopNZ  DetectUART1
                JNZ     DetectUARTFailed

                Dec     DX
                In      AL, DX
                Inc     DX
                Cmp     AL, 0FEh
                JNE     DetectUART1

                Xor     CX, CX

DetectUART3:
                In      AL, DX
                Test    AL, 40h
                LoopNZ  DetectUART3
                JNZ     DetectUARTFailed

                Mov     AL, 03Fh
                Out     DX, AL

                Xor     CX, CX

DetectUART2:
                In      AL, DX
                Test    AL, 80h
                LoopNZ  DetectUART2
                JNZ     DetectUARTFailed

                Dec     DX
                In      AL, DX
                Inc     DX
                Cmp     AL, 0FEh
                JNE     DetectUART2
                Dec     DX

                ClC
                StI
                Ret

DetectUARTFailed:
                StC
                StI
                Ret

Comment ~

; From SB-DevKit

                ClI

                Inc     DX
                Xor     CX, CX

DetectUART1:
                In      AL, DX
                Test    AL, 40h         ; Ready for output
                LoopNZ  DetectUART1
                JNZ     DetectUARTError

                Mov     AL, 0FFh        ; Reset!
                Out     DX, AL

                Xor     CX, CX

DetectUART2:
                In      AL, DX
                Test    AL, 80h
                JNZ     DetectUART3

                Dec     DX
                In      AL, DX
                Inc     DX
                Cmp     AL, 0FEh
                JE      DetectUART4

DetectUART3:
                Loop    DetectUART2

DetectUARTError:
                StI
                StC
                Ret

DetectUART4:                    ; Now to shove it into 'intelligent' mode.
                Xor     CX, CX

DetectUART5:
                In      AL, DX
                Test    AL, 40h
                LoopNZ  DetectUART5
                JNZ     DetectUARTError

                Mov     AL, 3Fh         ; Intelligent mode!
                Out     DX, AL

DetectUART6:
                Xor     CX, CX

DetectUART7:
                In      AL, DX
                Test    AL, 80h
                JNZ     DetectUART8

                Dec     DX
                In      AL, DX
                Inc     DX
                Cmp     AL, 0FEh
                JE      DetectUART9

DetectUART8:
                Loop    DetectUART7

                Jmp     DetectUARTError

DetectUART9:
                StI
                ClC
                Ret

~

EndP            DetectUART

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

Proc            ReinitUART

                Mov     DX, MIDIPort
                Test    DX, DX
                JZ      ReinitUART1

                Call    DetectUART

ReinitUART1:
                Ret

EndP            ReinitUART

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

Proc            ResetUART

                Mov     DX, MIDIPort
                Test    DX, DX
                JZ      ResetUART1

                Inc     DX

                Mov     AL, 0FFh
                Out     DX, AL

ResetUART1:
                Ret

EndP            ResetUART

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

Proc            SetCompress Far

                Mov     CX, [SI+22]
                Mov     CS:Compress, CL

                Mov     AX, 1
                ShL     AX, CL
                Mov     CS:Step, AX

                Call    Music_LoadAllSamples

                Mov     AX, 1
                Ret

EndP            SetCompress

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

Proc            GetCompress Far

                Push    CS
                Pop     ES
                Mov     DI, Offset Compress

                Ret

EndP            GetCompress

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

Proc            Load8BitSamplesForwards ; Given DS:SI, ECX = count

                Push    BX

                Mov     BX, CS:Step
                Mov     DX, CS:BasePort
                Add     DX, 400h
                Xor     AL, AL

Load8BitSamplesForwards2:
                Mov     AH, [SI]
                Add     SI, BX
                JC      Load8BitSamplesForwards4

Load8BitSamplesForwards3:
                Out     DX, AX

                Dec     ECX
                JNZ     Load8BitSamplesForwards2

                Pop     BX
                Ret

Load8BitSamplesForwards4:
                Add     ESI, 10000h
                Int     3
                Jmp     Load8BitSamplesForwards3

EndP            Load8BitSamplesForwards

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

Proc            Load16BitSamplesForwards ; Given DS:SI, ECX = count

                Push    BX

                Mov     BX, CS:Step
                Mov     DX, CS:BasePort
                Add     DX, 400h
                Add     BX, BX

Load16BitSamplesForwards2:
                Mov     AX, [SI]
                Add     SI, BX
                JC      Load16BitSamplesForwards4

Load16BitSamplesForwards3:
                Out     DX, AX

                Dec     ECX
                JNZ     Load16BitSamplesForwards2

                Pop     BX
                Ret

Load16BitSamplesForwards4:
                Add     ESI, 10000h
                Int     3
                Jmp     Load16BitSamplesForwards3

EndP            Load16BitSamplesForwards

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

Proc            Load8BitSamplesBackwards ; Given DS:SI, ECX = count

                Push    BX

                Mov     BX, CS:Step
                Mov     DX, CS:BasePort
                Add     DX, 400h
                Xor     AL, AL

                Sub     SI, BX
                JC      Load8BitSamplesBackwards6

Load8BitSamplesBackwards2:
                Sub     SI, BX
                JC      Load8BitSamplesBackwards4

Load8BitSamplesBackwards3:
                Mov     AH, [SI]
                Out     DX, AX

                Dec     ECX
                JNZ     Load8BitSamplesBackwards2


                Pop     BX
                Ret

Load8BitSamplesBackwards4:
                Sub     ESI, 10000h
                JC      Load8BitSamplesBackwards5
                Int     3
                Jmp     Load8BitSamplesBackwards3

Load8BitSamplesBackwards5:
                Xor     ESI, ESI
                Jmp     Load8BitSamplesBackwards3

Load8BitSamplesBackwards6:
                Sub     ESI, 10000h
                Int     3
                Jmp     Load8BitSamplesBackwards2


EndP            Load8BitSamplesBackwards

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

Proc            Load16BitSamplesBackwards ; Given DS:SI, ECX = count

                Push    BX

                Mov     BX, CS:Step
                Mov     DX, CS:BasePort
                Add     DX, 400h
                Add     BX, BX

                Sub     SI, BX
                JC      Load16BitSamplesBackwards6

Load16BitSamplesBackwards2:
                Sub     SI, BX
                JC      Load16BitSamplesBackwards4

Load16BitSamplesBackwards3:
                Mov     AX, [SI]
                Out     DX, AX

                Dec     ECX
                JNZ     Load16BitSamplesBackwards2

                Pop     BX
                Ret

Load16BitSamplesBackwards4:
                Sub     ESI, 10000h
                JC      Load16BitSamplesBackwards5
                Int     3
                Jmp     Load16BitSamplesBackwards3

Load16BitSamplesBackwards5:
                Xor     ESI, ESI
                Jmp     Load16BitSamplesBackwards3

Load16BitSamplesBackwards6:
                Sub     ESI, 10000h
                Int     3
                Jmp     Load16BitSamplesBackwards2


EndP            Load16BitSamplesBackwards

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

Proc            WriteDataChannel

                Or      AX, DX

Proc            WriteData       ; Have BX/EBX = value
                                ; AX = xxyyh
                                ;      ^ ^
                                ;      | |
                                ;      | \-- value to send to pointer register
                                ;      \---- 0, 1, 2 or 3, 4
                                ;       0 = data reg 0
                                ;       1 = data reg 1, dword
                                ;       2 = data reg 2
                                ;       3 = data reg 3
                                ;       4 = data reg 4, word

                Jmp     $+2
                Jmp     $+2

                Push    DX
                Push    AX

                Mov     DX, BasePort
                Add     DX, 802h
                And     AX, 0FFh
                Out     DX, AX
                Pop     AX

                Jmp     $+2
                Jmp     $+2

                Cmp     AH, 1
                JB      WriteDataReg0
                JE      WriteDataReg1DWord
                Cmp     AH, 3
                JB      WriteDataReg2
                JE      WriteDataReg3
                Jmp     WriteDataReg1Word

WriteDataReg0:
                Sub     DX, 802h
                Mov     EAX, EBX
                Out     DX, EAX

                Pop     DX
                Ret

WriteDataReg1DWord:
                Sub     DX, 402h
                Mov     EAX, EBX
                Out     DX, EAX

                Pop     DX
                Ret

WriteDataReg1Word:
                Sub     DX, 402h
                Mov     AX, BX
                Out     DX, AX

                Pop     DX
                Ret

WriteDataReg2:
                Sub     DX, 400h
                Mov     AX, BX
                Out     DX, AX

                Pop     DX
                Ret

WriteDataReg3:
                Sub     DL, 2
                Mov     AX, BX
                Out     DX, AX

                Pop     DX
                Ret

EndP            WriteData

EndP            WriteDataChannel

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

Proc            ReadDataChannel

                Or      AX, DX

Proc            ReadData       ; AX = xxyyh
                                ;      ^ ^
                                ;      | |
                                ;      | \-- value to send to pointer register
                                ;      \---- 0, 1, 2 or 3, 4
                                ;       0 = data reg 0
                                ;       1 = data reg 1, dword
                                ;       2 = data reg 2
                                ;       3 = data reg 3
                                ;       4 = data reg 4, word

                Jmp     $+2
                Jmp     $+2

                Push    DX
                Push    AX

                Mov     DX, BasePort
                Add     DX, 802h
                And     AX, 0FFh
                Out     DX, AX
                Pop     AX

                Jmp     $+2
                Jmp     $+2

                Cmp     AH, 1
                JB      ReadDataReg0
                JE      ReadDataReg1DWord
                Cmp     AH, 3
                JB      ReadDataReg2
                JE      ReadDataReg3
                Jmp     ReadDataReg1Word

ReadDataReg0:
                Sub     DX, 802h
                In      EAX, DX

                Pop     DX
                Ret

ReadDataReg1DWord:
                Sub     DX, 402h
                In      EAX, DX

                Pop     DX
                Ret

ReadDataReg1Word:
                Sub     DX, 402h
                In      AX, DX

                Pop     DX
                Ret

ReadDataReg2:
                Sub     DX, 400h
                In      AX, DX

                Pop     DX
                Ret

ReadDataReg3:
                Sub     DL, 2
                In      AX, DX

                Pop     DX
                Ret

EndP            ReadData

EndP            ReadDataChannel

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

Const44100      DD      44100.0
Const1000h      DD      4096.0
ConstE000h      DD      57344.0

Proc            SetAWEFrequency

                Mov     EAX, [SI+10h]   ; Final freq

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

;                Test    EAX, EAX
                JZ      SetAWEFrequencyError
                Cmp     EAX, 88200*2
                JAE     SetAWEFrequencyError

                Mov     DWord Ptr [SI+4], EAX

                FLd     CS:ConstE000h
                FLd     CS:Const1000h
                FILd    DWord Ptr [SI+4]
                FDiv    CS:Const44100
                FYL2X   ; ST = ln(Pitch/44100)/ln(2) * 1000h
                FAddP   ST(1)
                FIStP   DWord Ptr [SI+4]

                Mov     AX, IP
                Mov     BX, [SI+4]
                Call    WriteDataChannel

                Ret
                        Assume DS:Nothing

SetAWEFrequencyError:
                Call    StopAWENote

                Mov     Word Ptr [SI], 200h
                Test    Byte Ptr [SI+3Ah], 80h
                JNZ     SetAWEFrequencyError1

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

SetAWEFrequencyError1:
                Mov     AX, IP
                Xor     EBX, EBX
                Call    WriteDataChannel

                Push    DS SI

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

                Pop     SI DS

                Ret

EndP            SetAWEFrequency
                Assume DS:Nothing

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

Proc            SetAWEPan

                Mov     AX, PSST
                Call    ReadDataChannel         ; Get starting offset

                Cmp     CS:Stereo, 0
                JE      SetPan2

                Test    CL, 128
                JNZ     SetPan2

                Mov     BL, [SI+37h]            ; Final pan
                Cmp     BL, 100                 ; Surround -> central
                JNE     SetPan1

SetPan2:
                Mov     BL, 32

SetPan1:                        ; BL = 0->64, need to extend to 0->255
                Add     BL, BL
                Add     BL, BL
                SBB     BL, 0   ; BL = 0->255
                Not     BL

                ShL     EAX, 8
                SHLD    EBX, EAX, 24
                Mov     AX, PSST
                Call    WriteDataChannel

                Ret

EndP            SetAWEPan

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

Proc            SetAWEVolume

                Test    CH, 8
                JZ      SetAWEVolume1

                Test    CH, 1
                JNZ     SetAWEVolume5

                Cmp     Byte Ptr [SI+8], 0FFh
                JE      SetAWEVolume4

SetAWEVolume5:
                Mov     Byte Ptr [SI+8], 0FFh

                Mov     AX, IFATN
                Call    ReadDataChannel
                Mov     BX, AX
                Mov     AX, IFATN
                Mov     BL, 0FFh
                Call    WriteDataChannel

SetAWEVolume4:
                Ret

SetAWEVolume1:
; First check if channel has been disowned
                Xor     BX, BX
                Mov     BL, [SI+3Ah]                    ; BL = host channel

                Test    BL, BL
                JS      SetAWEVolume3

SetAWEVolume2:
                Mov     AH, [CS:AWEParameters+BX]       ; AH = filter
                Mov     AL, [CS:AWEParameters+BX+64]    ; AL = Q.

                ShR     AL, 3
                Mov     [SI+5Bh], AH

                Cmp     AL, [SI+3Fh]
                JE      SetAWEVolume3

                Mov     [SI+3Fh], AL

; Set Q
                Mov     BL, AL
                ShL     EBX, 28

                Mov     AX, CCCA
                Call    ReadDataChannel
                And     EAX, 0FFFFFFFh
                Or      EBX, EAX
                Mov     AX, CCCA
                Call    WriteDataChannel

SetAWEVolume3:
                Mov     AL, [SI+3Eh]
                Mul     Byte Ptr [SI+5Bh]
                ShL     AX, 1
                Xor     BX, BX
                Add     AH, 1
                Mov     BL, [SI+20h]                    ; Final volume
                Mov     [SI+8], BL
                Mov     BL, [CS:AWEVolumeTable+BX]
                Mov     BH, AH
                Mov     AX, IFATN
                Call    WriteDataChannel

                Ret

EndP            SetAWEVolume

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

Proc            StopAWENote

                Mov     AX, DCYSUSV
                Mov     BX, 80h
                Call    WriteDataChannel

                Mov     AX, VTFT
                Mov     EBX, 0FFFFh
                Call    WriteDataChannel

                Mov     AX, CVCF
                Call    WriteDataChannel

                Mov     BX, 80h
                Mov     AX, DCYSUSV
                Call    WriteDataChannel

                Mov     AX, VTFT
                Mov     EBX, 0FFFFh
                Call    WriteDataChannel

                Mov     AX, CVCF
                Call    WriteDataChannel

                Xor     EBX, EBX
                Mov     AX, ENVVOL
                Call    WriteDataChannel

                Mov     AX, ENVVAL
                Call    WriteDataChannel

                Mov     AX, SUSDCY
                Call    WriteDataChannel

                Mov     AX, ATKHLDV
                Call    WriteDataChannel

                Mov     AX, LFO1VAL
                Call    WriteDataChannel

                Mov     AX, HLDATK
                Call    WriteDataChannel

                Mov     AX, LFO2VAL
                Call    WriteDataChannel

                Mov     AX, IP
                Call    WriteDataChannel

                Mov     AX, IFATN
                Call    ReadDataChannel
                Mov     BH, AH
                Mov     AX, IFATN
                Call    WriteDataChannel

                Xor     EBX, EBX
                Mov     AX, PEFE
                Call    WriteDataChannel

                Mov     AX, FMMOD
                Call    WriteDataChannel

                Mov     AX, TREMFRQ
                Call    WriteDataChannel

                Mov     AX, FM2FRQ2
                Call    WriteDataChannel

                Mov     AX, PTRX
                Call    WriteDataChannel

                Mov     AX, VTFT
                Call    WriteDataChannel

;                Mov     AX, PSST
;                Call    WriteDataChannel

                Mov     BL, 8
                Mov     AX, CSL
                Call    WriteDataChannel

                Mov     AX, CCCA
                Call    ReadDataChannel
                Mov     EBX, EAX
                Mov     AX, CCCA
                And     EBX, 0F0000000h
                Call    WriteDataChannel

                Xor     EBX, EBX
                Mov     AX, CPF
                Call    WriteDataChannel

                Ret

EndP            StopAWENote

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

Proc            SetAWERegisters         ; DS:SI = channel info table
                                        ; CX = number of channels...

                Push    CX
                Push    SI

                                        ; Stage 1.
                                        ;  Turn off any channel which has
                                        ;  a new note to play
                                        ;  If no new note to play and channel
                                        ;  is on, then get current position

                Xor     DX, DX          ; DX = oscillator number

GetAWERegisters1:
                Mov     BX, [SI]
                Test    BH, 2           ; Note cut command
                JZ      GetAWERegisters2

                Mov     BX, 200h
                Mov     [SI], BX

                Call    StopAWENote
                Jmp     GetAWERegisters4

GetAWERegisters2:
                Test    BL, 1           ; Channel on?
                JZ      GetAWERegisters4

                Test    BH, 1           ; New note?
                JZ      GetAWERegisters3

                                        ; Fade out volume
;                Mov     AX, DCYSUSV
;                Mov     BX, 807Fh
;                Call    WriteDataChannel

                Call    StopAWENote

                Jmp     GetAWERegisters4

GetAWERegisters3:                       ; Get offset
                Mov     AX, CCCA
                Call    ReadDataChannel

                Xor     BX, BX
                And     EAX, 00000000111111111111111111111111b
                Inc     EAX             ; Interpolator correction
                                        ; EAX = address in sound memory
                Mov     BL, [SI+36h]    ; BL = sample number
                LEA     BX, [EBX*4+EBX]
                ShL     BX, 2
                Add     BX, Offset AWEDataTable

                Cmp     Byte Ptr [SI+0Ah], 8
                JB      GetAddressNoLoop
                JE      GetAddressForwardsLoop

GetAddressPingPongLoop:
                Cmp     EAX, [CS:BX+16]
                JB      SetOldAddress

                Neg     EAX
                Add     EAX, [CS:BX+8]
                Jmp     SetOldAddress1

GetAddressNoLoop:
                Cmp     EAX, [CS:BX+4]  ; Start loop
                JB      SetOldAddress

                Call    StopAWENote

                                        ; OK.. gotta turn off channel
                Mov     Word Ptr [SI], 0
                Test    Byte Ptr [SI+3Ah], 80h
                JNZ     GetAWERegisters4

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

                Jmp     GetAWERegisters4

GetAddressForwardsLoop:
SetOldAddress:
                Sub     EAX, [CS:BX]    ; EAX = address in sample
                JNS     SetOldAddress1

                Xor     EAX, EAX

SetOldAddress1:
                Push    CX
                Mov     CL, Compress
                ShL     EAX, CL
                Pop     CX

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

GetAWERegisters4:
                Add     SI, 128

                Inc     DX
                Dec     CX
                JNZ     GetAWERegisters1

                Pop     SI
                Pop     CX

                Xor     DX, DX          ; DX = oscillator number

SetAWERegisters1:
        ; Stage 2.
        ; If new frequency, play new frequency
        ; If new volume, play new volume
        ; If new pan, play new pan
        ; If new note, set ENVVOL, ENVVAL, SUSDCY, ATKHLDV, LFO1VAL, HLDATK
        ;                  LFO2VAL, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2
        ;                  PSST, CSL, CCCA
        ;                  VTFT, CVCF, DCYSUSV, PTRX, CPF

                Push    CX
                Mov     CX, [SI]
                Test    CL, 1                   ; Channel on?
                JZ      SetAWERegistersEnd

                Test    CH, 1                   ; New note?
                JZ      SetAWERegisters2

                Xor     BX, BX
                Mov     BL, [SI+36h]
                LEA     DI, [EBX*4+EBX]
                ShL     DI, 2
                Add     DI, Offset AWEDataTable

                Mov     AX, DCYSUSV
                Mov     BX, 80h
                Call    WriteDataChannel

                Mov     AX, VTFT
                Xor     EBX, EBX
                Call    WriteDataChannel

                Mov     AX, CVCF
                Call    WriteDataChannel

                Cmp     DWord Ptr [CS:DI], 0FFFFFFFFh
                JE      SetAWERegistersError

                Mov     AX, PTRX
                Call    WriteDataChannel

                Mov     AX, CPF
                Call    WriteDataChannel


                Mov     AX, ENVVOL
                Mov     BX, 8000h
                Call    WriteDataChannel

                Mov     AX, ENVVAL
                Mov     BX, 8000h
                Call    WriteDataChannel

                Mov     AX, SUSDCY
                Mov     BX, 7F7Fh
                Call    WriteDataChannel

                Mov     AX, ATKHLDV
                Call    WriteDataChannel

                Mov     AX, LFO1VAL
                Mov     BX, 8000h
                Call    WriteDataChannel

                Mov     AX, HLDATK
                Mov     BX, 7F7Fh
                Call    WriteDataChannel

                Mov     AX, LFO2VAL
                Mov     BX, 8000h
                Call    WriteDataChannel

                Call    SetAWEFrequency
                Call    SetAWEVolume

                Mov     AX, PEFE
                Xor     BX, BX
                Call    WriteDataChannel

                Mov     AX, FMMOD
                Call    WriteDataChannel

                Mov     AX, TREMFRQ
                Mov     BX, 10h
                Call    WriteDataChannel

                Mov     AX, FM2FRQ2
                Call    WriteDataChannel


                Mov     EBX, [CS:DI+4]
                Dec     EBX                     ; Interpolator offset
                Mov     AX, PSST
                Call    WriteDataChannel

                Call    SetAWEPan

                Mov     AL, [CS:VolumeTable+6]  ; Chorus
                ShL     EAX, 24
                Mov     EBX, [CS:DI+8]
                Dec     EBX                     ; Interpolator offset
                Or      EBX, EAX
                Mov     AX, CSL
                Call    WriteDataChannel

                Mov     AL, [SI+3Fh]
                ShL     EAX, 28

                Push    CX
                Mov     CL, Compress
                Mov     EBX, [SI+4Ch]
                ShR     EBX, CL
                Pop     CX
                Add     EBX, [CS:DI]
                Dec     EBX                     ; Interpolator offset
                Or      EBX, EAX

                Mov     AX, CCCA                ; Current address.
                Call    WriteDataChannel


                Mov     AX, VTFT
                Mov     EBX, 0FFFFh
                Call    WriteDataChannel

                Mov     AX, CVCF
                Call    WriteDataChannel

                Mov     AX, DCYSUSV
                Mov     BX, 7F7Fh
                Call    WriteDataChannel

                Mov     AX, PTRX
                Mov     EBX, 40000000h          ; 25% reverb
                Or      BH, [CS:VolumeTable+7]
                Call    WriteDataChannel

                Mov     AX, CPF
                Call    WriteDataChannel
                Jmp     SetAWERegistersEnd

SetAWERegisters2:
                Test    CL, 32                  ; Frequency change?
                JZ      SetAWERegisters3

                Call    SetAWEFrequency

SetAWERegisters3:
                Test    CL, 64                  ; Volume change?
                JZ      SetAWERegisters4

                Call    SetAWEVolume

SetAWERegisters4:
                Test    CH, 80h                 ; New pan?
                JZ      SetAWERegistersEnd

                Call    SetAWEPan

SetAWERegistersEnd:
                Pop     CX
                And     Word Ptr [SI], 0111100010011111b

                Add     SI, 128

                Inc     DX
                Dec     CX
                JNZ     SetAWERegisters1

                Ret

SetAWERegistersError:
                Call    StopAWENote

                Mov     Word Ptr [SI], 0
                Test    Byte Ptr [SI+3Ah], 80h
                JNZ     SetAWERegistersEnd

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

                Jmp     SetAWERegistersEnd

EndP            SetAWERegisters

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

Proc            ACKIRQ

                Mov     AL, 20h
                Cmp     CS:IRQ, 7
                JBE     ACKIRQ1

                Out     0A0h, AL

ACKIRQ1:
                Out     20h, AL
                Ret

EndP            ACKIRQ

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

Proc            CheckMIDI

                Push    DS

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Xor     BX, BX
                Mov     DX, MIDIPort

                Mov     BL, [MIDIBufferTail]
                Test    DX, DX
                JZ      CheckMIDIEnd

                Inc     DX

CheckMIDIAgain:
                In      AL, DX

                Test    AL, AL
                JS      CheckMIDIAgain

                Dec     DX
                In      AL, DX

                Cmp     AL, 0F0h
                JAE     CheckMIDIEnd

                Inc     BL
                Cmp     BL, MIDIBufferHead
                JE      CheckMIDIEnd

                Mov     [MIDIBuffer+BX], AL
                Mov     [MIDIBufferTail], BL

CheckMIDIEnd:
                Pop     DS
                Ret

EndP            CheckMIDI
                Assume DS:Nothing

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

Proc            MIDIIRQHandler

                Push    AX BX DX

                Mov     DX, CS:MixerPort
                Mov     AL, 82h
                Out     DX, AL
                Inc     DL
                In      AL, DX

                Test    AL, 4
                JZ      MIDIIRQHandlerEnd

                Call    CheckMIDI

MIDIIRQHandlerEnd:
                Call    AckIRQ

                Pop     DX BX AX
                IRet


EndP            MIDIIRQHandler

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

Proc            SBIRQHandler

                PushAD
                Push    DS
                Push    ES

                StI

                Push    CS
                Pop     DS
                        Assume DS:Driver

                FNSave  [FPSave]

SBIRQHandlerAgain:
                Mov     DX, MixerPort
                Mov     AL, 82h
                Out     DX, AL
                Inc     DL
                In      AL, DX

                Test    AL, 4
                JZ      NoMIDIIRQ

                Push    AX
                Call    CheckMIDI
                Pop     AX

NoMIDIIRQ:
;                Test    AL, 2
;                JZ      No16BitIRQ
;
;                Push    AX
;                Mov     DX, MixerPort
;                Add     DL, 0Fh-4
;                In      AL, DX
;                Pop     AX
;
; No16BitIRQ:
                Test    AL, 1
                JNZ     SB8BitIRQ

SBNo8BitIRQ:
                Call    AckIRQ
                Jmp     SBEndIRQ

SB8BitIRQ:
                Mov     DX, MixerPort
                Add     DL, 0Eh-4
                In      AL, DX          ; 8-bit IRQ ack.


;                Add     DL, 0Ch-0Eh

;                Mov     AL, 80h         ; Output block of silence
;                Call    SBOut
;                Mov     AX, BlockLength2
;                Call    SBOut
;                Mov     AL, AH
;                Call    SBOut

                ClD
                Call    ACKIRQ

                Inc     IRQFlag
                JNZ     SBEndIRQ

                Call    SaveEMSPageFrame
                        Assume DS:Nothing

SB8BitIRQAgain:
                Call    Update          ; Returns DS:SI, CX

                Mov     BX, BlockLength
                Cmp     BX, BlockLength2
                JE      SBIRQHandler2
                Mov     BlockLength2, BX

                Mov     DX, SB16BasePort
                Add     DL, 0Ch

                MOv     AL, 0DAh
                Call    SBOut
                Mov     AL, 0C6h
                Call    SBOut
                Xor     AL, AL
                Call    SBOut
                Mov     AL, BL
                Call    SBOut
                Mov     AL, BH
                Call    SBOut

;                Mov     AL, 0D0h
;                Call    SBOut

;                Mov     AL, 80h         ; Output block of silence
;                Call    SBOut
;                Mov     AL, BL
;                Call    SBOut
;                Mov     AL, BH
;                Call    SBOut

SBIRQHandler2:
                Call    SetAWERegisters
                Sub     CS:IRQFlag, 1
                JNC     SB8BitIRQAgain

                Call    RestoreEMSPageFrame

SBEndIRQ:
                FRstor  [CS:FPSave]

                Pop     ES
                Pop     DS
                PopAD

                IRet

EndP            SBIRQHandler
                Assume DS:Nothing

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

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

                Mov     AX, AWEUpdateTimer
                Add     AWEUpdateCount, AX
                JC      AWEIRQHandler1

                Mov     AL, 20h
                Out     20h, AL
                Jmp     AWEIRQHandler2

AWEIRQHandler1:
                PushF
                Call    [OldIRQHandler]

AWEIRQHandler2:
                Xor     AWEUpdateFlag, 1
                JZ      AWEIRQHandlerEnd

                FNSave  [CS:FPSave]

                PushAD
                Push    ES

                ClD

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

                Pop     ES
                PopAD

                FRstor  [CS:FPSave]

AWEIRQHandlerEnd:
                Pop     DS
                Pop     AX
                IRet

EndP            AWEIRQHandler

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

Proc            EnableRAM

                Mov     DX, BasePort
                Mov     CX, 29

EnableRAM1:
                Mov     AX, DCYSUSV
                Or      AX, CX
                Mov     BX, 80h
                Call    WriteData

                Mov     AX, VTFT
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CVCF
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, PTRX
                Or      AX, CX
                Mov     EBX, 40000000h
                Call    WriteData

                Mov     AX, CPF
                Or      AX, CX
                Mov     EBX, 40000000h
                Call    WriteData

                Mov     AX, PSST
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CSL
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CCCA
                Or      AX, CX
                Mov     EBX, 6000000h   ; Left write
                Call    WriteData

                Dec     CX
                JNS     EnableRAM1

                Ret

EndP            EnableRAM

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

Proc            TestAWE                 ; Given DX = baseport.

                Push    DX

                Add     DX, 802h
                In      AL, DX
                In      AL, DX
                Not     AL
                Mov     BL, AL
                Out     DX, AL
                In      AL, DX
                Cmp     AL, BL
                JNE     TestAWE1                ; Register changed

                In      AX, DX                  ; Is upper part of pointer
                Mov     BX, AX                  ;  changing?
                Mov     CX, 128

TestAWE2:
                In      AX, DX
                Cmp     AL, BL
                JNE     TestAWE1
                Cmp     AH, BH
                JNE     TestAWE3

                Dec     CX
                JNZ     TestAWE2
                Jmp     TestAWE1

TestAWE3:
                Pop     DX

                ClC
                Ret

TestAWE1:
                Pop     DX
                StC
                Ret

EndP            TestAWE

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

Proc            InitSetAWE

                Mov     CX, 31

InitSetAWE1:
                Mov     AX, 31
                Sub     AX, CX
                Mov     BX, [SI]
                Or      AX, INIT1
                Call    WriteData

                Add     SI, 2

                Dec     CX
                JNS     InitSetAWE1

                Mov     CX, 31

InitSetAWE2:
                Mov     AX, 31
                Sub     AX, CX
                Mov     BX, [SI]
                Or      AX, INIT2
                Call    WriteData

                Add     SI, 2

                Dec     CX
                JNS     InitSetAWE2

                Mov     CX, 31

InitSetAWE3:
                Mov     AX, 31
                Sub     AX, CX
                Mov     BX, [SI]
                Or      AX, INIT3
                Call    WriteData

                Add     SI, 2

                Dec     CX
                JNS     InitSetAWE3

                Mov     CX, 31

InitSetAWE4:
                Mov     AX, 31
                Sub     AX, CX
                Mov     BX, [SI]
                Or      AX, INIT4
                Call    WriteData

                Add     SI, 2

                Dec     CX
                JNS     InitSetAWE4

                Ret

EndP            InitSetAWE

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

Proc            InitAWE

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     DX, BasePort

                Mov     AX, HWCF1
                Mov     BX, 59h
                Call    WriteData

                Mov     AX, CFG2
                Mov     BX, 20h
                Call    WriteData

                Mov     CX, 31

InitAwe1:
                Mov     BX, 80h
                Mov     AX, DCYSUSV
                Or      AX, CX
                Call    WriteData

                Xor     EBX, EBX
                Mov     AX, ENVVOL
                Or      AX, CX
                Call    WriteData

                Mov     AX, ENVVAL
                Or      AX, CX
                Call    WriteData

                Mov     AX, SUSDCY
                Or      AX, CX
                Call    WriteData

                Mov     AX, ATKHLDV
                Or      AX, CX
                Call    WriteData

                Mov     AX, LFO1VAL
                Or      AX, CX
                Call    WriteData

                Mov     AX, HLDATK
                Or      AX, CX
                Call    WriteData

                Mov     AX, LFO2VAL
                Or      AX, CX
                Call    WriteData

                Mov     AX, IP
                Or      AX, CX
                Call    WriteData

                Mov     AX, IFATN
                Or      AX, CX
                Call    WriteData

                Mov     AX, PEFE
                Or      AX, CX
                Call    WriteData

                Mov     AX, FMMOD
                Or      AX, CX
                Call    WriteData

                Mov     AX, TREMFRQ
                Or      AX, CX
                Call    WriteData

                Mov     AX, FM2FRQ2
                Or      AX, CX
                Call    WriteData

                Mov     AX, PTRX
                Or      AX, CX
                Call    WriteData

                Mov     AX, VTFT
                Or      AX, CX
                Call    WriteData

                Mov     AX, PSST
                Or      AX, CX
                Call    WriteData

                Mov     AX, CSL
                Or      AX, CX
                Call    WriteData

                Mov     AX, CCCA
                Or      AX, CX
                Call    WriteData

                Dec     CX
                JNS     InitAWE1

                Mov     CX, 31

InitAWE8:
                Mov     AX, CPF
                Or      AX, CX
                Call    WriteData

                Mov     AX, CVCF
                Or      AX, CX
                Call    WriteData

                Dec     CX
                JNS     InitAWE8
                                        ; Initialise still...
                Mov     AX, SMALR
                Call    WriteData

                Mov     AX, SMARR
                Call    WriteData

                Mov     AX, SMALW
                Call    WriteData

                Mov     AX, SMARW
                Call    WriteData

                Mov     SI, Offset InitTable1
                Call    InitSetAWE

                                        ;  Wait for 1024 sample periods
                Mov     AX, WC
                Call    ReadData

                Mov     BX, AX
                Mov     CX, AX
                Add     CX, 400h        ; 1024
                Cmp     BX, CX
                JB      InitAWE3

InitAWE4:
                Mov     AX, WC
                Call    ReadData
                Cmp     AX, CX
                JA      InitAWE4

InitAWE3:
                Mov     AX, WC
                Call    ReadData
                Cmp     AX, CX
                JB      InitAWE3

                Mov     SI, Offset InitTable2
                Call    InitSetAWE

                Mov     SI, Offset InitTable3
                Call    InitSetAWE

                Mov     AX, HWCF4
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, HWCF5
                Mov     EBX, 83h
                Call    WriteData

                Mov     AX, HWCF6
                Mov     EBX, 8000h
                Call    WriteData

                Mov     SI, Offset InitTable4
                Call    InitSetAWE

                Mov     AX, HWCF3
                Mov     BX, 4
                Call    WriteData

                Ret

EndP            InitAWE
                Assume DS:Nothing

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

Proc            InitDRAMRefresh

                Mov     AX, DCYSUSV+1Eh
                Mov     BX, 80h
                Call    WriteData

                Mov     AX, DCYSUSV+1Fh
                Call    WriteData

;

                Mov     AX, VTFT+1Eh
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CVCF+1Eh
                Call    WriteData

                Mov     AX, VTFT+1Fh
                Call    WriteData

                Mov     AX, CVCF+1Fh
                Call    WriteData

;

                Mov     AX, PTRX+1Eh
                Call    WriteData

                Mov     AX, CPF+1Eh
                Call    WriteData

                Mov     AX, PTRX+1Fh
                Call    WriteData

                Mov     AX, CPF+1Fh
                Call    WriteData

;

                Mov     AX, PSST+1Eh
                Call    WriteData
                Mov     AX, PSST+1Fh
                Call    WriteData

                Mov     BX, 0FFFFh
                Mov     AX, CSL+1Eh
                Call    WriteData
                Mov     AX, CSL+1Fh
                Call    WriteData

                Xor     BX, BX
                Mov     AX, CCCA+1Eh
                Call    WriteData
                Mov     AX, CCCA+1Fh
                Call    WriteData

                Ret

EndP            InitDRAMRefresh
                Assume DS:Nothing

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

Proc            ResetDSP Far            ; AX = Port

                Push    AX
                Push    CX
                Push    DX

                Mov     DX, AX
                Add     DL, 6
                Mov     AL, 1
                Out     DX, AL

                In      AL, DX
                In      AL, DX
                In      AL, DX
                In      AL, DX

                Xor     AL, AL
                Out     DX, AL

                Add     DL, 8
                Mov     CX, 200

ResetDSP1:
                In      AL, DX
                Test    AL, AL
                JS      ResetDSP2
                Loop    ResetDSP1
                Jmp     ResetDSP3

ResetDSP2:
                Sub     DL, 4
                In      AL, DX
                Cmp     AL, 0AAh
                JE      ResetDSP4
                Add     DL, 4
                Loop    ResetDSP1

ResetDSP3:
                StC

ResetDSP4:
                Pop     DX
                Pop     CX
                Pop     AX
                Ret

EndP            ResetDSP

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

Proc            SBGetRegister

                Out     DX, AL
                Inc     DX
                In      AL, DX
                Dec     DX

                Ret

EndP            SBGetRegister

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

Proc            SBIn            ; DX = 2xEh, returns AL

SBIn1:
                In      AL, DX

                ShR     AL, 7
                LoopZ   SBIn

;                Test    AL, AL
;                JNS     SBIn1

                Add     DL, 0Ah-0Eh     ; DX = 2xAh -> Data read port
                In      AL, DX
                Add     DL, 0Eh-0Ah

                Ret

EndP            SBIn

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

Proc            DetectCard Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     Forced, AL

                Mov     DX, BasePort
                Cmp     DX, 0FFFFh
                JE      DetectCard1

                Cmp     DX, 620h
                JB      DetectCard3
                Cmp     DX, 680h
                JA      DetectCard3

                Call    TestAWE
                JNC     DetectCardFound
                Ret

DetectCard1:
                Mov     DX, 620h

DetectCard2:
                Call    TestAWE
                JNC     DetectCardFound

                Add     DL, 20h
                Cmp     DL, 80h
                JBE     DetectCard2

DetectCard3:
                StC
                Ret

DetectCardFound:
                Mov     BasePort, DX

                                ; Initialise AWE 32
                Call    InitAWE
                Call    InitDRAMRefresh

                                ; Detect amount of RAM.

                Mov     DX, BasePort
                Mov     CX, 29

DetectCardMemory1:
                Mov     AX, DCYSUSV
                Or      AX, CX
                Mov     BX, 80h
                Call    WriteData

                Mov     AX, VTFT
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CVCF
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, PTRX
                Or      AX, CX
                Mov     EBX, 40000000h
                Call    WriteData

                Mov     AX, CPF
                Or      AX, CX
                Mov     EBX, 40000000h
                Call    WriteData

                Mov     AX, PSST
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CSL
                Or      AX, CX
                Xor     EBX, EBX
                Call    WriteData

                Mov     AX, CCCA
                Or      AX, CX
                Mov     EBX, 4000000h   ; Left read

                Test    CL, 2
                JZ      DetectCardMemory2

                Mov     EBX, 6000000h   ; Left write

DetectCardMemory2:
                Call    WriteData

                Dec     CX
                JNS     DetectCardMemory1

                Xor     EDI, EDI                ; Amount of memory stored in
                                                ; EDI

                Mov     AX, SMALW
                Mov     EBX, 200000h
                Call    WriteData

                Mov     AX, SMLD
                Mov     BX, 0FFFFh
                Call    WriteData

                Mov     AX, SMLD
                Mov     BX, 5555h
                Call    WriteData

                Mov     AX, SMLD
                Mov     BX, 0AAAAh
                Call    WriteData

                Mov     AX, SMALR
                Mov     EBX, 200000h
                Call    WriteData

                Mov     AX, SMLD
                Call    ReadData

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 0FFFFh
                JNE     DetectCardMemory6

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 5555h
                JNE     DetectCardMemory6

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 0AAAAh
                JNE     DetectCardMemory6

                Mov     EDI, 20000h

DetectCardMemory3:                      ; Set read/write addresses..
                Mov     AX, SMALW
                Mov     EBX, EDI
                Add     EBX, 200000h
                Call    WriteData

                Mov     AX, SMLD
                Mov     BX, 5555h
                Call    WriteData

                Mov     AX, SMLD
                Mov     BX, 0AAAAh
                Call    WriteData

                Mov     AX, SMALR
                Mov     EBX, 200000h
                Call    WriteData

                Mov     AX, SMLD
                Call    ReadData

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 0FFFFh
                JNE     DetectCardMemory5

                Mov     AX, SMALR
                Mov     EBX, EDI
                Add     EBX, 200000h
                Call    WriteData

                Mov     AX, SMLD
                Call    ReadData

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 5555h
                JNE     DetectCardMemory5

                Mov     AX, SMLD
                Call    ReadData
                Cmp     AX, 0AAAAh
                JNE     DetectCardMemory5

DetectCardMemory4:
                Add     EDI, 20000h
                Cmp     EDI, 0E00000h
                JB      DetectCardMemory3

DetectCardMemory5:
                Cmp     EDI, 0DFFFE0h
                JB      DetectCardMemory7

                Mov     EDI, 0DFFFE0h

DetectCardMemory7:
                Test    EDI, EDI
                JZ      DetectCardMemory6

                Mov     AWEMemory, EDI

                Mov     MixerPort, 210h
                Mov     AX, BasePort
                Sub     AX, 400h
                Call    ResetDSP
                JNC     DetectMixer2

DetectMixer1:
                Mov     AX, MixerPort
                Call    ResetDSP
                JNC     DetectMixer2

DetectMixer3:
                Add     MixerPort, 10h
                Cmp     MixerPort, 280h
                JBE     DetectMixer1

                Mov     DX, BasePort
                Sub     DX, 400h
                Mov     MixerPort, DX

                Jmp     DetectCard4

DetectMixer2:                            ; OK... DSP found.
                                        ; Get DSP version
                Mov     DX, AX
                Add     DL, 0Ch         ; 2xCh -> Data ready to send...

                Mov     CX, 200

DetectMixerLoop1:
                In      AL, DX
;                Test    AL, AL
;                JS      DetectMixerLoop1
                ShR     AL, 7
                LoopNZ  DetectMixerLoop1

                Mov     AL, 0E1h        ; Get DSP version command
                Out     DX, AL

                Add     DL, 0Eh-0Ch     ; DX = 2xEh -> Data available status

                Call    SBIn
                Mov     AH, AL          ; AH = Major version number
                Call    SBIn            ; AL = Minor version number

                Cmp     AX, 40Ch        ; SB DSP = 4.12+
                JB      DetectMixer3

                Sub     DL, 0Eh
                Mov     MixerPort, DX

DetectCard4:
                Mov     SB16BasePort, DX
                Add     MixerPort, 4    ; Mixerport

                Add     DL, 4

                Mov     AL, 30h
                Call    SBGetRegister
                ShR     AL, 3
                Mov     VolumeTable, AL

                Mov     AL, 31h
                Call    SBGetRegister
                ShR     AL, 3
                Mov     [VolumeTable+1], AL

                Mov     AL, 44h
                Call    SBGetRegister
                ShR     AL, 4
                Mov     [VolumeTable+2], AL

                Mov     AL, 45h
                Call    SBGetRegister
                ShR     AL, 4
                Mov     [VolumeTable+3], AL

                Mov     AL, 46h
                Call    SBGetRegister
                ShR     AL, 4
                Mov     [VolumeTable+4], AL

                Mov     AL, 47h
                Call    SBGetRegister
                ShR     AL, 4
                Mov     [VolumeTable+5], AL

                Mov     DX, MixerPort
                Mov     AX, 0F834h
                Out     DX, AX

                Mov     AL, 35h
                Out     DX, AX

                Mov     DX, MixerPort
                Mov     AL, 80h         ; IRQ select
                Out     DX, AL
                Inc     DL              ; 2x5h = Mixer data port

                In      AL, DX

                Dec     DL

                Mov     BX, IRQ
                Cmp     BX, 0FFFFh
                JE      DetectCardIRQ1
                Cmp     Forced, 0
                JE      DetectCardIRQ1

                Mov     AH, 11h
                Cmp     BL, 2
                JE      SetCardIRQ1
                Cmp     BL, 9
                JE      SetCardIRQ1

                Mov     AH, 12h
                Cmp     BL, 5
                JE      SetCardIRQ1

                Mov     AH, 14h
                Cmp     BL, 7
                JE      SetCardIRQ1

                Mov     AH, 18h
                Cmp     BL, 10
                JE      SetCardIRQ1

                Jmp     NoWindows

SetCardIRQ1:
                Mov     AL, 80h
                Out     DX, AL
                Inc     DL
                Mov     AL, AH
                Out     DX, AL
                Dec     DL
                Jmp     DetectCard6

DetectCardIRQ1:
                Mov     BX, 2
                Test    AL, 1
                JNZ     DetectCardIRQ2

                Mov     BL, 5
                Test    AL, 2
                JNZ     DetectCardIRQ2

                Mov     BL, 7
                Test    AL, 4
                JNZ     DetectCardIRQ2

                Mov     BL, 10
                Test    AL, 8
                JNZ     DetectCardIRQ2

                StC
                Ret

DetectCardIRQ2:
                Cmp     IRQ, 0FFFFh
                JE      DetectCardIRQ3

                Cmp     BX, IRQ
                JE      DetectCard6

                StC
                Ret

DetectCardIRQ3:
                Mov     IRQ, BX

DetectCard6:
                Mov     AL, 81h
                Out     DX, AL
                Inc     DX
                In      AL, DX
                Dec     DX

                And     AL, 11
                Xor     BX, BX
                Cmp     AL, 1
                JE      DetectCardDMA

                Inc     BX
                Cmp     AL, 2
                JE      DetectCardDMA

                Inc     BX
                Inc     BX
                Cmp     AL, 8
                JNE     NoWindows

DetectCardDMA:
                Mov     DMA, BX

DetectCardWindows:
                Mov     AX, 1600h               ; Windows detection.
                Int     2Fh
                Test    AL, 7Fh
                JZ      NoWindows

                Mov     SBIRQMode, 1

NoWindows:
                Mov     EAX, 'Jeff'
                ClC
                Ret

DetectCardMemory6:
                StC
                Ret

EndP            DetectCard
                Assume DS:Nothing

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

Proc            SetSamplingRate
                Assume DS:Driver

                PushA
                Push    ES

                Mov     AX, SB16BasePort
                Call    ResetDSP

; Set dma
                Mov     BX, DMABuffer
                Xor     AX, AX
                Mov     DX, DMA
                Mov     DI, 512
                Call    SetDMA

                LES     DI, ActualDMAPtr
                Xor     AX, AX
                Mov     CX, 256
                Rep     StosW

                Mov     DX, SB16BasePort
                Add     DL, 0Ch

;                Mov     AL, 0D3h        ; Turn off speaker
;                Call    SBOut
                                         ; Set mixing frequency
                Mov     AL, 40h
                Call    SBOut
                Mov     AL, 0EAh
                Call    SBOut            ; 45454Hz
;                Mov     AL, 211
;                Call    SBOut           ; 22222 Hz.

                Mov     AL, 0C6h
                Call    SBOut
                Xor     AL, AL
                Call    SBOut
                Mov     AX, BlockLength
                Dec     AX
                Call    SBOut
                Mov     AL, AH
                Call    SBOut

                Pop     ES
                PopA
                Ret

EndP            SetSamplingRate
                Assume DS:Nothing

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

Proc            SetMIDIIRQ

                PushAD
                Push    DS
                Push    ES

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Xor     AX, AX
                Mov     ES, AX

                Mov     DI, IRQ
                ShL     DI, 2
                Add     DI, Offset IRQData
                Mov     BX, [DI]

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

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

                Mov     AX, IMR
                And     AX, [DI+2]

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

                Pop     ES
                Pop     DS
                PopAD

                Ret

EndP            SetMIDIIRQ

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

Proc            SetIRQ
                        Assume DS:Driver

                PushAD
                Push    ES

                Xor     AX, AX
                Mov     ES, AX

                Mov     DI, IRQ
                ShL     DI, 2
                Add     DI, Offset IRQData
                Mov     BX, [DI]

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

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

                Mov     AX, IMR
                And     AX, [DI+2]

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

                Pop     ES
                PopAD

                Ret

EndP            SetIRQ
                Assume DS:Nothing

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

Proc            ResetIRQ

                PushAD
                Push    DS
                Push    ES

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Xor     AX, AX
                Mov     ES, AX

                Mov     DI, IRQ
                ShL     DI, 2
                Mov     BX, [IRQData+DI]

                Mov     EAX, OldIRQHandler
                Mov     [ES:BX], EAX

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

                Pop     ES
                Pop     DS
                PopAD

                Ret

EndP            ResetIRQ
                Assume DS:Nothing

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

Proc            InitMIDI
                Assume DS:Driver

                Mov     DX, 330h
                Call    DetectUART
                JC      DetectMIDI1

                Mov     MIDIPort, 330h
                Jmp     DetectMIDIEnd

DetectMIDI1:
                Mov     DX, 300h
                Call    DetectUART
                JC      DetectMIDIEnd

                Mov     MIDIPort, 300h

DetectMIDIEnd:
                Ret

EndP            InitMIDI
                Assume DS:Nothing

;ÄÄ 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
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

FControlWord    DW      0

Proc            InitSound Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

                FNInit                          ; Initialise floating point
                FNSTCW  FControlWord
                And     FControlWord, 0F0FFh
                FLDCW   FControlWord

                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     AX, CS
                Mov     DriverSegment1, AX
                Mov     DriverSegment2, AX
                Mov     DriverSegment3, AX
                Mov     DriverSegment4, AX
                Mov     DriverSegment5, AX
                Mov     DriverSegment6, AX
                Mov     DriverSegment7, AX
                Mov     DriverSegment8, AX

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

                Cmp     SBIRQMode, 0
                JE      InitSound1

                Cmp     DMABuffer, 0
                JNE     InitSound3

                Mov     AH, 48h
                Mov     BX, 1024/16
                Int     21h
                JNC     InitSound4

                Mov     SBIRQMode, 0
                Jmp     InitSound1

InitSound4:
                Mov     DMABuffer, AX

InitSound3:
                Call    SetIRQ
                Call    GetTempo
                Call    SetTempo
                Call    ResetMemory
                Call    SetSamplingRate

                Call    InitMIDI

                Mov     SI, Offset AWE32Msg2
                Mov     AX, BasePort

                Mov     BX, IRQ
                Mov     CX, DMA

                Ret

InitSound1:
                Call    SetMIDIIRQ
                Call    GetTempo
                Call    SetTempo
                Call    ResetMemory

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

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

                ClI

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

                StI

InitSound2:
                Call    InitMIDI

                Mov     SI, Offset AWE32Msg
                Mov     AX, BasePort

                Mov     EBX, AWEMemory
                SHR     EBX, 9

                Ret

EndP            InitSound
                Assume DS:Nothing

;ÄÄ ReInitSound ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; Reinitialises sound output
; Initiates sound output
;
; Parameters: AX = number of channels.
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            ReInitSound Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     SI, Offset AWE32ReinitMsg
                Mov     BX, 40
                Call    SetInfoLine

                Call    ResetUART
                Call    InitAWE
                Call    InitDRAMRefresh

                Cmp     SBIRQMode, 0
                JE      ReInitSound1

                Call    ResetIRQ
                Call    SetIRQ
                Call    SetSamplingRate
                Call    ReinitUART
                Ret

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

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

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

                Call    ResetIRQ
                Call    SetMIDIIRQ
                Call    ReinitUART

                Ret

EndP            ReInitSound
                Assume DS:Nothing

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

Proc            UnInitSound Far


                Call    GotoHomeDirectory

                                        ; Now to save config into driver file.
                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     AX, 3D02h       ; Read write access
                Mov     DX, Offset DriverName
                Int     21h
                JC      SaveConfig2

                Mov     BX, AX

                Mov     AX, 4200h
                Xor     CX, CX
                Mov     DX, Offset CONFIGURATIONOFFSET
                Int     21h
                JC      SaveConfig1

                Mov     AH, 40h
                Mov     CX, CONFIGSIZE
                Mov     DX, Offset Chorus
                Int     21h

SaveConfig1:
                PushF
                Mov     AH, 3Eh
                Int     21h
                PopF

SaveConfig2:
                Call    ResetIRQ

                Cmp     SBIRQMode, 0
                JE      UnInitSound1

                Mov     DX, SB16BasePort
                Add     DL, 0Ch

                Call    ResetUART

                Mov     AX, SB16BasePort
                Call    ResetDSP

                Call    InitAWE

                Push    ES
                Mov     AH, 49h
                Mov     ES, DMABuffer
                Int     21h
                Pop     ES

                Ret

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

                Mov     AX, SB16BasePort
                Call    ResetDSP
                Call    ResetUART
                Call    InitAWE
                Call    ResetIRQ
                Ret

EndP            UnInitSound
                Assume DS:Nothing

;ÄÄ Poll ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
; This procedure is called as often as possible by IT.EXE
; AX = Playmode (0 for nothing in particular, 1 = pattern, 2 = song)
;
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            Poll Far

                Push    CS
                Pop     DS
                        Assume DS:Driver

Poll1:
                Call    [UARTBufferEmpty]
                JNC     PollEnd

                Xor     BX, BX

                ClI

                Mov     BL, MIDIBufferHead
                Cmp     BL, MIDIBufferTail
                JZ      PollEnd         ; Nothing in queue

                Inc     BL
                Mov     AL, [MIDIBuffer+BX]
                Mov     MIDIBufferHead, BL

                Call    [UARTSend]
                Jmp     Poll1

PollEnd:
                StI
                Ret

EndP            Poll
                Assume DS:Nothing

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

Proc            SetTempo Far

                Push    AX
                Push    BX
                Push    DX

                Cmp     CS:SBIRQMode, 0
                JE      SetTempo1
                                        ; BlockLength = 55555/BPM
                                        ; BlockLength = 45454*5/2
                                        ;             = 113635
                Mov     AX, 48099
                Mov     DX, 1

                Div     BX
                Dec     AX
                Dec     AX
                Mov     CS:BlockLength, AX

;                Mov     DX, SB16BasePort
;                Add     DL, 0Ch

                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     CS:AWEUpdateTimer, 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
;
; Returns: **Carry set if NO error**
;          **Carry clear if error**
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Proc            LoadSample Far
                                        ; if no sample, then do nothing
                                        ; MemoryUsed = length of sample
                                        ; if sustain loop, then use sustain
                                        ;  loop information
                                        ; if no sustain loop, then use loop
                                        ;  information
                                        ; if no loop or sustain loop,
                                        ;  memoryused += 16; (16 zero samples
                                        ;                     at the end)
                                        ;
                PushAD
                Push    DS
                Push    ES
                Push    FS

                Push    AX

                ClI

                Call    EnableRAM       ; Enable access to DRAM.

                                        ; Set destination address
                Mov     AX, SMALW
                Mov     EBX, CS:AWEMemoryUsed
                Add     EBX, 200000h
                Call    WriteData

                Mov     DX, CS:BasePort
                Add     DX, 802h        ; Index
                Mov     AX, 32+26
                Out     DX, AX

                Pop     AX

                Mov     FS, CS:SongDataArea
                LEA     DI, [EAX*4+EAX]
                ShL     DI, 2
                Add     DI, Offset AWEDataTable-20

                Mov     ECX, -1

                Mov     DWord Ptr [CS:DI], ECX    ; Start
                Mov     DWord Ptr [CS:DI+4], ECX  ; Loop start
                Mov     DWord Ptr [CS:DI+8], ECX  ; Loop end
                Mov     DWord Ptr [CS:DI+12], ECX ; Size occupied
                Mov     DWord Ptr [CS:DI+16], ECX ; Size occupied

                Mov     BP, AX
                Add     BP, BP
                Mov     BP, [FS:64910+BP]

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

                JZ      LoadSample1

                        ; 16 bit

                Mov     CS:LoadSampleFuncF, Offset Load16BitSamplesForwards
                Mov     CS:LoadSampleFuncB, Offset Load16BitSamplesBackwards

                Jmp     LoadSample2

LoadSample1:            ; 8 bit
                Mov     CS:LoadSampleFuncF, Offset Load8BitSamplesForwards
                Mov     CS:LoadSampleFuncB, Offset Load8BitSamplesBackwards

LoadSample2:
                Mov     AL, [FS:BP+12h]
                Test    AL, 30h                 ; Loop or sustain loop?
                JZ      LoadSampleNoLoop

                Mov     EBX, [FS:BP+34h]        ; Loop begin
                Mov     EDX, [FS:BP+38h]        ; Loop end
                Test    AL, 20h                 ; Sustain loop?
                JZ      LoadSample3

                ShR     AL, 1
                Mov     EBX, [FS:BP+40h]
                Mov     EDX, [FS:BP+44h]
                Jmp     LoadSample3

LoadSampleError:
                ClC
                Jmp     LoadSampleEnd

LoadSampleNoError:
                StC

LoadSampleEnd:
                StI
                Pop     FS
                Pop     ES
                Pop     DS
                PopAD

                Ret

LoadSampleNoLoop:                       ; ECX contains length of sample
                Mov     EAX, ECX
                Mov     EDX, AWEMemoryUsed
                Mov     EBX, AWEMemory
                Sub     EBX, EDX                ; EBX = AWEMemory remaining

                Mov     CL, Compress
                ShR     EAX, CL                 ; Compress sample
                Add     EAX, 16                 ; zeroes at end of sample

                Cmp     EAX, EBX
                JA      LoadSampleError

                Mov     ECX, EAX
                Add     AWEMemoryUsed, EAX      ; Record memory as used
                Mov     [CS:DI+12], EAX

                Add     EDX, 200000h

                Sub     ECX, 16                 ; Number of samples to transfer
                Mov     [CS:DI], EDX
                Add     EDX, ECX
                Mov     [CS:DI+4], EDX             ; Loop start
                Add     EDX, 14
                Mov     [CS:DI+8], EDX             ; Loop end

                                        ; Now to transfer samples to AWE32
                Call    [CS:LoadSampleFuncF]
                                        ; Now to shove a whole lot of zeroes
                Xor     AX, AX
                Mov     CX, 16

LoadSampleNoLoop2:
                Out     DX, AX
                Loop    LoadsampleNoLoop2

                Jmp     LoadSampleNoError

LoadSample3:                            ; OK... EBX = loop start
                                        ;       EDX = loop end
                                        ;        AL&40h = ping pong
                Test    AL, 40h
                JNZ     LoadSamplePingPong

                Mov     CL, Compress

                Push    EBX

                ShR     EDX, CL
                ShR     EBX, CL
                Mov     EAX, EDX
                Add     EAX, 2          ; For loop fixing

                Mov     ECX, AWEMemory
                Sub     ECX, AWEMemoryUsed      ; ECX = AWEMemoryRemaining

                Cmp     EAX, ECX
                Pop     ECX
                JA      LoadSampleError         ; Sufficient memory?
                Push    ECX

                Mov     ECX, EAX
                Mov     EAX, AWEMemoryUsed
                Add     AWEMemoryUsed, ECX
                Mov     [CS:DI+12], ECX

                Sub     ECX, 2

                Add     EAX, 200000h
                Mov     [CS:DI], EAX

                Add     EDX, EAX
                Add     EAX, EBX

                Mov     [CS:DI+4], EAX
                Mov     [CS:DI+8], EDX

                Call    [CS:LoadSampleFuncF]
                                                ; Now to fix loop.. 1 extra
                                                ; sample.

                Pop     ESI                     ; Loop start
                Test    Byte Ptr [FS:BP+12h], 2
                JZ      LoadSampleForwards1

                Add     ESI, ESI

LoadSampleForwards1:
                Int     3

                Mov     ECX, 2
                Call    [CS:LoadSampleFuncF]

                Jmp     LoadSampleNoError

LoadSamplePingPong:
                Mov     CL, Compress
                ShR     EDX, CL
                ShR     EBX, CL

                Mov     EAX, EDX
                Add     EAX, EDX
                Sub     EAX, EBX
                Inc     EAX

                Mov     ECX, AWEMemory
                Sub     ECX, AWEMemoryUsed

                Cmp     EAX, ECX
                JA      LoadSampleError

                Mov     [CS:DI+12], EAX
                Mov     ECX, AWEMemoryUsed
                Add     AWEMemoryUsed, EAX

                Add     ECX, 200000h
                Add     EAX, ECX
                Dec     EAX

                Mov     [CS:DI], ECX
                Add     ECX, EBX
                Mov     [CS:DI+4], ECX
                Mov     [CS:DI+8], EAX

                Mov     EAX, [CS:DI]
                Add     EAX, EDX
                Mov     [CS:DI+16], EAX

                Mov     ECX, EDX
                Sub     EDX, EBX
                Push    EDX

                Call    [CS:LoadSampleFuncF]

                Pop     ECX
                Inc     ECX

                Call    [CS:LoadSampleFuncB]

                Jmp     LoadSampleNoError

EndP            LoadSample

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

Proc            ReleaseSample Far

                PushAD

                LEA     DI, [EAX*4+EAX]         ; DI = AX * 5
                ShL     DI, 2
                Add     DI, Offset AWEDataTable

                Mov     EBX, [CS:DI+12]
                Mov     EAX, CS:AWEMemoryUsed
                Sub     EAX, EBX
                Add     EAX, 200000h
                Cmp     EAX, [CS:DI]
                JNE     ReleaseSample1

                Sub     AWEMemoryUsed, EBX
ReleaseSample1:
                Mov     EAX, -1
                Mov     [CS:DI], EAX
                Mov     [CS:DI+4], EAX
                Mov     [CS:DI+8], EAX
                Mov     [CS:DI+12], EAX

                PopAD
                Ret

EndP            ReleaseSample

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

Proc            ResetMemory Far

                Push    CS
                Pop     ES

                Xor     EAX, EAX
                Mov     CS:AWEMemoryUsed, EAX

                Mov     DI, Offset AWEDataTable
                Mov     CX, 1000
                Mov     AX, 0FFFFh
                Rep     StosW

                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     SI, Offset AWE32Status

                Mov     EAX, AWEMemory
                Sub     EAX, AWEMemoryUsed
                SHR     EAX, 9

                ClC
                Ret

EndP            GetStatus

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

Proc            SoundCardScreen Far

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

                ClC
                Ret

EndP            SoundCardScreen

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

Proc            GetVariable Far         ; Returns AX, given DI

                Xor     AH, AH
                Mov     AL, [CS:VolumeTable+DI]
                Ret

EndP            GetVariable

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

Proc            SetVariable Far         ; Given AX, DI

                Push    DS
                Push    DX

                Push    CS
                Pop     DS
                        Assume DS:Driver

                Mov     [VolumeTable+DI], AL

                Mov     DX, MixerPort
                Mov     AL, 30h
                Mov     AH, [VolumeTable]
                ShL     AH, 3
                Out     DX, AX

                Mov     AL, 31h
                Mov     AH, [VolumeTable+1]
                ShL     AH, 3
                Out     DX, AX

                Mov     AL, 44h
                Mov     AH, [VolumeTable+2]
                ShL     AH, 4
                Out     DX, AX

                Mov     AL, 45h
                Mov     AH, [VolumeTable+3]
                ShL     AH, 4
                Out     DX, AX

                Mov     AL, 46h
                Mov     AH, [VolumeTable+4]
                ShL     AH, 4
                Out     DX, AX

                Mov     AL, 47h
                Mov     AH, [VolumeTable+5]
                ShL     AH, 4
                Out     DX, AX

                Pop     DX
                Pop     DS
                Ret

EndP            SetVariable
                Assume DS:Nothing

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

EndDriver:

;********  Provided Variable Table *************

MaxNumberOfChannels     DW      30      ; Maximum number of channels the
                                        ; driver can handle.
StopAfterPlay           DW      0
DefaultChannels         DW      30
DriverFlags             DW      1       ; MIDI Out supported

                        DW      4 Dup (0)

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

ProvidedTableStart:

        DW      Offset DetectCard

        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      ; For MIDI Out

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

EndS

End
